From 44639a6423c03552a3c0faafab27ef8f395f73a6 Mon Sep 17 00:00:00 2001 From: Simon Robertshaw Date: Thu, 19 Jan 2012 13:44:59 +0000 Subject: Some folder changes, started search and client diff --git a/Makefile b/Makefile index 4d20bfc..43fa157 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ OBJS += $(patsubst src/%.cpp,build/obj/powder.exe/%.o,$(SOURCES)) FOLDERS := $(sort $(dir $(OBJS))) -CFLAGS := -Wno-deprecated -Wno-deprecated-declarations -Isrc/ -Idata/ -DWIN32 -DWINCONSOLE -OFLAGS := -O3 -ffast-math -ftree-vectorize -funsafe-math-optimizations -msse2 -fkeep-inline-functions +CFLAGS := -w -Isrc/ -Idata/ -DWIN32 -DWINCONSOLE +OFLAGS := -fkeep-inline-functions #-O3 -ffast-math -ftree-vectorize -funsafe-math-optimizations -msse2 LFLAGS := -lmingw32 -lregex -lws2_32 -lSDLmain -lpthread -lSDL -lm -lbz2 # -mwindows CFLAGS += $(OFLAGS) diff --git a/PowderToy++.files b/PowderToy++.files index 5a30285..af47ebb 100644 --- a/PowderToy++.files +++ b/PowderToy++.files @@ -140,7 +140,6 @@ includes/Console.h includes/interface/Engine.h includes/interface/Platform.h src/interface/State.cpp -src/interface/Sandbox.cpp src/interface/Panel.cpp src/interface/Engine.cpp src/interface/ControlFactory.cpp @@ -290,7 +289,6 @@ src/elements/acid.cpp src/elements/acel.cpp src/interface/Window.h src/interface/State.h -src/interface/Sandbox.h src/interface/Point.h src/interface/Platform.h src/interface/Panel.h @@ -308,3 +306,23 @@ src/interface/Engine.cpp src/interface/ControlFactory.cpp src/interface/Component.cpp src/interface/Button.cpp +src/interface/SaveButton.h +src/interface/SaveButton.cpp +src/client/Client.h +src/client/Client.cpp +src/client/HTTP.h +src/client/HTTP.c +src/client/HTTP.cpp +src/client/MD5.cpp +src/client/MD5.h +src/search/Thumbnail.h +src/simulation/Simulation.h +src/simulation/Gravity.h +src/simulation/Elements.h +src/simulation/ElementGraphics.h +src/simulation/ElementFunctions.h +src/simulation/Element.h +src/simulation/Air.h +src/simulation/Simulation.cpp +src/simulation/Gravity.cpp +src/simulation/Air.cpp diff --git a/src/Air.cpp b/src/Air.cpp deleted file mode 100644 index 2d8d1b5..0000000 --- a/src/Air.cpp +++ /dev/null @@ -1,301 +0,0 @@ -#include -#include "Config.h" -#include "Air.h" -//#include -//#include -#include "gravity.h" - -/*float kernel[9]; - -float vx[YRES/CELL][XRES/CELL], ovx[YRES/CELL][XRES/CELL]; -float vy[YRES/CELL][XRES/CELL], ovy[YRES/CELL][XRES/CELL]; -float pv[YRES/CELL][XRES/CELL], opv[YRES/CELL][XRES/CELL]; -unsigned char bmap_blockair[YRES/CELL][XRES/CELL]; - -float cb_vx[YRES/CELL][XRES/CELL]; -float cb_vy[YRES/CELL][XRES/CELL]; -float cb_pv[YRES/CELL][XRES/CELL]; -float cb_hv[YRES/CELL][XRES/CELL]; - -float fvx[YRES/CELL][XRES/CELL], fvy[YRES/CELL][XRES/CELL]; - -float hv[YRES/CELL][XRES/CELL], ohv[YRES/CELL][XRES/CELL]; // For Ambient Heat */ - -void Air::make_kernel(void) //used for velocity -{ - int i, j; - float s = 0.0f; - for (j=-1; j<2; j++) - for (i=-1; i<2; i++) - { - kernel[(i+1)+3*(j+1)] = expf(-2.0f*(i*i+j*j)); - s += kernel[(i+1)+3*(j+1)]; - } - s = 1.0f / s; - for (j=-1; j<2; j++) - for (i=-1; i<2; i++) - kernel[(i+1)+3*(j+1)] *= s; -} -void Air::update_airh(void) -{ - int x, y, i, j; - float dh, dx, dy, f, tx, ty; - for (i=0; i0 && y+j0 && x+i=2 && i=2 && j0) - vy[y][x] -= airdiff/5000.0f; - } - ohv[y][x] = dh; - } - } - memcpy(hv, ohv, sizeof(hv)); -} - -void Air::update_air(void) -{ - int x, y, i, j; - float dp, dx, dy, f, tx, ty; - - for (y=0; y0 && y+j0 && x+i=2 && i=2 && j 256.0f) dp = 256.0f; - if (dp < -256.0f) dp = -256.0f; - if (dx > 256.0f) dx = 256.0f; - if (dx < -256.0f) dx = -256.0f; - if (dy > 256.0f) dy = 256.0f; - if (dy < -256.0f) dy = -256.0f; - - - switch (airMode) - { - default: - case 0: //Default - break; - case 1: //0 Pressure - dp = 0.0f; - break; - case 2: //0 Velocity - dx = 0.0f; - dy = 0.0f; - break; - case 3: //0 Air - dx = 0.0f; - dy = 0.0f; - dp = 0.0f; - break; - case 4: //No Update - break; - } - - ovx[y][x] = dx; - ovy[y][x] = dy; - opv[y][x] = dp; - } - memcpy(vx, ovx, sizeof(vx)); - memcpy(vy, ovy, sizeof(vy)); - memcpy(pv, opv, sizeof(pv)); - } -} -Air::Air() -{ - //Simulation should do this. - make_kernel(); -} diff --git a/src/Air.h b/src/Air.h deleted file mode 100644 index 8e4dc25..0000000 --- a/src/Air.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef AIR_H -#define AIR_H -#include "Config.h" - -class Simulation; - -class Air -{ -public: - int airMode; - //Arrays from the simulation - unsigned char (*bmap)[XRES/CELL]; - unsigned char (*emap)[XRES/CELL]; - float (*fvx)[XRES/CELL]; - float (*fvy)[XRES/CELL]; - // - float vx[YRES/CELL][XRES/CELL]; - float ovx[YRES/CELL][XRES/CELL]; - float vy[YRES/CELL][XRES/CELL]; - float ovy[YRES/CELL][XRES/CELL]; - float pv[YRES/CELL][XRES/CELL]; - float opv[YRES/CELL][XRES/CELL]; - float hv[YRES/CELL][XRES/CELL]; - float ohv[YRES/CELL][XRES/CELL]; // Ambient Heat - unsigned char bmap_blockair[YRES/CELL][XRES/CELL]; - float kernel[9]; - void make_kernel(void); - void update_airh(void); - void update_air(void); - Air(); -}; - -#endif diff --git a/src/Console.h b/src/Console.h index 657f935..8f7a072 100644 --- a/src/Console.h +++ b/src/Console.h @@ -5,7 +5,7 @@ #include #include "interface/Sandbox.h" -#include "Simulation.h" +#include "simulation/Simulation.h" class ConsoleCommand { diff --git a/src/Element.h b/src/Element.h deleted file mode 100644 index 449bf51..0000000 --- a/src/Element.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef ELEMENT_H -#define ELEMENT_H -// This header should be included by all files in src/elements/ - -#include -#include "Simulation.h" -#include "Renderer.h" -#include "ElementFunctions.h" -//#include "powder.h" -#include "Gravity.h" -#include "Misc.h" -#include "ElementGraphics.h" - -#endif diff --git a/src/ElementFunctions.h b/src/ElementFunctions.h deleted file mode 100644 index ef80b6f..0000000 --- a/src/ElementFunctions.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * ElementFunctions.h - * - * Created on: Jan 5, 2012 - * Author: Simon - */ - -#ifndef ELEMENTFUNCTIONS_H_ -#define ELEMENTFUNCTIONS_H_ -#include "Elements.h" - -int update_ACID(UPDATE_FUNC_ARGS); -int update_ANAR(UPDATE_FUNC_ARGS); -int update_AMTR(UPDATE_FUNC_ARGS); -int update_ARAY(UPDATE_FUNC_ARGS); -int update_BCLN(UPDATE_FUNC_ARGS); -int update_BCOL(UPDATE_FUNC_ARGS); -int update_BMTL(UPDATE_FUNC_ARGS); -int update_BRMT(UPDATE_FUNC_ARGS); -int update_BOMB(UPDATE_FUNC_ARGS); -int update_BOYL(UPDATE_FUNC_ARGS); -int update_BTRY(UPDATE_FUNC_ARGS); -int update_C5(UPDATE_FUNC_ARGS); -int update_CLNE(UPDATE_FUNC_ARGS); -int update_COAL(UPDATE_FUNC_ARGS); -int update_DEUT(UPDATE_FUNC_ARGS); -int update_DSTW(UPDATE_FUNC_ARGS); -int update_FOG(UPDATE_FUNC_ARGS); -int update_FRZW(UPDATE_FUNC_ARGS); -int update_FRZZ(UPDATE_FUNC_ARGS); -int update_FSEP(UPDATE_FUNC_ARGS); -int update_FUSE(UPDATE_FUNC_ARGS); -int update_FIRW(UPDATE_FUNC_ARGS); -int update_FWRK(UPDATE_FUNC_ARGS); -int update_GLAS(UPDATE_FUNC_ARGS); -int update_GLOW(UPDATE_FUNC_ARGS); -int update_GOO(UPDATE_FUNC_ARGS); -int update_HSWC(UPDATE_FUNC_ARGS); -int update_IRON(UPDATE_FUNC_ARGS); -int update_ICEI(UPDATE_FUNC_ARGS); -int update_ISZ(UPDATE_FUNC_ARGS); -int update_LCRY(UPDATE_FUNC_ARGS); -int update_MORT(UPDATE_FUNC_ARGS); -int update_NEUT(UPDATE_FUNC_ARGS); -int update_NPTCT(UPDATE_FUNC_ARGS); -int update_PCLN(UPDATE_FUNC_ARGS); -int update_PHOT(UPDATE_FUNC_ARGS); -int update_PIPE(UPDATE_FUNC_ARGS); -int update_PLNT(UPDATE_FUNC_ARGS); -int update_PLUT(UPDATE_FUNC_ARGS); -int update_PRTI(UPDATE_FUNC_ARGS); -int update_PRTO(UPDATE_FUNC_ARGS); -int update_PYRO(UPDATE_FUNC_ARGS); -int update_PUMP(UPDATE_FUNC_ARGS); -int update_QRTZ(UPDATE_FUNC_ARGS); -int update_RIME(UPDATE_FUNC_ARGS); -int update_SHLD1(UPDATE_FUNC_ARGS); -int update_SHLD2(UPDATE_FUNC_ARGS); -int update_SHLD3(UPDATE_FUNC_ARGS); -int update_SHLD4(UPDATE_FUNC_ARGS); -int update_SING(UPDATE_FUNC_ARGS); -int update_SLTW(UPDATE_FUNC_ARGS); -int update_SPAWN(UPDATE_FUNC_ARGS); -int update_SPAWN2(UPDATE_FUNC_ARGS); -int update_SPNG(UPDATE_FUNC_ARGS); -int update_SPRK(UPDATE_FUNC_ARGS); -int update_STKM(UPDATE_FUNC_ARGS); -int update_STKM2(UPDATE_FUNC_ARGS); -int update_SWCH(UPDATE_FUNC_ARGS); -int update_THDR(UPDATE_FUNC_ARGS); -int update_THRM(UPDATE_FUNC_ARGS); -int update_URAN(UPDATE_FUNC_ARGS); -int update_VINE(UPDATE_FUNC_ARGS); -int update_WARP(UPDATE_FUNC_ARGS); -int update_WATR(UPDATE_FUNC_ARGS); -int update_WIFI(UPDATE_FUNC_ARGS); -int update_WTRV(UPDATE_FUNC_ARGS); -int update_YEST(UPDATE_FUNC_ARGS); -int update_SOAP(UPDATE_FUNC_ARGS); -int update_O2(UPDATE_FUNC_ARGS); -int update_H2(UPDATE_FUNC_ARGS); -int update_NBHL(UPDATE_FUNC_ARGS); -int update_NWHL(UPDATE_FUNC_ARGS); -int update_MERC(UPDATE_FUNC_ARGS); -int update_PBCN(UPDATE_FUNC_ARGS); -int update_GPMP(UPDATE_FUNC_ARGS); -int update_CLST(UPDATE_FUNC_ARGS); -int update_DLAY(UPDATE_FUNC_ARGS); -int update_WIRE(UPDATE_FUNC_ARGS); -int update_GBMB(UPDATE_FUNC_ARGS); -int update_CO2(UPDATE_FUNC_ARGS); -int update_CBNW(UPDATE_FUNC_ARGS); -int update_STOR(UPDATE_FUNC_ARGS); -int update_BIZR(UPDATE_FUNC_ARGS); -int update_PVOD(UPDATE_FUNC_ARGS); -int update_CONV(UPDATE_FUNC_ARGS); -int update_CAUS(UPDATE_FUNC_ARGS); -int update_DEST(UPDATE_FUNC_ARGS); -int update_EMP(UPDATE_FUNC_ARGS); -int update_LIGH(UPDATE_FUNC_ARGS); -int update_FIGH(UPDATE_FUNC_ARGS); -int update_ELEC(UPDATE_FUNC_ARGS); -int update_ACEL(UPDATE_FUNC_ARGS); -int update_DCEL(UPDATE_FUNC_ARGS); -int update_BANG(UPDATE_FUNC_ARGS); -int update_IGNT(UPDATE_FUNC_ARGS); -int update_MISC(UPDATE_FUNC_ARGS); -int update_legacy_PYRO(UPDATE_FUNC_ARGS); -int update_legacy_all(UPDATE_FUNC_ARGS); -int run_stickman(playerst* playerp, UPDATE_FUNC_ARGS); -void STKM_init_legs(Simulation * sim, playerst* playerp, int i); -void STKM_interact(Simulation * sim, playerst* playerp, int i, int x, int y); - - -int graphics_FIRE(GRAPHICS_FUNC_ARGS); -int graphics_SMKE(GRAPHICS_FUNC_ARGS); -int graphics_PLSM(GRAPHICS_FUNC_ARGS); -int graphics_DEUT(GRAPHICS_FUNC_ARGS); -int graphics_PHOT(GRAPHICS_FUNC_ARGS); -int graphics_NEUT(GRAPHICS_FUNC_ARGS); -int graphics_LAVA(GRAPHICS_FUNC_ARGS); -int graphics_SPRK(GRAPHICS_FUNC_ARGS); -int graphics_QRTZ(GRAPHICS_FUNC_ARGS); -int graphics_CLST(GRAPHICS_FUNC_ARGS); -int graphics_CBNW(GRAPHICS_FUNC_ARGS); -int graphics_SPNG(GRAPHICS_FUNC_ARGS); -int graphics_LIFE(GRAPHICS_FUNC_ARGS); -int graphics_DUST(GRAPHICS_FUNC_ARGS); -int graphics_GRAV(GRAPHICS_FUNC_ARGS); -int graphics_WIFI(GRAPHICS_FUNC_ARGS); -int graphics_PRTI(GRAPHICS_FUNC_ARGS); -int graphics_PRTO(GRAPHICS_FUNC_ARGS); -int graphics_BIZR(GRAPHICS_FUNC_ARGS); -int graphics_PIPE(GRAPHICS_FUNC_ARGS); -int graphics_INVS(GRAPHICS_FUNC_ARGS); -int graphics_ACID(GRAPHICS_FUNC_ARGS); -int graphics_FILT(GRAPHICS_FUNC_ARGS); -int graphics_BRAY(GRAPHICS_FUNC_ARGS); -int graphics_SWCH(GRAPHICS_FUNC_ARGS); -int graphics_THDR(GRAPHICS_FUNC_ARGS); -int graphics_GLOW(GRAPHICS_FUNC_ARGS); -int graphics_LCRY(GRAPHICS_FUNC_ARGS); -int graphics_PCLN(GRAPHICS_FUNC_ARGS); -int graphics_PBCN(GRAPHICS_FUNC_ARGS); -int graphics_DLAY(GRAPHICS_FUNC_ARGS); -int graphics_HSWC(GRAPHICS_FUNC_ARGS); -int graphics_PVOD(GRAPHICS_FUNC_ARGS); -int graphics_STOR(GRAPHICS_FUNC_ARGS); -int graphics_PUMP(GRAPHICS_FUNC_ARGS); -int graphics_GPMP(GRAPHICS_FUNC_ARGS); -int graphics_HFLM(GRAPHICS_FUNC_ARGS); -int graphics_FIRW(GRAPHICS_FUNC_ARGS); -int graphics_BOMB(GRAPHICS_FUNC_ARGS); -int graphics_GBMB(GRAPHICS_FUNC_ARGS); -int graphics_COAL(GRAPHICS_FUNC_ARGS); -int graphics_STKM(GRAPHICS_FUNC_ARGS); -int graphics_STKM2(GRAPHICS_FUNC_ARGS); -int graphics_DEST(GRAPHICS_FUNC_ARGS); -int graphics_EMP(GRAPHICS_FUNC_ARGS); -int graphics_LIGH(GRAPHICS_FUNC_ARGS); -int graphics_FIGH(GRAPHICS_FUNC_ARGS); -int graphics_ELEC(GRAPHICS_FUNC_ARGS); -int graphics_WIRE(GRAPHICS_FUNC_ARGS); -int graphics_ACEL(GRAPHICS_FUNC_ARGS); -int graphics_DCEL(GRAPHICS_FUNC_ARGS); -int graphics_DEFAULT(GRAPHICS_FUNC_ARGS); - -#endif /* ELEMENTFUNCTIONS_H_ */ diff --git a/src/ElementGraphics.h b/src/ElementGraphics.h deleted file mode 100644 index a880e71..0000000 --- a/src/ElementGraphics.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef PGRAPHICS_H -#define PGRAPHICS_H - -#define PMODE 0x00000FFF -#define PMODE_NONE 0x00000000 -#define PMODE_FLAT 0x00000001 -#define PMODE_BLOB 0x00000002 -#define PMODE_BLUR 0x00000004 -#define PMODE_GLOW 0x00000008 -#define PMODE_SPARK 0x00000010 -#define PMODE_FLARE 0x00000020 -#define PMODE_LFLARE 0x00000040 -#define PMODE_ADD 0x00000080 -#define PMODE_BLEND 0x00000100 -#define PSPEC_STICKMAN 0x00000200 - -#define OPTIONS 0x0000F000 -#define NO_DECO 0x00001000 -#define DECO_FIRE 0x00002000 - -#define FIREMODE 0x00FF0000 -#define FIRE_ADD 0x00010000 -#define FIRE_BLEND 0x00020000 - -#define EFFECT 0xFF000000 -#define EFFECT_GRAVIN 0x01000000 -#define EFFECT_GRAVOUT 0x02000000 - -#define RENDER_EFFE OPTIONS | PSPEC_STICKMAN | EFFECT | PMODE_SPARK | PMODE_FLARE | PMODE_LFLARE -#define RENDER_FIRE OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_ADD | PMODE_BLEND | FIREMODE -#define RENDER_GLOW OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_GLOW | PMODE_ADD | PMODE_BLEND -#define RENDER_BLUR OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_BLUR | PMODE_ADD | PMODE_BLEND -#define RENDER_BLOB OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_BLOB | PMODE_ADD | PMODE_BLEND -#define RENDER_BASC OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_ADD | PMODE_BLEND -#define RENDER_NONE OPTIONS | PSPEC_STICKMAN | PMODE_FLAT - -#define COLOUR_HEAT 0x00000001 -#define COLOUR_LIFE 0x00000002 -#define COLOUR_GRAD 0x00000004 - -#define COLOUR_DEFAULT 0x00000000 - -#define DISPLAY_AIRC 0x00000001 -#define DISPLAY_AIRP 0x00000002 -#define DISPLAY_AIRV 0x00000004 -#define DISPLAY_AIRH 0x00000008 -#define DISPLAY_AIR 0x0000000F -#define DISPLAY_WARP 0x00000010 -#define DISPLAY_PERS 0x00000020 -#define DISPLAY_EFFE 0x00000040 - -#endif diff --git a/src/Elements.h b/src/Elements.h deleted file mode 100644 index 204460c..0000000 --- a/src/Elements.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Elements.h - * - * Created on: Jan 5, 2012 - * Author: Simon - */ - -//#ifndef ELEMENTS_H_ -//#define ELEMENTS_H_ - -//#include "Config.h" -//#include "Simulation.h" - -#define IPL -257.0f -#define IPH 257.0f -#define ITL MIN_TEMP-1 -#define ITH MAX_TEMP+1 -// no transition (PT_NONE means kill part) -#define NT -1 -// special transition - lava ctypes etc need extra code, which is only found and run if ST is given -#define ST PT_NUM - -#define R_TEMP 22 -#define MAX_TEMP 9999 -#define MIN_TEMP 0 -#define O_MAX_TEMP 3500 -#define O_MIN_TEMP -273 - -#define TYPE_PART 0x00001 //1 Powders -#define TYPE_LIQUID 0x00002 //2 Liquids -#define TYPE_SOLID 0x00004 //4 Solids -#define TYPE_GAS 0x00008 //8 Gasses (Includes plasma) -#define TYPE_ENERGY 0x00010 //16 Energy (Thunder, Light, Neutrons etc.) -#define PROP_CONDUCTS 0x00020 //32 Conducts electricity -#define PROP_BLACK 0x00040 //64 Absorbs Photons (not currently implemented or used, a photwl attribute might be better) -#define PROP_NEUTPENETRATE 0x00080 //128 Penetrated by neutrons -#define PROP_NEUTABSORB 0x00100 //256 Absorbs neutrons, reflect is default (not currently implemented or used) -#define PROP_NEUTPASS 0x00200 //512 Neutrons pass through, such as with glass -#define PROP_DEADLY 0x00400 //1024 Is deadly for stickman (not currently implemented or used) -#define PROP_HOT_GLOW 0x00800 //2048 Hot Metal Glow -#define PROP_LIFE 0x01000 //4096 Is a GoL type -#define PROP_RADIOACTIVE 0x02000 //8192 Radioactive -#define PROP_LIFE_DEC 0x04000 //2^14 Life decreases by one every frame if > zero -#define PROP_LIFE_KILL 0x08000 //2^15 Kill when life value is <= zero -#define PROP_LIFE_KILL_DEC 0x10000 //2^16 Kill when life value is decremented to <= zero -#define PROP_SPARKSETTLE 0x20000 //2^17 Allow Sparks/Embers to settle - -#define FLAG_STAGNANT 1 - -#define ST_NONE 0 -#define ST_SOLID 1 -#define ST_LIQUID 2 -#define ST_GAS 3 - -#define UPDATE_FUNC_ARGS Simulation* sim, int i, int x, int y, int surround_space, int nt, Particle *parts, int pmap[YRES][XRES] -// to call another update function with same arguments: -#define UPDATE_FUNC_SUBCALL_ARGS sim, i, x, y, surround_space, nt, parts, pmap - -#define GRAPHICS_FUNC_ARGS Renderer * ren, Particle *cpart, int nx, int ny, int *pixel_mode, int* cola, int *colr, int *colg, int *colb, int *firea, int *firer, int *fireg, int *fireb -#define GRAPHICS_FUNC_SUBCALL_ARGS ren, cpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb - -#define UI_WALLSTART 222 -#define UI_ACTUALSTART 122 -#define UI_WALLCOUNT 25 - -#define WL_WALLELEC 122 -#define WL_EWALL 123 -#define WL_DETECT 124 -#define WL_STREAM 125 -#define WL_SIGN 126 -#define WL_FAN 127 -#define WL_FANHELPER 255 -#define WL_ALLOWLIQUID 128 -#define WL_DESTROYALL 129 -#define WL_ERASE 130 -#define WL_WALL 131 -#define WL_ALLOWAIR 132 -#define WL_ALLOWSOLID 133 -#define WL_ALLOWALLELEC 134 -#define WL_EHOLE 135 - -#define SPC_AIR 236 -#define SPC_HEAT 237 -#define SPC_COOL 238 -#define SPC_VACUUM 239 -#define SPC_WIND 241 -#define SPC_PGRV 243 -#define SPC_NGRV 244 -#define SPC_PROP 246 - -#define WL_ALLOWGAS 140 -#define WL_GRAV 142 -#define WL_ALLOWENERGY 145 - -#define NGT_GOL 0 -#define NGT_HLIF 1 -#define NGT_ASIM 2 -#define NGT_2x2 3 -#define NGT_DANI 4 -#define NGT_AMOE 5 -#define NGT_MOVE 6 -#define NGT_PGOL 7 -#define NGT_DMOE 8 -#define NGT_34 9 -#define NGT_LLIF 10 -#define NGT_STAN 11 -#define NGT_SEED 12 -#define NGT_MAZE 13 -#define NGT_COAG 14 -#define NGT_WALL 15 -#define NGT_GNAR 16 -#define NGT_REPL 17 -#define NGT_MYST 18 -#define NGT_LOTE 19 -#define NGT_FRG2 20 -#define NGT_STAR 21 -#define NGT_FROG 22 -#define NGT_BRAN 23 - -#define PT_NONE 0 -#define PT_DUST 1 -#define PT_WATR 2 -#define PT_OIL 3 -#define PT_FIRE 4 -#define PT_STNE 5 -#define PT_LAVA 6 -#define PT_GUNP 7 -#define PT_NITR 8 -#define PT_CLNE 9 -#define PT_GAS 10 -#define PT_PLEX 11 -#define PT_GOO 12 -#define PT_ICEI 13 -#define PT_METL 14 -#define PT_SPRK 15 -#define PT_SNOW 16 -#define PT_WOOD 17 -#define PT_NEUT 18 -#define PT_PLUT 19 -#define PT_PLNT 20 -#define PT_ACID 21 -#define PT_VOID 22 -#define PT_WTRV 23 -#define PT_CNCT 24 -#define PT_DSTW 25 -#define PT_SALT 26 -#define PT_SLTW 27 -#define PT_DMND 28 -#define PT_BMTL 29 -#define PT_BRMT 30 -#define PT_PHOT 31 -#define PT_URAN 32 -#define PT_WAX 33 -#define PT_MWAX 34 -#define PT_PSCN 35 -#define PT_NSCN 36 -#define PT_LNTG 37 -#define PT_INSL 38 -#define PT_BHOL 39 -#define PT_WHOL 40 -#define PT_RBDM 41 -#define PT_LRBD 42 -#define PT_NTCT 43 -#define PT_SAND 44 -#define PT_GLAS 45 -#define PT_PTCT 46 -#define PT_BGLA 47 -#define PT_THDR 48 -#define PT_PLSM 49 -#define PT_ETRD 50 -#define PT_NICE 51 -#define PT_NBLE 52 -#define PT_BTRY 53 -#define PT_LCRY 54 -#define PT_STKM 55 -#define PT_SWCH 56 -#define PT_SMKE 57 -#define PT_DESL 58 -#define PT_COAL 59 -#define PT_LO2 60 -#define PT_O2 61 -#define PT_INWR 62 -#define PT_YEST 63 -#define PT_DYST 64 -#define PT_THRM 65 -#define PT_GLOW 66 -#define PT_BRCK 67 -#define PT_HFLM 68 -#define PT_FIRW 69 -#define PT_FUSE 70 -#define PT_FSEP 71 -#define PT_AMTR 72 -#define PT_BCOL 73 -#define PT_PCLN 74 -#define PT_HSWC 75 -#define PT_IRON 76 -#define PT_MORT 77 -#define PT_LIFE 78 -#define PT_DLAY 79 -#define PT_CO2 80 -#define PT_DRIC 81 -#define PT_CBNW 82 -#define PT_STOR 83 -#define PT_PVOD 84 -#define PT_CONV 85 -#define PT_CAUS 86 - -#define PT_LIGH 87 -#define PT_TESC 88 -#define PT_DEST 89 - -#define PT_SPNG 90 -#define PT_RIME 91 -#define PT_FOG 92 -#define PT_BCLN 93 -#define PT_LOVE 94 -#define PT_DEUT 95 -#define PT_WARP 96 -#define PT_PUMP 97 -#define PT_FWRK 98 -#define PT_PIPE 99 -#define PT_FRZZ 100 -#define PT_FRZW 101 -#define PT_GRAV 102 -#define PT_BIZR 103 -#define PT_BIZRG 104 -#define PT_BIZRS 105 -#define PT_INST 106 -#define PT_ISOZ 107 -#define PT_ISZS 108 -#define PT_PRTI 109 -#define PT_PRTO 110 -#define PT_PSTE 111 -#define PT_PSTS 112 -#define PT_ANAR 113 -#define PT_VINE 114 -#define PT_INVIS 115 -#define PT_EQUALVEL 116 //all particles equal their velocities -#define PT_SPAWN2 117 -#define PT_SPAWN 118 -#define PT_SHLD1 119 -#define PT_SHLD2 120 -#define PT_SHLD3 121 -#define PT_SHLD4 122 -#define PT_LOLZ 123 -#define PT_WIFI 124 -#define PT_FILT 125 -#define PT_ARAY 126 -#define PT_BRAY 127 -#define PT_STKM2 128 -#define PT_BOMB 129 -#define PT_C5 130 -#define PT_SING 131 -#define PT_QRTZ 132 -#define PT_PQRT 133 -#define PT_EMP 134 -#define PT_BREC 135 -#define PT_ELEC 136 -#define PT_ACEL 137 -#define PT_DCEL 138 -#define PT_BANG 139 -#define PT_IGNT 140 -#define PT_BOYL 141 - -#define OLD_PT_WIND 147 -#define PT_H2 148 -#define PT_SOAP 149 -#define PT_NBHL 150 -#define PT_NWHL 151 -#define PT_MERC 152 -#define PT_PBCN 153 -#define PT_GPMP 154 -#define PT_CLST 155 -#define PT_WIRE 156 -#define PT_GBMB 157 -#define PT_FIGH 158 -#define PT_NUM 159 - - -//#endif /* ELEMENTS_H_ */ diff --git a/src/Graphics.cpp b/src/Graphics.cpp index 52fa4c9..65d198f 100644 --- a/src/Graphics.cpp +++ b/src/Graphics.cpp @@ -19,13 +19,13 @@ #endif #include "Config.h" -#include "air.h" -#include "gravity.h" +//#include "simulation/Air.h" +//#include "simulation/Gravity.h" //#include "powder.h" -#define INCLUDE_PSTRUCT -#include "Simulation.h" -#include "Graphics.h" -#include "ElementGraphics.h" +//#define INCLUDE_PSTRUCT +//#include "Simulation.h" +//#include "Graphics.h" +//#include "ElementGraphics.h" #define INCLUDE_FONTDATA #include "font.h" #include "misc.h" @@ -1501,15 +1501,24 @@ void Graphics::draw_image(pixel *img, int x, int y, int w, int h, int a) { int i, j, r, g, b; if (!img) return; - for (j=0; j YRES+MENUSIZE) h = (YRES+MENUSIZE)-y; //Adjust height to prevent drawing off the bottom + if(a >= 255) + for (j=0; j -#include -#include -#include "Config.h" -#include "Gravity.h" -//#include "powder.h" - -#ifdef GRAVFFT -#include -#endif - -void Gravity::bilinear_interpolation(float *src, float *dst, int sw, int sh, int rw, int rh) -{ - int y, x, fxceil, fyceil; - float fx, fy, fyc, fxc; - double intp; - float tr, tl, br, bl; - //Bilinear interpolation for upscaling - for (y=0; y=sw) fxceil = sw-1; - if (fyceil>=sh) fyceil = sh-1; - tr = src[sw*(int)floor(fy)+fxceil]; - tl = src[sw*(int)floor(fy)+(int)floor(fx)]; - br = src[sw*fyceil+fxceil]; - bl = src[sw*fyceil+(int)floor(fx)]; - dst[rw*y+x] = ((tl*(1.0f-fxc))+(tr*(fxc)))*(1.0f-fyc) + ((bl*(1.0f-fxc))+(br*(fxc)))*(fyc); - } -} - -void Gravity::gravity_init() -{ - //Allocate full size Gravmaps - th_ogravmap = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - th_gravmap = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - th_gravy = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - th_gravx = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - th_gravp = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - gravmap = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - gravy = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - gravx = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - gravp = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); - gravmask = (unsigned int *)calloc((XRES/CELL)*(YRES/CELL), sizeof(unsigned)); -} - -void Gravity::gravity_cleanup() -{ -#ifdef GRAVFFT - grav_fft_cleanup(); -#endif -} - -void Gravity::gravity_update_async() -{ - int result; - if(ngrav_enable) - { - pthread_mutex_lock(&gravmutex); - result = grav_ready; - if(result) //Did the gravity thread finish? - { - //if (!sys_pause||framerender){ //Only update if not paused - //Switch the full size gravmaps, we don't really need the two above any more - float *tmpf; - - if(th_gravchanged) - { - #if !defined(GRAVFFT) && defined(GRAV_DIFF) - memcpy(gravy, th_gravy, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memcpy(gravx, th_gravx, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memcpy(gravp, th_gravp, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - #else - tmpf = gravy; - gravy = th_gravy; - th_gravy = tmpf; - - tmpf = gravx; - gravx = th_gravx; - th_gravx = tmpf; - - tmpf = gravp; - gravp = th_gravp; - th_gravp = tmpf; - #endif - } - - tmpf = gravmap; - gravmap = th_gravmap; - th_gravmap = tmpf; - - grav_ready = 0; //Tell the other thread that we're ready for it to continue - pthread_cond_signal(&gravcv); - //} - } - pthread_mutex_unlock(&gravmutex); - //Apply the gravity mask - membwand(gravy, gravmask, (XRES/CELL)*(YRES/CELL)*sizeof(float), (XRES/CELL)*(YRES/CELL)*sizeof(unsigned)); - membwand(gravx, gravmask, (XRES/CELL)*(YRES/CELL)*sizeof(float), (XRES/CELL)*(YRES/CELL)*sizeof(unsigned)); - memset(gravmap, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - } -} - -void *Gravity::update_grav_async_helper(void * context) -{ - ((Gravity *)context)->update_grav_async(); -} - -void Gravity::update_grav_async() -{ - int done = 0; - int thread_done = 0; - memset(th_ogravmap, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(th_gravmap, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(th_gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(th_gravx, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(th_gravp, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - //memset(th_gravy, 0, XRES*YRES*sizeof(float)); - //memset(th_gravx, 0, XRES*YRES*sizeof(float)); - //memset(th_gravp, 0, XRES*YRES*sizeof(float)); -#ifdef GRAVFFT - grav_fft_init(); -#endif - while(!thread_done){ - if(!done){ - update_grav(); - done = 1; - pthread_mutex_lock(&gravmutex); - - grav_ready = done; - thread_done = gravthread_done; - - pthread_mutex_unlock(&gravmutex); - } else { - pthread_mutex_lock(&gravmutex); - pthread_cond_wait(&gravcv, &gravmutex); - - done = grav_ready; - thread_done = gravthread_done; - - pthread_mutex_unlock(&gravmutex); - } - } - pthread_exit(NULL); -} - -void Gravity::start_grav_async() -{ - if(!ngrav_enable){ - gravthread_done = 0; - grav_ready = 0; - pthread_mutex_init (&gravmutex, NULL); - pthread_cond_init(&gravcv, NULL); - pthread_create(&gravthread, NULL, &Gravity::update_grav_async_helper, this); //Start asynchronous gravity simulation - ngrav_enable = 1; - } - memset(gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(gravx, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(gravp, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); -} - -void Gravity::stop_grav_async() -{ - if(ngrav_enable){ - pthread_mutex_lock(&gravmutex); - gravthread_done = 1; - pthread_cond_signal(&gravcv); - pthread_mutex_unlock(&gravmutex); - pthread_join(gravthread, NULL); - pthread_mutex_destroy(&gravmutex); //Destroy the mutex - ngrav_enable = 0; - } - //Clear the grav velocities - memset(gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(gravx, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); - memset(gravp, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); -} - -#ifdef GRAVFFT -int grav_fft_status = 0; -float *th_ptgravx, *th_ptgravy, *th_gravmapbig, *th_gravxbig, *th_gravybig; -fftwf_complex *th_ptgravxt, *th_ptgravyt, *th_gravmapbigt, *th_gravxbigt, *th_gravybigt; -fftwf_plan plan_gravmap, plan_gravx_inverse, plan_gravy_inverse; - -void Gravity::grav_fft_init() -{ - int xblock2 = XRES/CELL*2; - int yblock2 = YRES/CELL*2; - int x, y, fft_tsize = (xblock2/2+1)*yblock2; - float distance, scaleFactor; - fftwf_plan plan_ptgravx, plan_ptgravy; - if (grav_fft_status) return; - - //use fftw malloc function to ensure arrays are aligned, to get better performance - th_ptgravx = fftwf_malloc(xblock2*yblock2*sizeof(float)); - th_ptgravy = fftwf_malloc(xblock2*yblock2*sizeof(float)); - th_ptgravxt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); - th_ptgravyt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); - th_gravmapbig = fftwf_malloc(xblock2*yblock2*sizeof(float)); - th_gravmapbigt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); - th_gravxbig = fftwf_malloc(xblock2*yblock2*sizeof(float)); - th_gravybig = fftwf_malloc(xblock2*yblock2*sizeof(float)); - th_gravxbigt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); - th_gravybigt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); - - //select best algorithm, could use FFTW_PATIENT or FFTW_EXHAUSTIVE but that increases the time taken to plan, and I don't see much increase in execution speed - plan_ptgravx = fftwf_plan_dft_r2c_2d(yblock2, xblock2, th_ptgravx, th_ptgravxt, FFTW_MEASURE); - plan_ptgravy = fftwf_plan_dft_r2c_2d(yblock2, xblock2, th_ptgravy, th_ptgravyt, FFTW_MEASURE); - plan_gravmap = fftwf_plan_dft_r2c_2d(yblock2, xblock2, th_gravmapbig, th_gravmapbigt, FFTW_MEASURE); - plan_gravx_inverse = fftwf_plan_dft_c2r_2d(yblock2, xblock2, th_gravxbigt, th_gravxbig, FFTW_MEASURE); - plan_gravy_inverse = fftwf_plan_dft_c2r_2d(yblock2, xblock2, th_gravybigt, th_gravybig, FFTW_MEASURE); - - //(XRES/CELL)*(YRES/CELL)*4 is size of data array, scaling needed because FFTW calculates an unnormalized DFT - scaleFactor = -M_GRAV/((XRES/CELL)*(YRES/CELL)*4); - //calculate velocity map caused by a point mass - for (y=0; y 0.0001f || th_gravmap[i*(XRES/CELL)+j]<-0.0001f) //Only calculate with populated or changed cells. - { -#endif - for (y = 0; y < YRES / CELL; y++) { - for (x = 0; x < XRES / CELL; x++) { - if (x == j && y == i)//Ensure it doesn't calculate with itself - continue; - distance = sqrt(pow(j - x, 2) + pow(i - y, 2)); -#ifdef GRAV_DIFF - val = th_gravmap[i*(XRES/CELL)+j] - th_ogravmap[i*(XRES/CELL)+j]; -#else - val = th_gravmap[i*(XRES/CELL)+j]; -#endif - th_gravx[y*(XRES/CELL)+x] += M_GRAV * val * (j - x) / pow(distance, 3); - th_gravy[y*(XRES/CELL)+x] += M_GRAV * val * (i - y) / pow(distance, 3); - th_gravp[y*(XRES/CELL)+x] += M_GRAV * val / pow(distance, 2); - } - } - } - } - } -fin: - memcpy(th_ogravmap, th_gravmap, (XRES/CELL)*(YRES/CELL)*sizeof(float)); -} -#endif - - - -void Gravity::grav_mask_r(int x, int y, char checkmap[YRES/CELL][XRES/CELL], char shape[YRES/CELL][XRES/CELL], char *shapeout) -{ - if(x < 0 || x >= XRES/CELL || y < 0 || y >= YRES/CELL) - return; - if(x == 0 || y ==0 || y == (YRES/CELL)-1 || x == (XRES/CELL)-1) - *shapeout = 1; - checkmap[y][x] = 1; - shape[y][x] = 1; - if(x-1 >= 0 && !checkmap[y][x-1] && bmap[y][x-1]!=WL_GRAV) - grav_mask_r(x-1, y, checkmap, shape, shapeout); - if(y-1 >= 0 && !checkmap[y-1][x] && bmap[y-1][x]!=WL_GRAV) - grav_mask_r(x, y-1, checkmap, shape, shapeout); - if(x+1 < XRES/CELL && !checkmap[y][x+1] && bmap[y][x+1]!=WL_GRAV) - grav_mask_r(x+1, y, checkmap, shape, shapeout); - if(y+1 < YRES/CELL && !checkmap[y+1][x] && bmap[y+1][x]!=WL_GRAV) - grav_mask_r(x, y+1, checkmap, shape, shapeout); - return; -} -void Gravity::mask_free(mask_el *c_mask_el){ - if(c_mask_el==NULL) - return; - if(c_mask_el->next!=NULL) - mask_free((mask_el*)c_mask_el->next); - free(c_mask_el->shape); - free(c_mask_el); -} -void Gravity::gravity_mask() -{ - char checkmap[YRES/CELL][XRES/CELL]; - int x = 0, y = 0, i, j; - unsigned maskvalue; - mask_el *t_mask_el = NULL; - mask_el *c_mask_el = NULL; - if(!gravmask) - return; - memset(checkmap, 0, sizeof(checkmap)); - for(x = 0; x < XRES/CELL; x++) - { - for(y = 0; y < YRES/CELL; y++) - { - if(bmap[y][x]!=WL_GRAV && checkmap[y][x] == 0) - { - //Create a new shape - if(t_mask_el==NULL){ - t_mask_el = (mask_el *)malloc(sizeof(mask_el)); - t_mask_el->shape = (char *)malloc((XRES/CELL)*(YRES/CELL)); - memset(t_mask_el->shape, 0, (XRES/CELL)*(YRES/CELL)); - t_mask_el->shapeout = 0; - t_mask_el->next = NULL; - c_mask_el = t_mask_el; - } else { - c_mask_el->next = (mask_el *)malloc(sizeof(mask_el)); - c_mask_el = (mask_el *)c_mask_el->next; - c_mask_el->shape = (char *)malloc((XRES/CELL)*(YRES/CELL)); - memset(c_mask_el->shape, 0, (XRES/CELL)*(YRES/CELL)); - c_mask_el->shapeout = 0; - c_mask_el->next = NULL; - } - //Fill the shape - grav_mask_r(x, y, (char (*)[XRES/CELL])checkmap, (char (*)[XRES/CELL])c_mask_el->shape, (char*)&c_mask_el->shapeout); - } - } - } - c_mask_el = t_mask_el; - memset(gravmask, 0, (XRES/CELL)*(YRES/CELL)*sizeof(unsigned)); - while(c_mask_el!=NULL) - { - char *cshape = c_mask_el->shape; - for(x = 0; x < XRES/CELL; x++) - { - for(y = 0; y < YRES/CELL; y++) - { - if(cshape[y*(XRES/CELL)+x]){ - if(c_mask_el->shapeout) - maskvalue = 0xFFFFFFFF; - else - maskvalue = 0x00000000; - gravmask[y*(XRES/CELL)+x] = maskvalue; - } - } - } - c_mask_el = (mask_el*)c_mask_el->next; - } - mask_free(t_mask_el); -} - -Gravity::Gravity() -{ - gravity_init(); -} diff --git a/src/Gravity.h b/src/Gravity.h deleted file mode 100644 index 9f36240..0000000 --- a/src/Gravity.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef GRAVITY_H -#define GRAVITY_H - -#include -#include "Config.h" -#include "Simulation.h" - -class Simulation; - -struct mask_el { - char *shape; - char shapeout; - void *next; -}; -typedef struct mask_el mask_el; - - -/* - * float *gravmap = NULL;//Maps to be used by the main thread - float *gravp = NULL; - float *gravy = NULL; - float *gravx = NULL; - unsigned *gravmask = NULL; - - float *th_ogravmap = NULL;// Maps to be processed by the gravity thread - float *th_gravmap = NULL; - float *th_gravx = NULL; - float *th_gravy = NULL; - float *th_gravp = NULL; - - int th_gravchanged = 0; - - pthread_t gravthread; - pthread_mutex_t gravmutex; - pthread_cond_t gravcv; - int grav_ready = 0; - int gravthread_done = 0; - */ -class Gravity -{ -private: - unsigned *gravmask; - - float *th_ogravmap; - float *th_gravmap; - float *th_gravx; - float *th_gravy; - float *th_gravp; - - int th_gravchanged; - - pthread_t gravthread; - pthread_mutex_t gravmutex; - pthread_cond_t gravcv; - int grav_ready; - int gravthread_done; - - //Simulation * sim; -public: - float *gravmap; - float *gravp; - float *gravy; - float *gravx; - unsigned char (*bmap)[XRES/CELL]; - int ngrav_enable; - void grav_mask_r(int x, int y, char checkmap[YRES/CELL][XRES/CELL], char shape[YRES/CELL][XRES/CELL], char *shapeout); - void mask_free(mask_el *c_mask_el); - - void gravity_init(); - void gravity_cleanup(); - void gravity_update_async(); - - static void *update_grav_async_helper(void * context); - void update_grav_async(); - - void start_grav_async(); - void stop_grav_async(); - void update_grav(); - void gravity_mask(); - - void bilinear_interpolation(float *src, float *dst, int sw, int sh, int rw, int rh); - - #ifdef GRAVFFT - void grav_fft_init(); - void grav_fft_cleanup(); - #endif - - Gravity(); -}; - -/*extern int ngrav_enable; //Newtonian gravity -extern int gravwl_timeout; -extern int gravityMode;*/ - -/*float *gravmap;//Maps to be used by the main thread -float *gravp; -float *gravy; -float *gravx; -unsigned *gravmask; - -float *th_ogravmap;// Maps to be processed by the gravity thread -float *th_gravmap; -float *th_gravx; -float *th_gravy; -float *th_gravp;*/ - - -#endif diff --git a/src/Misc.h b/src/Misc.h index c5a61ef..65ae5b3 100644 --- a/src/Misc.h +++ b/src/Misc.h @@ -3,6 +3,16 @@ #include #include +enum HorizontalAlignment +{ + AlignLeft, AlignCentre, AlignRight +}; + +enum VerticalAlignment +{ + AlignTop, AlignMiddle, AlignBottom +}; + #if defined(WIN32) && !defined(__GNUC__) #define x86_cpuid(func,af,bf,cf,df) \ do {\ diff --git a/src/PowderToy.cpp b/src/PowderToy.cpp index cf7d804..0ee1648 100644 --- a/src/PowderToy.cpp +++ b/src/PowderToy.cpp @@ -6,10 +6,7 @@ #include #include "Config.h" #include "Global.h" -#include "Simulation.h" -#include "Renderer.h" #include "Graphics.h" -#include "Air.h" #include "interface/Engine.h" #include "interface/Button.h" @@ -22,6 +19,8 @@ #include "game/GameController.h" #include "game/GameView.h" +#include "client/HTTP.h" + using namespace std; SDL_Surface * SDLOpen() diff --git a/src/Renderer.cpp b/src/Renderer.cpp index 67f9348..2644924 100644 --- a/src/Renderer.cpp +++ b/src/Renderer.cpp @@ -9,10 +9,10 @@ #include "Config.h" #include "Renderer.h" #include "Graphics.h" -#include "Elements.h" -#include "ElementFunctions.h" -#include "ElementGraphics.h" -#include "Air.h" +#include "simulation/Elements.h" +#include "simulation/ElementFunctions.h" +#include "simulation/ElementGraphics.h" +#include "simulation/Air.h" extern "C" { #include "hmap.h" diff --git a/src/Renderer.h b/src/Renderer.h index 39c8c1a..a756f13 100644 --- a/src/Renderer.h +++ b/src/Renderer.h @@ -2,7 +2,7 @@ #define RENDERER_H #include "Config.h" -#include "Simulation.h" +#include "simulation/Simulation.h" #include "Graphics.h" class Simulation; diff --git a/src/Simulation.cpp b/src/Simulation.cpp deleted file mode 100644 index a1a785a..0000000 --- a/src/Simulation.cpp +++ /dev/null @@ -1,3593 +0,0 @@ -#include -#include -#define _cplusplus -#include "Config.h" -#include "Simulation.h" -#include "Elements.h" -#include "ElementFunctions.h" -#include "Air.h" -#include "Gravity.h" -//#include "powder.h" - -void Simulation::clear_area(int area_x, int area_y, int area_w, int area_h) -{ - int cx = 0; - int cy = 0; - for (cy=0; cyx2) - { - i = x2; - x2 = x1; - x1 = i; - } - if (y1>y2) - { - j = y2; - y2 = y1; - y1 = j; - } - for (j=y1; j<=y2; j++) - for (i=x1; i<=x2; i++) - create_parts(i, j, 0, 0, c, flags); -} - -int Simulation::flood_prop_2(int x, int y, size_t propoffset, void * propvalue, int proptype, int parttype, char * bitmap) -{ - int x1, x2, i, dy = 1; - x1 = x2 = x; - while (x1>=CELL) - { - if ((pmap[y][x1-1]&0xFF)!=parttype || bitmap[(y*XRES)+x1-1]) - { - break; - } - x1--; - } - while (x2>8; - if(proptype==2){ - *((float*)(((char*)&parts[i])+propoffset)) = *((float*)propvalue); - } else if(proptype==0) { - *((int*)(((char*)&parts[i])+propoffset)) = *((int*)propvalue); - } else if(proptype==1) { - *((char*)(((char*)&parts[i])+propoffset)) = *((char*)propvalue); - } - bitmap[(y*XRES)+x] = 1; - } - if (y>=CELL+dy) - for (x=x1; x<=x2; x++) - if ((pmap[y-dy][x]&0xFF)==parttype && !bitmap[((y-dy)*XRES)+x]) - if (!flood_prop_2(x, y-dy, propoffset, propvalue, proptype, parttype, bitmap)) - return 0; - if (y=CELL) - { - if ((pmap[y][x1-1]&0xFF)!=cm || bmap[y/CELL][(x1-1)/CELL]!=bm) - { - break; - } - x1--; - } - while (x2=CELL+dy && x1==x2 && - ((pmap[y-1][x1-1]&0xFF)==PT_INST||(pmap[y-1][x1-1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1]&0xFF)==PT_INST||(pmap[y-1][x1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1+1]&0xFF)==PT_INST || (pmap[y-1][x1+1]&0xFF)==PT_SPRK) && - (pmap[y-2][x1-1]&0xFF)!=PT_INST && ((pmap[y-2][x1]&0xFF)==PT_INST ||(pmap[y-2][x1]&0xFF)==PT_SPRK) && (pmap[y-2][x1+1]&0xFF)!=PT_INST) - flood_parts(x1, y-2, fullc, cm, bm, flags); - else if (y>=CELL+dy) - for (x=x1; x<=x2; x++) - if ((pmap[y-1][x]&0xFF)!=PT_SPRK) - { - if (x==x1 || x==x2 || y>=YRES-CELL-1 || - (pmap[y-1][x-1]&0xFF)==PT_INST || (pmap[y-1][x+1]&0xFF)==PT_INST || - (pmap[y+1][x-1]&0xFF)==PT_INST || ((pmap[y+1][x]&0xFF)!=PT_INST&&(pmap[y+1][x]&0xFF)!=PT_SPRK) || (pmap[y+1][x+1]&0xFF)==PT_INST) - flood_parts(x, y-dy, fullc, cm, bm, flags); - - } - - if (y=CELL+dy) - for (x=x1; x<=x2; x++) - if ((pmap[y-dy][x]&0xFF)==cm && bmap[(y-dy)/CELL][x/CELL]==bm) - if (!flood_parts(x, y-dy, fullc, cm, bm, flags)) - return 0; - if (y=CELL) - { - if ((ptypes[(pmap[y][x1-1]&0xFF)].falldown)!=2) - { - break; - } - x1--; - } - while (x2>8].tmp2 = !check;//flag it as checked, maybe shouldn't use .tmp2 - //check above, maybe around other sides too? - if ( ((y-1) > originaly) && !pmap[y-1][x] && eval_move(parts[i].type, x, y-1, NULL)) - { - int oldx = (int)(parts[i].x + 0.5f); - int oldy = (int)(parts[i].y + 0.5f); - pmap[y-1][x] = pmap[oldy][oldx]; - pmap[oldy][oldx] = 0; - parts[i].x = x; - parts[i].y = y-1; - return 0; - } - } - // fill children - - if (y>=CELL+1) - for (x=x1; x<=x2; x++) - if ((ptypes[(pmap[y-1][x]&0xFF)].falldown)==2 && parts[pmap[y-1][x]>>8].tmp2 == check) - if (!flood_water(x, y-1, i, originaly, check)) - return 0; - if (y>8].tmp2 == check) - if (!flood_water(x, y+1, i, originaly, check)) - return 0; - return 1; -} - -//wrapper around create_part to create TESC with correct tmp value -int Simulation::create_part_add_props(int p, int x, int y, int tv, int rx, int ry) -{ - p=create_part(p, x, y, tv); - if (tv==PT_TESC) - { - parts[p].tmp=rx*4+ry*4+7; - if (parts[p].tmp>300) - parts[p].tmp=300; - } - return p; -} - -//this creates particles from a brush, don't use if you want to create one particle -int Simulation::create_parts(int x, int y, int rx, int ry, int c, int flags) -{ - int i, j, r, f = 0, u, v, oy, ox, b = 0, dw = 0, stemp = 0, p;//n; - - int wall = c - 100; - if (c==SPC_WIND || c==PT_FIGH) - return 0; - - //if(c==SPC_PROP){ - // prop_edit_ui(vid_buf, x, y); - // return 0; - //} - for (r=UI_ACTUALSTART; r<=UI_ACTUALSTART+UI_WALLCOUNT; r++) - { - if (wall==r) - { - if (c == SPC_AIR || c == SPC_HEAT || c == SPC_COOL || c == SPC_VACUUM || c == SPC_PGRV || c == SPC_NGRV || wall == WL_SIGN) - break; - if (wall == WL_ERASE) - b = 0; - else - b = wall; - dw = 1; - } - } - if (c == WL_FANHELPER) - { - b = WL_FANHELPER; - dw = 1; - } - if (wall == WL_GRAV) - { - gravwl_timeout = 60; - } - if (c==PT_LIGH) - { - if (lighting_recreate>0 && rx+ry>0) - return 0; - p=create_part(-2, x, y, c); - if (p!=-1) - { - parts[p].life=rx+ry; - if (parts[p].life>55) - parts[p].life=55; - parts[p].temp=parts[p].life*150; // temperature of the lighting shows the power of the lighting - lighting_recreate+=parts[p].life/2+1; - return 1; - } - else return 0; - } - - if (dw==1) - { - ry = ry/CELL; - rx = rx/CELL; - x = x/CELL; - y = y/CELL; - x -= rx/2; - y -= ry/2; - for (ox=x; ox<=x+rx; ox++) - { - for (oy=y; oy<=y+rx; oy++) - { - if (ox>=0&&ox=0&&oy=0 && i+u=0 && j+v=XRES || y+j>=YRES) - continue; - //if (!REPLACE_MODE) - create_part(-2, x+i, y+j, c); - /*else if ((pmap[y+j][x+i]&0xFF)==SLALT&&SLALT!=0) - create_part(-2, x+i, y+j, c);*/ - } - return 1; - } - - /*if (flags&BRUSH_REPLACEMODE) - { - if (rx==0&&ry==0) - { - if ((pmap[y][x]&0xFF)==SLALT || SLALT==0) - { - if ((pmap[y][x])) - { - delete_part(x, y, 0); - if (c!=0) - create_part_add_props(-2, x, y, c, rx, ry); - } - } - } - else - for (j=-ry; j<=ry; j++) - for (i=-rx; i<=rx; i++) - if (InCurrentBrush(i ,j ,rx ,ry)) - { - if ( x+i<0 || y+j<0 || x+i>=XRES || y+j>=YRES) - continue; - if ((pmap[y+j][x+i]&0xFF)!=SLALT&&SLALT!=0) - continue; - if ((pmap[y+j][x+i])) - { - delete_part(x+i, y+j, 0); - if (c!=0) - create_part_add_props(-2, x+i, y+j, c, rx, ry); - } - } - return 1; - - }*/ - //else, no special modes, draw element like normal. - if (rx==0&&ry==0)//workaround for 1pixel brush/floodfill crashing. todo: find a better fix later. - { - if (create_part_add_props(-2, x, y, c, rx, ry)==-1) - f = 1; - } - else - for (j=-ry; j<=ry; j++) - for (i=-rx; i<=rx; i++) - //if (InCurrentBrush(i ,j ,rx ,ry)) - if (create_part_add_props(-2, x+i, y+j, c, rx, ry)==-1) - f = 1; - return !f; -} -/*int Simulation::InCurrentBrush(int i, int j, int rx, int ry) -{ - switch(CURRENT_BRUSH) - { - case CIRCLE_BRUSH: - return (pow(i,2)*pow(ry,2)+pow(j,2)*pow(rx,2)<=pow(rx,2)*pow(ry,2)); - break; - case SQUARE_BRUSH: - return (i*j<=ry*rx); - break; - case TRI_BRUSH: - return (j <= ry ) && ( j >= (((-2.0*ry)/rx)*i) -ry) && ( j >= (((-2.0*ry)/(-rx))*i)-ry ) ; - break; - } - return 0; -} -int Simulation::get_brush_flags() -{ - int flags = 0; - if (REPLACE_MODE) - flags |= BRUSH_REPLACEMODE; - if (sdl_mod & KMOD_CAPS) - flags |= BRUSH_SPECIFIC_DELETE; - if ((sdl_mod & KMOD_LALT) && (sdl_mod & (KMOD_CTRL))) - flags |= BRUSH_SPECIFIC_DELETE; - return flags; -}*/ -void Simulation::create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flags) -{ - int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy; - float e, de; - if (c==SPC_PROP) - return; - if (cp) - { - y = x1; - x1 = y1; - y1 = y; - y = x2; - x2 = y2; - y2 = y; - } - if (x1 > x2) - { - y = x1; - x1 = x2; - x2 = y; - y = y1; - y1 = y2; - y2 = y; - } - dx = x2 - x1; - dy = abs(y2 - y1); - e = 0.0f; - if (dx) - de = dy/(float)dx; - else - de = 0.0f; - y = y1; - sy = (y1= 0.5f) - { - y += sy; - if ((c==WL_EHOLE+100 || c==WL_ALLOWGAS+100 || c==WL_ALLOWENERGY+100 || c==WL_ALLOWALLELEC+100 || c==WL_ALLOWSOLID+100 || c==WL_ALLOWAIR+100 || c==WL_WALL+100 || c==WL_DESTROYALL+100 || c==WL_ALLOWLIQUID+100 || c==WL_FAN+100 || c==WL_STREAM+100 || c==WL_DETECT+100 || c==WL_EWALL+100 || c==WL_WALLELEC+100 || !(rx+ry)) - && ((y1=y2))) - { - if (cp) - create_parts(y, x, rx, ry, c, flags); - else - create_parts(x, y, rx, ry, c, flags); - } - e -= 1.0f; - } - } -} - -void *Simulation::transform_save(void *odata, int *size, matrix2d transform, vector2d translate) -{ - void *ndata; - unsigned char (*bmapo)[XRES/CELL] = (unsigned char (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(unsigned char)); - unsigned char (*bmapn)[XRES/CELL] = (unsigned char (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(unsigned char)); - Particle *partst = (Particle *)calloc(sizeof(Particle), NPART); - sign *signst = (sign *)calloc(MAXSIGNS, sizeof(sign)); - unsigned (*pmapt)[XRES] = (unsigned (*)[XRES])calloc(YRES*XRES, sizeof(unsigned)); - float (*fvxo)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); - float (*fvyo)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); - float (*fvxn)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); - float (*fvyn)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); - int i, x, y, nx, ny, w, h, nw, nh; - vector2d pos, tmp, ctl, cbr; - vector2d cornerso[4]; - unsigned char *odatac = (unsigned char *)odata; - //*if (parse_save(odata, *size, 0, 0, 0, bmapo, fvxo, fvyo, signst, partst, pmapt)) TODO: IMPLEMENT - { - free(bmapo); - free(bmapn); - free(partst); - free(signst); - free(pmapt); - free(fvxo); - free(fvyo); - free(fvxn); - free(fvyn); - return odata; - } - w = odatac[6]*CELL; - h = odatac[7]*CELL; - // undo any translation caused by rotation - cornerso[0] = v2d_new(0,0); - cornerso[1] = v2d_new(w-1,0); - cornerso[2] = v2d_new(0,h-1); - cornerso[3] = v2d_new(w-1,h-1); - for (i=0; i<4; i++) - { - tmp = m2d_multiply_v2d(transform,cornerso[i]); - if (i==0) ctl = cbr = tmp; // top left, bottom right corner - if (tmp.xcbr.x) cbr.x = tmp.x; - if (tmp.y>cbr.y) cbr.y = tmp.y; - } - // casting as int doesn't quite do what we want with negative numbers, so use floor() - tmp = v2d_new(floor(ctl.x+0.5f),floor(ctl.y+0.5f)); - translate = v2d_sub(translate,tmp); - nw = floor(cbr.x+0.5f)-floor(ctl.x+0.5f)+1; - nh = floor(cbr.y+0.5f)-floor(ctl.y+0.5f)+1; - if (nw>XRES) nw = XRES; - if (nh>YRES) nh = YRES; - // rotate and translate signs, parts, walls - for (i=0; i=nw || ny<0 || ny>=nh) - { - signst[i].text[0] = 0; - continue; - } - signst[i].x = nx; - signst[i].y = ny; - } - for (i=0; i=nw || ny<0 || ny>=nh) - { - partst[i].type = PT_NONE; - continue; - } - partst[i].x = nx; - partst[i].y = ny; - } - for (y=0; y=nw || ny<0 || ny>=nh) - continue; - if (bmapo[y][x]) - { - bmapn[ny][nx] = bmapo[y][x]; - if (bmapo[y][x]==WL_FAN) - { - fvxn[ny][nx] = fvxo[y][x]; - fvyn[ny][nx] = fvyo[y][x]; - } - } - } - //ndata = build_save(size,0,0,nw,nh,bmapn,fvxn,fvyn,signst,partst); TODO: IMPLEMENT - free(bmapo); - free(bmapn); - free(partst); - free(signst); - free(pmapt); - free(fvxo); - free(fvyo); - free(fvxn); - free(fvyn); - return ndata; -} - -void Simulation::orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[]) -{ - resblock1[0] = (block1&0x000000FF); - resblock1[1] = (block1&0x0000FF00)>>8; - resblock1[2] = (block1&0x00FF0000)>>16; - resblock1[3] = (block1&0xFF000000)>>24; - - resblock2[0] = (block2&0x000000FF); - resblock2[1] = (block2&0x0000FF00)>>8; - resblock2[2] = (block2&0x00FF0000)>>16; - resblock2[3] = (block2&0xFF000000)>>24; -} - -void Simulation::orbitalparts_set(int *block1, int *block2, int resblock1[], int resblock2[]) -{ - int block1tmp = 0; - int block2tmp = 0; - - block1tmp = (resblock1[0]&0xFF); - block1tmp |= (resblock1[1]&0xFF)<<8; - block1tmp |= (resblock1[2]&0xFF)<<16; - block1tmp |= (resblock1[3]&0xFF)<<24; - - block2tmp = (resblock2[0]&0xFF); - block2tmp |= (resblock2[1]&0xFF)<<8; - block2tmp |= (resblock2[2]&0xFF)<<16; - block2tmp |= (resblock2[3]&0xFF)<<24; - - *block1 = block1tmp; - *block2 = block2tmp; -} - -inline int Simulation::is_wire(int x, int y) -{ - return bmap[y][x]==WL_DETECT || bmap[y][x]==WL_EWALL || bmap[y][x]==WL_ALLOWLIQUID || bmap[y][x]==WL_WALLELEC || bmap[y][x]==WL_ALLOWALLELEC || bmap[y][x]==WL_EHOLE; -} - -inline int Simulation::is_wire_off(int x, int y) -{ - return (bmap[y][x]==WL_DETECT || bmap[y][x]==WL_EWALL || bmap[y][x]==WL_ALLOWLIQUID || bmap[y][x]==WL_WALLELEC || bmap[y][x]==WL_ALLOWALLELEC || bmap[y][x]==WL_EHOLE) && emap[y][x]<8; -} - -int Simulation::get_wavelength_bin(int *wm) -{ - int i, w0=30, wM=0; - - if (!*wm) - return -1; - - for (i=0; i<30; i++) - if (*wm & (1< wM) - wM = i; - } - - if (wM-w0 < 5) - return (wM+w0)/2; - - i = rand() % (wM-w0-3); - i += w0; - - *wm &= 0x1F << i; - return i + 2; -} - -void Simulation::set_emap(int x, int y) -{ - int x1, x2; - - if (!is_wire_off(x, y)) - return; - - // go left as far as possible - x1 = x2 = x; - while (x1>0) - { - if (!is_wire_off(x1-1, y)) - break; - x1--; - } - while (x21 && x1==x2 && - is_wire(x1-1, y-1) && is_wire(x1, y-1) && is_wire(x1+1, y-1) && - !is_wire(x1-1, y-2) && is_wire(x1, y-2) && !is_wire(x1+1, y-2)) - set_emap(x1, y-2); - else if (y>0) - for (x=x1; x<=x2; x++) - if (is_wire_off(x, y-1)) - { - if (x==x1 || x==x2 || y>=YRES/CELL-1 || - is_wire(x-1, y-1) || is_wire(x+1, y-1) || - is_wire(x-1, y+1) || !is_wire(x, y+1) || is_wire(x+1, y+1)) - set_emap(x, y-1); - } - - if (y>8].type; - else - return PT_NONE; - } - else - { - int pmr2 = pmap[(int)((parts[ci].y + parts[ni].y)/2+0.5f)][(int)((parts[ci].x + parts[ni].x)/2+0.5f)];//seems to be more accurate. - if (pmr2) - { - if (parts[pmr2>>8].type==t) - return t; - } - else - return PT_NONE; - } - return PT_NONE; -} - - -int Simulation::nearest_part(int ci, int t, int max_d) -{ - int distance = (max_d!=-1)?max_d:MAX_DISTANCE; - int ndistance = 0; - int id = -1; - int i = 0; - int cx = (int)parts[ci].x; - int cy = (int)parts[ci].y; - for (i=0; i<=parts_lastActiveIndex; i++) - { - if ((parts[i].type==t||(t==-1&&parts[i].type))&&!parts[i].life&&i!=ci) - { - ndistance = abs(cx-parts[i].x)+abs(cy-parts[i].y);// Faster but less accurate Older: sqrt(pow(cx-parts[i].x, 2)+pow(cy-parts[i].y, 2)); - if (ndistance=XRES || ny>=YRES) - return 0; - - r = pmap[ny][nx]; - if (r) - r = (r&~0xFF) | parts[r>>8].type; - if (rr) - *rr = r; - if (pt>=PT_NUM || (r&0xFF)>=PT_NUM) - return 0; - result = can_move[pt][r&0xFF]; - if (result==3) - { - if ((pt==PT_PHOT || pt==PT_ELEC) && (r&0xFF)==PT_LCRY) - result = (parts[r>>8].life > 5)? 2 : 0; - if ((r&0xFF)==PT_INVIS) - { - if (pv[ny/CELL][nx/CELL]>4.0f || pv[ny/CELL][nx/CELL]<-4.0f) result = 2; - else result = 0; - } - if ((r&0xFF)==PT_PVOD) - { - if (parts[r>>8].life == 10) result = 1; - else result = 0; - } - } - if (bmap[ny/CELL][nx/CELL]) - { - if (bmap[ny/CELL][nx/CELL]==WL_ALLOWGAS && !(ptypes[pt].properties&TYPE_GAS))// && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE) - return 0; - if (bmap[ny/CELL][nx/CELL]==WL_ALLOWENERGY && !(ptypes[pt].properties&TYPE_ENERGY))// && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE) - return 0; - if (bmap[ny/CELL][nx/CELL]==WL_ALLOWLIQUID && ptypes[pt].falldown!=2) - return 0; - if (bmap[ny/CELL][nx/CELL]==WL_ALLOWSOLID && ptypes[pt].falldown!=1) - return 0; - if (bmap[ny/CELL][nx/CELL]==WL_ALLOWAIR || bmap[ny/CELL][nx/CELL]==WL_WALL || bmap[ny/CELL][nx/CELL]==WL_WALLELEC) - return 0; - if (bmap[ny/CELL][nx/CELL]==WL_EWALL && !emap[ny/CELL][nx/CELL]) - return 0; - if (bmap[ny/CELL][nx/CELL]==WL_EHOLE && !emap[ny/CELL][nx/CELL]) - return 2; - } - return result; -} - -int Simulation::try_move(int i, int x, int y, int nx, int ny) -{ - unsigned r, e; - - if (x==nx && y==ny) - return 1; - if (nx<0 || ny<0 || nx>=XRES || ny>=YRES) - return 1; - - e = eval_move(parts[i].type, nx, ny, &r); - - if ((r&0xFF)==PT_BOMB && parts[i].type==PT_BOMB && parts[i].tmp == 1) - e = 2; - - /* half-silvered mirror */ - if (!e && parts[i].type==PT_PHOT && - (((r&0xFF)==PT_BMTL && rand()>8].temp = parts[i].temp; - - if ((r & 0xFF) < PT_NUM && ptypes[r&0xFF].hconduct && ((r&0xFF)!=PT_HSWC||parts[r>>8].life==10) && (r&0xFF)!=PT_FILT) - parts[i].temp = parts[r>>8].temp = restrict_flt((parts[r>>8].temp+parts[i].temp)/2, MIN_TEMP, MAX_TEMP); - } - if ((parts[i].type==PT_NEUT || parts[i].type==PT_ELEC) && ((r&0xFF)==PT_CLNE || (r&0xFF)==PT_PCLN || (r&0xFF)==PT_BCLN || (r&0xFF)==PT_PBCN)) { - if (!parts[r>>8].ctype) - parts[r>>8].ctype = parts[i].type; - } - if ((r&0xFF)==PT_PRTI && (parts[i].type==PT_PHOT || parts[i].type==PT_NEUT || parts[i].type==PT_ELEC)) - { - int nnx, count; - for (count=0; count<8; count++) - { - if (isign(x-nx)==isign(portal_rx[count]) && isign(y-ny)==isign(portal_ry[count])) - break; - } - count = count%8; - parts[r>>8].tmp = (int)((parts[r>>8].temp-73.15f)/100+1); - if (parts[r>>8].tmp>=CHANNELS) parts[r>>8].tmp = CHANNELS-1; - else if (parts[r>>8].tmp<0) parts[r>>8].tmp = 0; - for ( nnx=0; nnx<80; nnx++) - if (!portalp[parts[r>>8].tmp][count][nnx].type) - { - portalp[parts[r>>8].tmp][count][nnx] = parts[i]; - parts[i].type=PT_NONE; - break; - } - } - return 0; - } - - if (e == 2) //if occupy same space - { - if (parts[i].type == PT_PHOT && (r&0xFF)==PT_GLOW && !parts[r>>8].life) - if (rand() < RAND_MAX/30) - { - parts[r>>8].life = 120; - create_gain_photon(i); - } - if (parts[i].type == PT_PHOT && (r&0xFF)==PT_FILT) - { - int temp_bin = (int)((parts[r>>8].temp-273.0f)*0.025f); - if (temp_bin < 0) temp_bin = 0; - if (temp_bin > 25) temp_bin = 25; - if(!parts[r>>8].tmp){ - parts[i].ctype = 0x1F << temp_bin; //Assign Colour - } else if(parts[r>>8].tmp==1){ - parts[i].ctype &= 0x1F << temp_bin; //Filter Colour - } else if(parts[r>>8].tmp==2){ - parts[i].ctype |= 0x1F << temp_bin; //Add Colour - } else if(parts[r>>8].tmp==3){ - parts[i].ctype &= ~(0x1F << temp_bin); //Subtract Colour - } - } - if (parts[i].type == PT_NEUT && (r&0xFF)==PT_GLAS) { - if (rand() < RAND_MAX/10) - create_cherenkov_photon(i); - } - if (parts[i].type == PT_PHOT && (r&0xFF)==PT_INVIS && pv[ny/CELL][nx/CELL]<=4.0f && pv[ny/CELL][nx/CELL]>=-4.0f) { - part_change_type(i,x,y,PT_NEUT); - parts[i].ctype = 0; - } - if ((parts[i].type==PT_BIZR||parts[i].type==PT_BIZRG) && (r&0xFF)==PT_FILT) - { - int temp_bin = (int)((parts[r>>8].temp-273.0f)*0.025f); - if (temp_bin < 0) temp_bin = 0; - if (temp_bin > 25) temp_bin = 25; - parts[i].ctype = 0x1F << temp_bin; - } - return 1; - } - //else e=1 , we are trying to swap the particles, return 0 no swap/move, 1 is still overlap/move, because the swap takes place later - - if ((r&0xFF)==PT_VOID || (r&0xFF)==PT_PVOD) //this is where void eats particles - { - if (parts[i].type == PT_STKM) - { - player.spwn = 0; - } - if (parts[i].type == PT_STKM2) - { - player2.spwn = 0; - } - if (parts[i].type == PT_FIGH) - { - fighters[(unsigned char)parts[i].tmp].spwn = 0; - fighcount--; - } - parts[i].type=PT_NONE; - return 0; - } - if ((r&0xFF)==PT_BHOL || (r&0xFF)==PT_NBHL) //this is where blackhole eats particles - { - if (parts[i].type == PT_STKM) - { - player.spwn = 0; - } - if (parts[i].type == PT_STKM2) - { - player2.spwn = 0; - } - if (parts[i].type == PT_FIGH) - { - fighters[(unsigned char)parts[i].tmp].spwn = 0; - fighcount--; - } - parts[i].type=PT_NONE; - if (!legacy_enable) - { - parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f; - } - - return 0; - } - if (((r&0xFF)==PT_WHOL||(r&0xFF)==PT_NWHL) && parts[i].type==PT_ANAR) //whitehole eats anar - { - parts[i].type=PT_NONE; - if (!legacy_enable) - { - parts[r>>8].temp = restrict_flt(parts[r>>8].temp- (MAX_TEMP-parts[i].temp)/2, MIN_TEMP, MAX_TEMP); - } - - return 0; - } - - if (parts[i].type==PT_CNCT && y0) - return 0; - - e = r >> 8; //e is now the particle number at r (pmap[ny][nx]) - if (r)//the swap part, if we make it this far, swap - { - if (parts[i].type==PT_NEUT) { - // target material is NEUTPENETRATE, meaning it gets moved around when neutron passes - unsigned s = pmap[y][x]; - if (!(ptypes[s&0xFF].properties&PROP_NEUTPENETRATE)) - return 1; // if the element currently underneath neutron isn't NEUTPENETRATE, don't move anything except the neutron - // if nothing is currently underneath neutron, only move target particle - if (s) - { - pmap[ny][nx] = (s&~(0xFF))|parts[s>>8].type; - parts[s>>8].x = nx; - parts[s>>8].y = ny; - } - else pmap[ny][nx] = 0; - parts[e].x = x; - parts[e].y = y; - pmap[y][x] = (e<<8)|parts[e].type; - return 1; - } - - if ((pmap[ny][nx]>>8)==e) pmap[ny][nx] = 0; - parts[e].x += x-nx; - parts[e].y += y-ny; - pmap[(int)(parts[e].y+0.5f)][(int)(parts[e].x+0.5f)] = (e<<8)|parts[e].type; - } - return 1; -} - -// try to move particle, and if successful update pmap and parts[i].x,y -int Simulation::do_move(int i, int x, int y, float nxf, float nyf) -{ - int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f); - int result = try_move(i, x, y, nx, ny); - if (result) - { - int t = parts[i].type; - parts[i].x = nxf; - parts[i].y = nyf; - if (ny!=y || nx!=x) - { - if ((pmap[y][x]>>8)==i) pmap[y][x] = 0; - else if ((photons[y][x]>>8)==i) photons[y][x] = 0; - if (nx=XRES-CELL || ny=YRES-CELL)//kill_part if particle is out of bounds - { - kill_part(i); - return -1; - } - if (t==PT_PHOT||t==PT_NEUT||t==PT_ELEC) - photons[ny][nx] = t|(i<<8); - else if (t) - pmap[ny][nx] = t|(i<<8); - } - } - return result; -} - -int Simulation::pn_junction_sprk(int x, int y, int pt) -{ - unsigned r = pmap[y][x]; - if ((r & 0xFF) != pt) - return 0; - r >>= 8; - if (parts[r].type != pt) - return 0; - if (parts[r].life != 0) - return 0; - - parts[r].ctype = pt; - part_change_type(r,x,y,PT_SPRK); - parts[r].life = 4; - return 1; -} - -void Simulation::photoelectric_effect(int nx, int ny)//create sparks from PHOT when hitting PSCN and NSCN -{ - unsigned r = pmap[ny][nx]; - - if ((r&0xFF) == PT_PSCN) { - if ((pmap[ny][nx-1] & 0xFF) == PT_NSCN || - (pmap[ny][nx+1] & 0xFF) == PT_NSCN || - (pmap[ny-1][nx] & 0xFF) == PT_NSCN || - (pmap[ny+1][nx] & 0xFF) == PT_NSCN) - pn_junction_sprk(nx, ny, PT_PSCN); - } -} - -unsigned Simulation::direction_to_map(float dx, float dy, int t) -{ - // TODO: - // Adding extra directions causes some inaccuracies. - // Not adding them causes problems with some diagonal surfaces (photons absorbed instead of reflected). - // For now, don't add them. - // Solution may involve more intelligent setting of initial i0 value in find_next_boundary? - // or rewriting normal/boundary finding code - - return (dx >= 0) | - (((dx + dy) >= 0) << 1) | /* 567 */ - ((dy >= 0) << 2) | /* 4+0 */ - (((dy - dx) >= 0) << 3) | /* 321 */ - ((dx <= 0) << 4) | - (((dx + dy) <= 0) << 5) | - ((dy <= 0) << 6) | - (((dy - dx) <= 0) << 7); - /* - return (dx >= -0.001) | - (((dx + dy) >= -0.001) << 1) | // 567 - ((dy >= -0.001) << 2) | // 4+0 - (((dy - dx) >= -0.001) << 3) | // 321 - ((dx <= 0.001) << 4) | - (((dx + dy) <= 0.001) << 5) | - ((dy <= 0.001) << 6) | - (((dy - dx) <= 0.001) << 7); - }*/ -} - -int Simulation::is_blocking(int t, int x, int y) -{ - if (t & REFRACT) { - if (x<0 || y<0 || x>=XRES || y>=YRES) - return 0; - if ((pmap[y][x] & 0xFF) == PT_GLAS) - return 1; - return 0; - } - - return !eval_move(t, x, y, NULL); -} - -int Simulation::is_boundary(int pt, int x, int y) -{ - if (!is_blocking(pt,x,y)) - return 0; - if (is_blocking(pt,x,y-1) && is_blocking(pt,x,y+1) && is_blocking(pt,x-1,y) && is_blocking(pt,x+1,y)) - return 0; - return 1; -} - -int Simulation::find_next_boundary(int pt, int *x, int *y, int dm, int *em) -{ - static int dx[8] = {1,1,0,-1,-1,-1,0,1}; - static int dy[8] = {0,1,1,1,0,-1,-1,-1}; - static int de[8] = {0x83,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC1}; - int i, ii, i0; - - if (*x <= 0 || *x >= XRES-1 || *y <= 0 || *y >= YRES-1) - return 0; - - if (*em != -1) { - i0 = *em; - dm &= de[i0]; - } else - i0 = 0; - - for (ii=0; ii<8; ii++) { - i = (ii + i0) & 7; - if ((dm & (1 << i)) && is_boundary(pt, *x+dx[i], *y+dy[i])) { - *x += dx[i]; - *y += dy[i]; - *em = i; - return 1; - } - } - - return 0; -} - -int Simulation::get_normal(int pt, int x, int y, float dx, float dy, float *nx, float *ny) -{ - int ldm, rdm, lm, rm; - int lx, ly, lv, rx, ry, rv; - int i, j; - float r, ex, ey; - - if (!dx && !dy) - return 0; - - if (!is_boundary(pt, x, y)) - return 0; - - ldm = direction_to_map(-dy, dx, pt); - rdm = direction_to_map(dy, -dx, pt); - lx = rx = x; - ly = ry = y; - lv = rv = 1; - lm = rm = -1; - - j = 0; - for (i=0; i= NORMAL_INTERP) - return 0; - - if (pt == PT_PHOT) - photoelectric_effect(x, y); - - return get_normal(pt, x, y, dx, dy, nx, ny); -} - -//For soap only -void Simulation::detach(int i) -{ - if ((parts[i].ctype&2) == 2) - { - if ((parts[parts[i].tmp].ctype&4) == 4) - parts[parts[i].tmp].ctype ^= 4; - } - - if ((parts[i].ctype&4) == 4) - { - if ((parts[parts[i].tmp2].ctype&2) == 2) - parts[parts[i].tmp2].ctype ^= 2; - } - - parts[i].ctype = 0; -} - -void Simulation::kill_part(int i)//kills particle number i -{ - int x, y; - - if(elementCount[parts[i].type] && parts[i].type) - elementCount[parts[i].type]--; - x = (int)(parts[i].x+0.5f); - y = (int)(parts[i].y+0.5f); - if (parts[i].type == PT_STKM) - { - player.spwn = 0; - } - if (parts[i].type == PT_STKM2) - { - player2.spwn = 0; - } - if (parts[i].type == PT_FIGH) - { - fighters[(unsigned char)parts[i].tmp].spwn = 0; - fighcount--; - } - if (parts[i].type == PT_SOAP) - { - detach(i); - } - if (x>=0 && y>=0 && x>8)==i) - pmap[y][x] = 0; - else if ((photons[y][x]>>8)==i) - photons[y][x] = 0; - } - - parts[i].type = PT_NONE; - parts[i].life = pfree; - pfree = i; -} - -void Simulation::part_change_type(int i, int x, int y, int t)//changes the type of particle number i, to t. This also changes pmap at the same time. -{ - if (x<0 || y<0 || x>=XRES || y>=YRES || i>=NPART || t<0 || t>=PT_NUM) - return; - if (!ptypes[t].enabled) - t = PT_NONE; - - if (parts[i].type == PT_STKM) - player.spwn = 0; - - if (parts[i].type == PT_STKM2) - player2.spwn = 0; - - if (parts[i].type == PT_FIGH) - { - fighters[(unsigned char)parts[i].tmp].spwn = 0; - fighcount--; - } - - parts[i].type = t; - if (t==PT_PHOT || t==PT_NEUT || t==PT_ELEC) - { - photons[y][x] = t|(i<<8); - if ((pmap[y][x]>>8)==i) - pmap[y][x] = 0; - } - else - { - pmap[y][x] = t|(i<<8); - if ((photons[y][x]>>8)==i) - photons[y][x] = 0; - } -} - -int Simulation::create_part(int p, int x, int y, int tv)//the function for creating a particle, use p=-1 for creating a new particle, -2 is from a brush, or a particle number to replace a particle. -{ - int i; - - int t = tv & 0xFF; - int v = (tv >> 8) & 0xFF; - - if (x<0 || y<0 || x>=XRES || y>=YRES || ((t<0 || t>=PT_NUM)&&t!=SPC_HEAT&&t!=SPC_COOL&&t!=SPC_AIR&&t!=SPC_VACUUM&&t!=SPC_PGRV&&t!=SPC_NGRV)) - return -1; - if (t>=0 && t>8].temp>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp + 0.1f, MIN_TEMP, MAX_TEMP); - } else if ((sdl_mod & (KMOD_SHIFT)) && (sdl_mod & (KMOD_CTRL))) { - parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp + 50.0f, MIN_TEMP, MAX_TEMP); - } else { - parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp + 4.0f, MIN_TEMP, MAX_TEMP); - } - } - if (t==SPC_COOL&&parts[pmap[y][x]>>8].temp>MIN_TEMP) - { - if ((pmap[y][x]&0xFF)==PT_PUMP || (pmap[y][x]&0xFF)==PT_GPMP) { - parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp - 0.1f, MIN_TEMP, MAX_TEMP); - } else if ((sdl_mod & (KMOD_SHIFT)) && (sdl_mod & (KMOD_CTRL))) { - parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp - 50.0f, MIN_TEMP, MAX_TEMP); - } else { - parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp - 4.0f, MIN_TEMP, MAX_TEMP); - } - } - return pmap[y][x]>>8; - } - else - { - return -1; - } - }*/ - if (t==SPC_AIR) - { - pv[y/CELL][x/CELL] += 0.03f; - if (y+CELL>8].ctype=PT_DUST; - } - if (!((pmap[y][x]&0xFF)==PT_INST||(ptypes[pmap[y][x]&0xFF].properties&PROP_CONDUCTS))) - return -1; - if (parts[pmap[y][x]>>8].life!=0) - return -1; - parts[pmap[y][x]>>8].type = PT_SPRK; - parts[pmap[y][x]>>8].life = 4; - parts[pmap[y][x]>>8].ctype = pmap[y][x]&0xFF; - pmap[y][x] = (pmap[y][x]&~0xFF) | PT_SPRK; - return pmap[y][x]>>8; - } - if (t==PT_SPAWN&&elementCount[PT_SPAWN]) - return -1; - if (t==PT_SPAWN2&&elementCount[PT_SPAWN2]) - return -1; - if (p==-1)//creating from anything but brush - { - if (pmap[y][x] || (bmap[y/CELL][x/CELL] && !eval_move(t, x, y, NULL))) - { - if ((pmap[y][x]&0xFF)!=PT_SPAWN&&(pmap[y][x]&0xFF)!=PT_SPAWN2) - { - if (t!=PT_STKM&&t!=PT_STKM2&&t!=PT_FIGH) - { - return -1; - } - } - } - if (pfree == -1) - return -1; - i = pfree; - pfree = parts[i].life; - } - else if (p==-2)//creating from brush - { - if (pmap[y][x]) - { - if (( - ((pmap[y][x]&0xFF)==PT_STOR&&!(ptypes[t].properties&TYPE_SOLID))|| - (pmap[y][x]&0xFF)==PT_CLNE|| - (pmap[y][x]&0xFF)==PT_BCLN|| - (pmap[y][x]&0xFF)==PT_CONV|| - ((pmap[y][x]&0xFF)==PT_PCLN&&t!=PT_PSCN&&t!=PT_NSCN)|| - ((pmap[y][x]&0xFF)==PT_PBCN&&t!=PT_PSCN&&t!=PT_NSCN) - )&&( - t!=PT_CLNE&&t!=PT_PCLN&& - t!=PT_BCLN&&t!=PT_STKM&& - t!=PT_STKM2&&t!=PT_PBCN&& - t!=PT_STOR&&t!=PT_FIGH) - ) - { - parts[pmap[y][x]>>8].ctype = t; - if (t==PT_LIFE && v>8].tmp = v; - } - return -1; - } - if (photons[y][x] && (t==PT_PHOT||t==PT_NEUT||t==PT_ELEC)) - return -1; - if (pfree == -1) - return -1; - i = pfree; - pfree = parts[i].life; - } - else if (p==-3)//skip pmap checks, e.g. for sing explosion - { - if (pfree == -1) - return -1; - i = pfree; - pfree = parts[i].life; - } - else - { - int oldX = (int)(parts[p].x+0.5f); - int oldY = (int)(parts[p].y+0.5f); - if ((pmap[oldY][oldX]>>8)==p) - pmap[oldY][oldX] = 0; - if ((photons[oldY][oldX]>>8)==p) - photons[oldY][oldX] = 0; - i = p; - } - - if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; - - parts[i].dcolour = 0; - if (t==PT_GLAS) - { - parts[i].pavg[1] = pv[y/CELL][x/CELL]; - } - else if (t==PT_QRTZ) - { - parts[i].pavg[1] = pv[y/CELL][x/CELL]; - } - else - { - parts[i].pavg[0] = 0.0f; - parts[i].pavg[1] = 0.0f; - } - if (t!=PT_STKM&&t!=PT_STKM2&&t!=PT_FIGH)//set everything to default values first, except for stickman. - { - parts[i].x = (float)x; - parts[i].y = (float)y; - parts[i].type = t; - parts[i].vx = 0; - parts[i].vy = 0; - parts[i].life = 0; - parts[i].ctype = 0; - parts[i].temp = ptypes[t].heat; - parts[i].tmp = 0; - parts[i].tmp2 = 0; - } - if (t==PT_LIGH && p==-2) - { - switch (gravityMode) - { - default: - case 0: - parts[i].tmp= 270+rand()%40-20; - break; - case 1: - parts[i].tmp = rand()%360; - break; - case 2: - parts[i].tmp = atan2(x-XCNTR, y-YCNTR)*(180.0f/M_PI)+90; - break; - } - parts[i].tmp2 = 4; - } - if (t==PT_SOAP) - { - parts[i].tmp = -1; - parts[i].tmp2 = -1; - } - //now set various properties that we want at spawn. - if (t==PT_ACID || t==PT_CAUS) - { - parts[i].life = 75; - } - /*Testing - if(t==PT_WOOD){ - parts[i].life = 150; - } - End Testing*/ - if (t==PT_WARP) { - parts[i].life = rand()%95+70; - } - if (t==PT_FUSE) { - parts[i].life = 50; - parts[i].tmp = 50; - } - /*if (ptypes[t].properties&PROP_LIFE) { - int r; - for (r = 0; r255 ? 255 : (colr<0 ? 0 : colr); - colg = colg>255 ? 255 : (colg<0 ? 0 : colg); - colb = colb>255 ? 255 : (colb<0 ? 0 : colb); - parts[i].dcolour = 0xFF000000 | (colr<<16) | (colg<<8) | colb; - } - elementCount[t]++; - return i; -} - -void Simulation::create_gain_photon(int pp)//photons from PHOT going through GLOW -{ - float xx, yy; - int i, lr, temp_bin, nx, ny; - - if (pfree == -1) - return; - i = pfree; - - lr = rand() % 2; - - if (lr) { - xx = parts[pp].x - 0.3*parts[pp].vy; - yy = parts[pp].y + 0.3*parts[pp].vx; - } else { - xx = parts[pp].x + 0.3*parts[pp].vy; - yy = parts[pp].y - 0.3*parts[pp].vx; - } - - nx = (int)(xx + 0.5f); - ny = (int)(yy + 0.5f); - - if (nx<0 || ny<0 || nx>=XRES || ny>=YRES) - return; - - if ((pmap[ny][nx] & 0xFF) != PT_GLOW) - return; - - pfree = parts[i].life; - if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; - - parts[i].type = PT_PHOT; - parts[i].life = 680; - parts[i].x = xx; - parts[i].y = yy; - parts[i].vx = parts[pp].vx; - parts[i].vy = parts[pp].vy; - parts[i].temp = parts[pmap[ny][nx] >> 8].temp; - parts[i].tmp = 0; - parts[i].pavg[0] = parts[i].pavg[1] = 0.0f; - photons[ny][nx] = PT_PHOT|(i<<8); - - temp_bin = (int)((parts[i].temp-273.0f)*0.25f); - if (temp_bin < 0) temp_bin = 0; - if (temp_bin > 25) temp_bin = 25; - parts[i].ctype = 0x1F << temp_bin; -} - -void Simulation::create_cherenkov_photon(int pp)//photons from NEUT going through GLAS -{ - int i, lr, nx, ny; - float r, eff_ior; - - if (pfree == -1) - return; - i = pfree; - - nx = (int)(parts[pp].x + 0.5f); - ny = (int)(parts[pp].y + 0.5f); - if ((pmap[ny][nx] & 0xFF) != PT_GLAS) - return; - - if (hypotf(parts[pp].vx, parts[pp].vy) < 1.44f) - return; - - pfree = parts[i].life; - if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; - - lr = rand() % 2; - - parts[i].type = PT_PHOT; - parts[i].ctype = 0x00000F80; - parts[i].life = 680; - parts[i].x = parts[pp].x; - parts[i].y = parts[pp].y; - parts[i].temp = parts[pmap[ny][nx] >> 8].temp; - parts[i].tmp = 0; - parts[i].pavg[0] = parts[i].pavg[1] = 0.0f; - photons[ny][nx] = PT_PHOT|(i<<8); - - if (lr) { - parts[i].vx = parts[pp].vx - 2.5f*parts[pp].vy; - parts[i].vy = parts[pp].vy + 2.5f*parts[pp].vx; - } else { - parts[i].vx = parts[pp].vx + 2.5f*parts[pp].vy; - parts[i].vy = parts[pp].vy - 2.5f*parts[pp].vx; - } - - /* photons have speed of light. no discussion. */ - r = 1.269 / hypotf(parts[i].vx, parts[i].vy); - parts[i].vx *= r; - parts[i].vy *= r; -} - -void Simulation::delete_part(int x, int y, int flags)//calls kill_part with the particle located at x,y -{ - unsigned i; - - if (x<0 || y<0 || x>=XRES || y>=YRES) - return; - if (photons[y][x]) { - i = photons[y][x]; - } else { - i = pmap[y][x]; - } - - if (!i) - return; - kill_part(i>>8); -} - -void Simulation::update_particles_i(int start, int inc) -{ - int i, j, x, y, t, nx, ny, r, surround_space, s, lt, rt, nt, nnx, nny, q, golnum, goldelete, z, neighbors, createdsomething; - float mv, dx, dy, ix, iy, lx, ly, nrx, nry, dp, ctemph, ctempl, gravtot; - int fin_x, fin_y, clear_x, clear_y, stagnant; - float fin_xf, fin_yf, clear_xf, clear_yf; - float nn, ct1, ct2, swappage; - float pt = R_TEMP; - float c_heat = 0.0f; - int h_count = 0; - int starti = (start*-1); - int surround[8]; - int surround_hconduct[8]; - int lighting_ok=1; - float pGravX, pGravY, pGravD; - - if (sys_pause&&lighting_recreate>0) - { - for (i=0; i<=parts_lastActiveIndex; i++) - { - if (parts[i].type==PT_LIGH && parts[i].tmp2>0) - { - lighting_ok=0; - break; - } - } - } - - if (lighting_ok) - lighting_recreate--; - - if (lighting_recreate<0) - lighting_recreate=1; - - if (lighting_recreate>21) - lighting_recreate=21; - - if (sys_pause&&!framerender)//do nothing if paused - return; - - //wire! - if(elementCount[PT_WIRE] > 0) - { - for (nx=0; nx>8].type==PT_WIRE) - parts[r>>8].tmp=parts[r>>8].ctype; - } - } - } - //game of life! - if (elementCount[PT_LIFE]>0&&++CGOL>=GSPEED)//GSPEED is frames per generation - { - int createdsomething = 0; - CGOL=0; - ISGOL=0; - for (nx=CELL; nx>8].type==PT_LIFE/* && parts[r>>8].ctype==golnum-1*/) - { - golnum = parts[r>>8].ctype+1; - if (golnum<=0 || golnum>NGOLALT) { - parts[r>>8].type = PT_NONE; - continue; - } - if (parts[r>>8].tmp == grule[golnum][9]-1) { - gol[nx][ny] = golnum; - for ( nnx=-1; nnx<2; nnx++) - { - for ( nny=-1; nny<2; nny++)//it will count itself as its own neighbor, which is needed, but will have 1 extra for delete check - { - rt = pmap[((ny+nny+YRES-3*CELL)%(YRES-2*CELL))+CELL][((nx+nnx+XRES-3*CELL)%(XRES-2*CELL))+CELL]; - if (!rt || (rt&0xFF)==PT_LIFE) - { - gol2[((nx+nnx+XRES-3*CELL)%(XRES-2*CELL))+CELL][((ny+nny+YRES-3*CELL)%(YRES-2*CELL))+CELL][golnum] ++; - gol2[((nx+nnx+XRES-3*CELL)%(XRES-2*CELL))+CELL][((ny+nny+YRES-3*CELL)%(YRES-2*CELL))+CELL][0] ++; - } - } - } - } else { - parts[r>>8].tmp --; - if (parts[r>>8].tmp<=0) - parts[r>>8].type = PT_NONE;//using kill_part makes it not work - } - } - //} - } - } - } - for (nx=CELL; nx=2&&gol2[nx][ny][golnum]>=(goldelete%2)+goldelete/2) - { - if (create_part(-1, nx, ny, PT_LIFE|((golnum-1)<<8))) - createdsomething = 1; - } - else if (gol[nx][ny]==golnum&&(grule[golnum][goldelete-1]==0||grule[golnum][goldelete-1]==2))//subtract 1 because it counted itself - { - if (parts[r>>8].tmp==grule[golnum][9]-1) - parts[r>>8].tmp --; - } - if (r && parts[r>>8].tmp<=0) - parts[r>>8].type = PT_NONE;//using kill_part makes it not work - } - for ( z = 0; z<=NGOL; z++) - gol2[nx][ny][z] = 0;//this improves performance A LOT compared to the memset, i was getting ~23 more fps with this. - } - } - //memset(gol2, 0, sizeof(gol2)); - } - if (ISWIRE==1)//wifi channel reseting - { - for ( q = 0; q<(int)(MAX_TEMP-73.15f)/100+2; q++) - if (!wireless[q][1]) - { - wireless[q][0] = 0; - } - else - wireless[q][1] = 0; - } - //the main particle loop function, goes over all particles. - for (i=0; i<=parts_lastActiveIndex; i++) - if (parts[i].type) - { - lx = parts[i].x; - ly = parts[i].y; - t = parts[i].type; - if (t<0 || t>=PT_NUM) - { - kill_part(i); - continue; - } - //printf("parts[%d].type: %d\n", i, parts[i].type); - - if (parts[i].life>0 && (ptypes[t].properties&PROP_LIFE_DEC)) - { - // automatically decrease life - parts[i].life--; - if (parts[i].life<=0 && (ptypes[t].properties&(PROP_LIFE_KILL_DEC|PROP_LIFE_KILL))) - { - // kill on change to no life - kill_part(i); - continue; - } - } - else if (parts[i].life<=0 && (ptypes[t].properties&PROP_LIFE_KILL)) - { - // kill if no life - kill_part(i); - continue; - } - - x = (int)(parts[i].x+0.5f); - y = (int)(parts[i].y+0.5f); - - //this kills any particle out of the screen, or in a wall where it isn't supposed to go - if (x=XRES-CELL || y>=YRES-CELL || - (bmap[y/CELL][x/CELL] && - (bmap[y/CELL][x/CELL]==WL_WALL || - bmap[y/CELL][x/CELL]==WL_WALLELEC || - bmap[y/CELL][x/CELL]==WL_ALLOWAIR || - (bmap[y/CELL][x/CELL]==WL_DESTROYALL) || - (bmap[y/CELL][x/CELL]==WL_ALLOWLIQUID && ptypes[t].falldown!=2) || - (bmap[y/CELL][x/CELL]==WL_ALLOWSOLID && ptypes[t].falldown!=1) || - (bmap[y/CELL][x/CELL]==WL_ALLOWGAS && !(ptypes[t].properties&TYPE_GAS)) || //&& ptypes[t].falldown!=0 && parts[i].type!=PT_FIRE && parts[i].type!=PT_SMKE && parts[i].type!=PT_HFLM) || - (bmap[y/CELL][x/CELL]==WL_ALLOWENERGY && !(ptypes[t].properties&TYPE_ENERGY)) || - (bmap[y/CELL][x/CELL]==WL_DETECT && (t==PT_METL || t==PT_SPRK)) || - (bmap[y/CELL][x/CELL]==WL_EWALL && !emap[y/CELL][x/CELL])) && (t!=PT_STKM) && (t!=PT_STKM2) && (t!=PT_FIGH))) - { - kill_part(i); - continue; - } - if (bmap[y/CELL][x/CELL]==WL_DETECT && emap[y/CELL][x/CELL]<8) - set_emap(x/CELL, y/CELL); - - //adding to velocity from the particle's velocity - vx[y/CELL][x/CELL] = vx[y/CELL][x/CELL]*ptypes[t].airloss + ptypes[t].airdrag*parts[i].vx; - vy[y/CELL][x/CELL] = vy[y/CELL][x/CELL]*ptypes[t].airloss + ptypes[t].airdrag*parts[i].vy; - - if (t==PT_GAS||t==PT_NBLE) - { - if (pv[y/CELL][x/CELL]<3.5f) - pv[y/CELL][x/CELL] += ptypes[t].hotair*(3.5f-pv[y/CELL][x/CELL]); - if (y+CELL= 0 && y-2 < YRES && (ptypes[t].properties&TYPE_LIQUID)) {//some heat convection for liquids - r = pmap[y-2][x]; - if (!(!r || parts[i].type != (r&0xFF))) { - if (parts[i].temp>parts[r>>8].temp) { - swappage = parts[i].temp; - parts[i].temp = parts[r>>8].temp; - parts[r>>8].temp = swappage; - } - } - } - - //heat transfer code - h_count = 0; -#ifdef REALHEAT - if (t&&(t!=PT_HSWC||parts[i].life==10)) - { - float c_Cm = 0.0f; -#else - if (t&&(t!=PT_HSWC||parts[i].life==10)&&ptypes[t].hconduct>(rand()%250)) - { - float c_Cm = 0.0f; -#endif - if (aheat_enable) - { - c_heat = (hv[y/CELL][x/CELL]-parts[i].temp)*0.04; - c_heat = restrict_flt(c_heat, -MAX_TEMP+MIN_TEMP, MAX_TEMP-MIN_TEMP); - parts[i].temp += c_heat; - hv[y/CELL][x/CELL] -= c_heat; - } - c_heat = 0.0f; - for (j=0; j<8; j++) - { - surround_hconduct[j] = i; - r = surround[j]; - if (!r) - continue; - rt = r&0xFF; - if (rt&&ptypes[rt].hconduct&&(rt!=PT_HSWC||parts[r>>8].life==10) - &&(t!=PT_FILT||(rt!=PT_BRAY&&rt!=PT_BIZR&&rt!=PT_BIZRG)) - &&(rt!=PT_FILT||(t!=PT_BRAY&&t!=PT_PHOT&&t!=PT_BIZR&&t!=PT_BIZRG))) - { - surround_hconduct[j] = r>>8; -#ifdef REALHEAT - c_heat += parts[r>>8].temp*96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight); - c_Cm += 96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight); -#else - c_heat += parts[r>>8].temp; -#endif - h_count++; - } - } -#ifdef REALHEAT - if (t == PT_PHOT) - pt = (c_heat+parts[i].temp*96.645)/(c_Cm+96.645); - else - pt = (c_heat+parts[i].temp*96.645/ptypes[t].hconduct*fabs(ptypes[t].weight))/(c_Cm+96.645/ptypes[t].hconduct*fabs(ptypes[t].weight)); - -#else - pt = (c_heat+parts[i].temp)/(h_count+1); -#endif - pt = parts[i].temp = restrict_flt(pt, MIN_TEMP, MAX_TEMP); - for (j=0; j<8; j++) - { - parts[surround_hconduct[j]].temp = pt; - } - - ctemph = ctempl = pt; - // change boiling point with pressure - if ((ptypes[t].state==ST_LIQUID && ptransitions[t].tht>-1 && ptransitions[t].tht-1 && ptransitions[t].tltptransitions[t].thv&&ptransitions[t].tht>-1) { - // particle type change due to high temperature - if (ptransitions[t].tht!=PT_NUM) - t = ptransitions[t].tht; - else if (t==PT_ICEI) { - if (parts[i].ctype>0&&parts[i].ctype274.0f) t = PT_WATR; - else s = 0; - } - else if (t==PT_SLTW) { - if (1>rand()%6) t = PT_SALT; - else t = PT_WTRV; - } - else s = 0; - } else if (ctempl-1) { - // particle type change due to low temperature - if (ptransitions[t].tlt!=PT_NUM) - t = ptransitions[t].tlt; - else if (t==PT_WTRV) { - if (pt<273.0f) t = PT_RIME; - else t = PT_DSTW; - } - else if (t==PT_LAVA) { - if (parts[i].ctype>0 && parts[i].ctype=ptransitions[PT_BMTL].thv) s = 0; - else if (ptransitions[parts[i].ctype].tht==PT_LAVA) { - if (pt>=ptransitions[parts[i].ctype].thv) s = 0; - } - else if (pt>=973.0f) s = 0; // freezing point for lava with any other (not listed in ptransitions as turning into lava) ctype - if (s) { - t = parts[i].ctype; - parts[i].ctype = PT_NONE; - if (t==PT_THRM) { - parts[i].tmp = 0; - t = PT_BMTL; - } - if (t==PT_PLUT) - { - parts[i].tmp = 0; - t = PT_LAVA; - } - } - } - else if (pt<973.0f) t = PT_STNE; - else s = 0; - } - else s = 0; - } - else s = 0; - if (s) { // particle type change occurred - if (t==PT_ICEI||t==PT_LAVA) - parts[i].ctype = parts[i].type; - if (!(t==PT_ICEI&&parts[i].ctype==PT_FRZW)) parts[i].life = 0; - if (ptypes[t].state==ST_GAS&&ptypes[parts[i].type].state!=ST_GAS) - pv[y/CELL][x/CELL] += 0.50f; - part_change_type(i,x,y,t); - if (t==PT_FIRE||t==PT_PLSM||t==PT_HFLM) - parts[i].life = rand()%50+120; - if (t==PT_LAVA) { - if (parts[i].ctype==PT_BRMT) parts[i].ctype = PT_BMTL; - else if (parts[i].ctype==PT_SAND) parts[i].ctype = PT_GLAS; - else if (parts[i].ctype==PT_BGLA) parts[i].ctype = PT_GLAS; - else if (parts[i].ctype==PT_PQRT) parts[i].ctype = PT_QRTZ; - parts[i].life = rand()%120+240; - } - if (t==PT_NONE) { - kill_part(i); - goto killed; - } - } - - pt = parts[i].temp = restrict_flt(parts[i].temp, MIN_TEMP, MAX_TEMP); - if (t==PT_LAVA) { - parts[i].life = restrict_flt((parts[i].temp-700)/7, 0.0f, 400.0f); - if (parts[i].ctype==PT_THRM&&parts[i].tmp>0) - { - parts[i].tmp--; - parts[i].temp = 3500; - } - if (parts[i].ctype==PT_PLUT&&parts[i].tmp>0) - { - parts[i].tmp--; - parts[i].temp = MAX_TEMP; - } - } - } - } - - if (t==PT_LIFE) - { - parts[i].temp = restrict_flt(parts[i].temp-50.0f, MIN_TEMP, MAX_TEMP); - //ISGOL=1;//means there is a life particle on screen - } - if (t==PT_WIRE) - { - //wire_placed = 1; - } - //spark updates from walls - if ((ptypes[t].properties&PROP_CONDUCTS) || t==PT_SPRK) - { - nx = x % CELL; - if (nx == 0) - nx = x/CELL - 1; - else if (nx == CELL-1) - nx = x/CELL + 1; - else - nx = x/CELL; - ny = y % CELL; - if (ny == 0) - ny = y/CELL - 1; - else if (ny == CELL-1) - ny = y/CELL + 1; - else - ny = y/CELL; - if (nx>=0 && ny>=0 && nx2.5f) - { - parts[i].life = rand()%80+180; - parts[i].temp = restrict_flt(ptypes[PT_FIRE].heat + (ptypes[t].flammable/2), MIN_TEMP, MAX_TEMP); - t = PT_FIRE; - part_change_type(i,x,y,t); - pv[y/CELL][x/CELL] += 0.25f * CFDS; - } - - - s = 1; - gravtot = fabs(gravy[(y/CELL)*(XRES/CELL)+(x/CELL)])+fabs(gravx[(y/CELL)*(XRES/CELL)+(x/CELL)]); - if (pv[y/CELL][x/CELL]>ptransitions[t].phv&&ptransitions[t].pht>-1) { - // particle type change due to high pressure - if (ptransitions[t].pht!=PT_NUM) - t = ptransitions[t].pht; - else if (t==PT_BMTL) { - if (pv[y/CELL][x/CELL]>2.5f) - t = PT_BRMT; - else if (pv[y/CELL][x/CELL]>1.0f && parts[i].tmp==1) - t = PT_BRMT; - else s = 0; - } - else s = 0; - } else if (pv[y/CELL][x/CELL]-1) { - // particle type change due to low pressure - if (ptransitions[t].plt!=PT_NUM) - t = ptransitions[t].plt; - else s = 0; - } else if (gravtot>(ptransitions[t].phv/4.0f)&&ptransitions[t].pht>-1) { - // particle type change due to high gravity - if (ptransitions[t].pht!=PT_NUM) - t = ptransitions[t].pht; - else if (t==PT_BMTL) { - if (gravtot>0.625f) - t = PT_BRMT; - else if (gravtot>0.25f && parts[i].tmp==1) - t = PT_BRMT; - else s = 0; - } - else s = 0; - } else s = 0; - if (s) { // particle type change occurred - parts[i].life = 0; - part_change_type(i,x,y,t); - if (t==PT_FIRE) - parts[i].life = rand()%50+120; - if (t==PT_NONE) { - kill_part(i); - goto killed; - } - } - - //call the particle update function, if there is one -#ifdef LUACONSOLE - if (ptypes[t].update_func && lua_el_mode[t] != 2) -#else - if (ptypes[t].update_func) -#endif - { - if ((*(ptypes[t].update_func))(this, i,x,y,surround_space,nt, parts, pmap)) - continue; - } -#ifdef LUACONSOLE - if(lua_el_mode[t]) - { - if(luacon_part_update(t,i,x,y,surround_space,nt)) - continue; - } -#endif - if (legacy_enable)//if heat sim is off - update_legacy_all(this, i,x,y,surround_space,nt, parts, pmap); - -killed: - if (parts[i].type == PT_NONE)//if its dead, skip to next particle - continue; - - if (!parts[i].vx&&!parts[i].vy)//if its not moving, skip to next particle, movement code it next - continue; - -#if defined(WIN32) && !defined(__GNUC__) - mv = max(fabsf(parts[i].vx), fabsf(parts[i].vy)); -#else - mv = fmaxf(fabsf(parts[i].vx), fabsf(parts[i].vy)); -#endif - if (mv < ISTP) - { - clear_x = x; - clear_y = y; - clear_xf = parts[i].x; - clear_yf = parts[i].y; - fin_xf = clear_xf + parts[i].vx; - fin_yf = clear_yf + parts[i].vy; - fin_x = (int)(fin_xf+0.5f); - fin_y = (int)(fin_yf+0.5f); - } - else - { - // interpolate to see if there is anything in the way - dx = parts[i].vx*ISTP/mv; - dy = parts[i].vy*ISTP/mv; - fin_xf = parts[i].x; - fin_yf = parts[i].y; - while (1) - { - mv -= ISTP; - fin_xf += dx; - fin_yf += dy; - fin_x = (int)(fin_xf+0.5f); - fin_y = (int)(fin_yf+0.5f); - if (mv <= 0.0f) - { - // nothing found - fin_xf = parts[i].x + parts[i].vx; - fin_yf = parts[i].y + parts[i].vy; - fin_x = (int)(fin_xf+0.5f); - fin_y = (int)(fin_yf+0.5f); - clear_xf = fin_xf-dx; - clear_yf = fin_yf-dy; - clear_x = (int)(clear_xf+0.5f); - clear_y = (int)(clear_yf+0.5f); - break; - } - if (fin_x=XRES-CELL || fin_y>=YRES-CELL || pmap[fin_y][fin_x] || (bmap[fin_y/CELL][fin_x/CELL] && (bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || bmap[fin_y/CELL][fin_x/CELL]==WL_DETECT || !eval_move(t,fin_x,fin_y,NULL)))) - { - // found an obstacle - clear_xf = fin_xf-dx; - clear_yf = fin_yf-dy; - clear_x = (int)(clear_xf+0.5f); - clear_y = (int)(clear_yf+0.5f); - break; - } - - } - } - - stagnant = parts[i].flags & FLAG_STAGNANT; - parts[i].flags &= ~FLAG_STAGNANT; - - if ((t==PT_PHOT||t==PT_NEUT||t==PT_ELEC)) { - if (t == PT_PHOT) { - rt = pmap[fin_y][fin_x] & 0xFF; - lt = pmap[y][x] & 0xFF; - - r = eval_move(PT_PHOT, fin_x, fin_y, NULL); - if (((rt==PT_GLAS && lt!=PT_GLAS) || (rt!=PT_GLAS && lt==PT_GLAS)) && r) { - if (!get_normal_interp(REFRACT|t, parts[i].x, parts[i].y, parts[i].vx, parts[i].vy, &nrx, &nry)) { - kill_part(i); - continue; - } - - r = get_wavelength_bin(&parts[i].ctype); - if (r == -1) { - kill_part(i); - continue; - } - nn = GLASS_IOR - GLASS_DISP*(r-15)/15.0f; - nn *= nn; - nrx = -nrx; - nry = -nry; - if (rt==PT_GLAS && lt!=PT_GLAS) - nn = 1.0f/nn; - ct1 = parts[i].vx*nrx + parts[i].vy*nry; - ct2 = 1.0f - (nn*nn)*(1.0f-(ct1*ct1)); - if (ct2 < 0.0f) { - // total internal reflection - parts[i].vx -= 2.0f*ct1*nrx; - parts[i].vy -= 2.0f*ct1*nry; - fin_xf = parts[i].x; - fin_yf = parts[i].y; - fin_x = x; - fin_y = y; - } else { - // refraction - ct2 = sqrtf(ct2); - ct2 = ct2 - nn*ct1; - parts[i].vx = nn*parts[i].vx + ct2*nrx; - parts[i].vy = nn*parts[i].vy + ct2*nry; - } - } - } - if (stagnant)//FLAG_STAGNANT set, was reflected on previous frame - { - // cast coords as int then back to float for compatibility with existing saves - if (!do_move(i, x, y, (float)fin_x, (float)fin_y)) { - kill_part(i); - continue; - } - } - else if (!do_move(i, x, y, fin_xf, fin_yf)) - { - // reflection - parts[i].flags |= FLAG_STAGNANT; - if (t==PT_NEUT && 100>(rand()%1000)) - { - kill_part(i); - continue; - } - r = pmap[fin_y][fin_x]; - - if ((r & 0xFF) == PT_PIPE && !(parts[r>>8].tmp&0xFF)) - { - parts[r>>8].tmp = (parts[r>>8].tmp&~0xFF) | parts[i].type; - parts[r>>8].temp = parts[i].temp; - parts[r>>8].flags = parts[i].life; - parts[r>>8].pavg[0] = parts[i].tmp; - parts[r>>8].pavg[1] = parts[i].ctype; - kill_part(i); - continue; - } - - // this should be replaced with a particle type attribute ("photwl" or something) - if ((r & 0xFF) == PT_PSCN) parts[i].ctype = 0x00000000; - if ((r & 0xFF) == PT_NSCN) parts[i].ctype = 0x00000000; - if ((r & 0xFF) == PT_SPRK) parts[i].ctype = 0x00000000; - if ((r & 0xFF) == PT_COAL) parts[i].ctype = 0x00000000; - if ((r & 0xFF) == PT_BCOL) parts[i].ctype = 0x00000000; - if ((r & 0xFF) == PT_PLEX) parts[i].ctype &= 0x1F00003E; - if ((r & 0xFF) == PT_NITR) parts[i].ctype &= 0x0007C000; - if ((r & 0xFF) == PT_NBLE) parts[i].ctype &= 0x3FFF8000; - if ((r & 0xFF) == PT_LAVA) parts[i].ctype &= 0x3FF00000; - if ((r & 0xFF) == PT_ACID) parts[i].ctype &= 0x1FE001FE; - if ((r & 0xFF) == PT_DUST) parts[i].ctype &= 0x3FFFFFC0; - if ((r & 0xFF) == PT_SNOW) parts[i].ctype &= 0x03FFFFFF; - if ((r & 0xFF) == PT_GOO) parts[i].ctype &= 0x3FFAAA00; - if ((r & 0xFF) == PT_PLNT) parts[i].ctype &= 0x0007C000; - if ((r & 0xFF) == PT_PLUT) parts[i].ctype &= 0x001FCE00; - if ((r & 0xFF) == PT_URAN) parts[i].ctype &= 0x003FC000; - - if (get_normal_interp(t, parts[i].x, parts[i].y, parts[i].vx, parts[i].vy, &nrx, &nry)) { - dp = nrx*parts[i].vx + nry*parts[i].vy; - parts[i].vx -= 2.0f*dp*nrx; - parts[i].vy -= 2.0f*dp*nry; - // leave the actual movement until next frame so that reflection of fast particles and refraction happen correctly - } else { - if (t!=PT_NEUT) - kill_part(i); - continue; - } - if (!parts[i].ctype&&t!=PT_NEUT&&t!=PT_ELEC) { - kill_part(i); - continue; - } - } - } - else if (ptypes[t].falldown==0) - { - // gasses and solids (but not powders) - if (!do_move(i, x, y, fin_xf, fin_yf)) - { - // can't move there, so bounce off - // TODO - if (fin_x>x+ISTP) fin_x=x+ISTP; - if (fin_xy+ISTP) fin_y=y+ISTP; - if (fin_y= rand()%400)//checking stagnant is cool, but then it doesn't update when you change it later. - { - if (!flood_water(x,y,i,y, parts[i].tmp2)) - goto movedone; - } - // liquids and powders - if (!do_move(i, x, y, fin_xf, fin_yf)) - { - if (fin_x!=x && do_move(i, x, y, fin_xf, clear_yf)) - { - parts[i].vx *= ptypes[t].collision; - parts[i].vy *= ptypes[t].collision; - } - else if (fin_y!=y && do_move(i, x, y, clear_xf, fin_yf)) - { - parts[i].vx *= ptypes[t].collision; - parts[i].vy *= ptypes[t].collision; - } - else - { - s = 1; - r = (rand()%2)*2-1; - if ((clear_x!=x || clear_y!=y || nt || surround_space) && - (fabsf(parts[i].vx)>0.01f || fabsf(parts[i].vy)>0.01f)) - { - // allow diagonal movement if target position is blocked - // but no point trying this if particle is stuck in a block of identical particles - dx = parts[i].vx - parts[i].vy*r; - dy = parts[i].vy + parts[i].vx*r; - if (fabsf(dy)>fabsf(dx)) - mv = fabsf(dy); - else - mv = fabsf(dx); - dx /= mv; - dy /= mv; - if (do_move(i, x, y, clear_xf+dx, clear_yf+dy)) - { - parts[i].vx *= ptypes[t].collision; - parts[i].vy *= ptypes[t].collision; - goto movedone; - } - swappage = dx; - dx = dy*r; - dy = -swappage*r; - if (do_move(i, x, y, clear_xf+dx, clear_yf+dy)) - { - parts[i].vx *= ptypes[t].collision; - parts[i].vy *= ptypes[t].collision; - goto movedone; - } - } - if (ptypes[t].falldown>1 && !ngrav_enable && gravityMode==0 && parts[i].vy>fabsf(parts[i].vx)) - { - s = 0; - // stagnant is true if FLAG_STAGNANT was set for this particle in previous frame - if (!stagnant || nt) //nt is if there is an something else besides the current particle type, around the particle - rt = 30;//slight less water lag, although it changes how it moves a lot - else - rt = 10; - for (j=clear_x+r; j>=0 && j>=clear_x-rt && j0) - r = 1; - else - r = -1; - if (s==1) - for (j=ny+r; j>=0 && j=ny-rt && j1 && fabsf(pGravX*parts[i].vx+pGravY*parts[i].vy)>fabsf(pGravY*parts[i].vx-pGravX*parts[i].vy)) - { - float nxf, nyf, prev_pGravX, prev_pGravY, ptGrav = ptypes[t].gravity; - s = 0; - // stagnant is true if FLAG_STAGNANT was set for this particle in previous frame - if (!stagnant || nt) //nt is if there is an something else besides the current particle type, around the particle - rt = 30;//slight less water lag, although it changes how it moves a lot - else - rt = 10; - nxf = clear_xf; - nyf = clear_yf; - for (j=0;jfabsf(pGravX)) - mv = fabsf(pGravY); - else - mv = fabsf(pGravX); - if (mv<0.0001f) break; - pGravX /= mv; - pGravY /= mv; - if (j) - { - nxf += r*(pGravY*2.0f-prev_pGravY); - nyf += -r*(pGravX*2.0f-prev_pGravX); - } - else - { - nxf += r*pGravY; - nyf += -r*pGravX; - } - prev_pGravX = pGravX; - prev_pGravY = pGravY; - nx = (int)(nxf+0.5f); - ny = (int)(nyf+0.5f); - if (nx<0 || ny<0 || nx>=XRES || ny >=YRES) - break; - if ((pmap[ny][nx]&0xFF)!=t || bmap[ny/CELL][nx/CELL]) - { - s = do_move(i, x, y, nxf, nyf); - if (s) - { - nx = (int)(parts[i].x+0.5f); - ny = (int)(parts[i].y+0.5f); - break; - } - if (bmap[ny/CELL][nx/CELL]!=WL_STREAM) - break; - } - } - if (s==1) - { - clear_x = nx; - clear_y = ny; - for (j=0;jfabsf(pGravX)) - mv = fabsf(pGravY); - else - mv = fabsf(pGravX); - if (mv<0.0001f) break; - pGravX /= mv; - pGravY /= mv; - nxf += pGravX; - nyf += pGravY; - nx = (int)(nxf+0.5f); - ny = (int)(nyf+0.5f); - if (nx<0 || ny<0 || nx>=XRES || ny>=YRES) - break; - if ((pmap[ny][nx]&0xFF)!=t || bmap[ny/CELL][nx/CELL]) - { - s = do_move(i, clear_x, clear_y, nxf, nyf); - if (s || bmap[ny/CELL][nx/CELL]!=WL_STREAM) - break; - } - } - } - else if (s==-1) {} // particle is out of bounds - else if ((clear_x!=x||clear_y!=y) && do_move(i, x, y, clear_xf, clear_yf)) {} - else parts[i].flags |= FLAG_STAGNANT; - parts[i].vx *= ptypes[t].collision; - parts[i].vy *= ptypes[t].collision; - } - else - { - // if interpolation was done, try moving to last clear position - if ((clear_x!=x||clear_y!=y) && do_move(i, x, y, clear_xf, clear_yf)) {} - else parts[i].flags |= FLAG_STAGNANT; - parts[i].vx *= ptypes[t].collision; - parts[i].vy *= ptypes[t].collision; - } - } - } - } -movedone: - continue; - } -} - -void Simulation::update_particles()//doesn't update the particles themselves, but some other things -{ - int i, j, x, y, t, nx, ny, r, cr,cg,cb, l = -1; - float lx, ly; - int lastPartUsed = 0; - int lastPartUnused = -1; -#ifdef MT - int pt = 0, pc = 0; - pthread_t *InterThreads; -#endif - - air->update_air(); - - memset(pmap, 0, sizeof(pmap)); - memset(photons, 0, sizeof(photons)); - NUM_PARTS = 0; - for (i=0; i<=parts_lastActiveIndex; i++)//the particle loop that resets the pmap/photon maps every frame, to update them. - { - if (parts[i].type) - { - t = parts[i].type; - x = (int)(parts[i].x+0.5f); - y = (int)(parts[i].y+0.5f); - if (x>=0 && y>=0 && x=NPART-1) pfree = -1; - else pfree = parts_lastActiveIndex+1; - } - else - { - if (parts_lastActiveIndex>=NPART-1) parts[lastPartUnused].life = -1; - else parts[lastPartUnused].life = parts_lastActiveIndex+1; - } - parts_lastActiveIndex = lastPartUsed; - if (!sys_pause||framerender) - { - for (y=0; y=XRES || ny<0 || ny>=YRES) - break; - addpixel(vid, nx, ny, 255, 255, 255, 64); - i = nx/CELL; - j = ny/CELL; - lx += vx[j][i]*0.125f; - ly += vy[j][i]*0.125f; - if (bmap[j][i]==WL_STREAM && i!=x && j!=y) - break; - } - drawtext(vid, x*CELL, y*CELL-2, "\x8D", 255, 255, 255, 128); - } -*/ -} - -Simulation::Simulation() -{ - //Create and attach gravity simulation - grav = new Gravity(); - //Give air sim references to our data - grav->bmap = bmap; - //Gravity sim gives us maps to use - gravx = grav->gravx; - gravy = grav->gravy; - gravp = grav->gravp; - gravmap = grav->gravmap; - - //Create and attach air simulation - air = new Air(); - //Give air sim references to our data - air->bmap = bmap; - air->emap = emap; - air->fvx = fvx; - air->fvy = fvy; - //Air sim gives us maps to use - vx = air->vx; - vy = air->vy; - pv = air->pv; - hv = air->hv; - - //ptypes[0] = {"", PIXPACK(0x000000), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, 0, R_TEMP+0.0f +273.15f, 251, "Erases particles.", ST_NONE, 0, NULL, NULL}; - //ptypes[1] = {"DUST", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 1, 85, 0, R_TEMP+0.0f +273.15f, 70, "Very light dust. Flammable.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, NULL, &graphics_DUST}; - //ptypes[2] = {"WATR", PIXPACK(0x2030D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, 0, R_TEMP-2.0f +273.15f, 29, "Liquid. Conducts electricity. Freezes. Extinguishes fires.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_WATR, NULL}; - -#define SC_WALL 0 -#define SC_ELEC 1 -#define SC_POWERED 2 -#define SC_EXPLOSIVE 3 -#define SC_GAS 4 -#define SC_LIQUID 5 -#define SC_POWDERS 6 -#define SC_SOLIDS 7 -#define SC_NUCLEAR 8 -#define SC_SPECIAL 9 -#define SC_LIFE 10 -#define SC_TOOL 11 -#define SC_CRACKER 13 -#define SC_CRACKER2 14 -#define SC_TOTAL 12 - - part_type ptypest[PT_NUM] = - { - //Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description - {"", PIXPACK(0x000000), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Erases particles.", ST_NONE, 0, NULL, NULL}, - {"DUST", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 1, 85, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Very light dust. Flammable.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, NULL, &graphics_DUST}, - {"WATR", PIXPACK(0x2030D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Liquid. Conducts electricity. Freezes. Extinguishes fires.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_WATR, NULL}, - {"OIL", PIXPACK(0x404010), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 20, 0, 0, 5, 1, 1, 20, SC_LIQUID, R_TEMP+0.0f +273.15f, 42, "Liquid. Flammable.", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, - {"FIRE", PIXPACK(0xFF1000), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.001f * CFDS, 1, 0, 0, 0, 1, 1, 1, 2, SC_EXPLOSIVE, R_TEMP+400.0f+273.15f, 88, "Ignites flammable materials. Heats air.", ST_GAS, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, &update_PYRO, &graphics_FIRE}, - {"STNE", PIXPACK(0xA0A0A0), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 1, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Heavy particles. Meltable.", ST_SOLID, TYPE_PART, NULL, NULL}, - {"LAVA", PIXPACK(0xE05010), 0.3f, 0.02f * CFDS, 0.95f, 0.80f, 0.0f, 0.15f, 0.00f, 0.0003f * CFDS, 2, 0, 0, 0, 2, 1, 1, 45, SC_LIQUID, R_TEMP+1500.0f+273.15f, 60, "Heavy liquid. Ignites flammable materials. Solidifies when cold.", ST_LIQUID, TYPE_LIQUID|PROP_LIFE_DEC, &update_PYRO, &graphics_LAVA}, - {"GUN", PIXPACK(0xC0C0D0), 0.7f, 0.02f * CFDS, 0.94f, 0.80f, -0.1f, 0.1f, 0.00f, 0.000f * CFDS, 1, 600, 1, 0, 10, 1, 1, 85, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 97, "Light dust. Explosive.", ST_SOLID, TYPE_PART, NULL, NULL}, - {"NITR", PIXPACK(0x20E010), 0.5f, 0.02f * CFDS, 0.92f, 0.97f, 0.0f, 0.2f, 0.00f, 0.000f * CFDS, 2, 1000, 2, 0, 3, 1, 1, 23, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 50, "Liquid. Pressure sensitive explosive.", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, - {"CLNE", PIXPACK(0xFFD010), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Solid. Duplicates any particles it touches.", ST_SOLID, TYPE_SOLID, &update_CLNE, NULL}, - {"GAS", PIXPACK(0xE0FF20), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 0.75f, 0.001f * CFDS, 0, 600, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+2.0f +273.15f, 42, "Gas. Diffuses. Flammable. Liquefies under pressure.", ST_GAS, TYPE_GAS, NULL, NULL}, - {"C-4", PIXPACK(0xD080E0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 1000, 2, 50, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Solid. Pressure sensitive explosive.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, NULL, NULL}, - {"GOO", PIXPACK(0x804000), 0.0f, 0.00f * CFDS, 0.97f, 0.50f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 12, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 75, "Solid. Deforms and disappears under pressure.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_GOO, NULL}, - {"ICE", PIXPACK(0xA0C0FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0003f* CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP-50.0f+273.15f, 46, "Solid. Freezes water. Crushes under pressure. Cools down air.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_ICEI, NULL}, - {"METL", PIXPACK(0x404060), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Solid. Conducts electricity. Meltable.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, NULL, NULL}, - {"SPRK", PIXPACK(0xFFFF80), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.001f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Electricity. Conducted by metal and water.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SPRK, &graphics_SPRK}, - {"SNOW", PIXPACK(0xC0E0FF), 0.7f, 0.01f * CFDS, 0.96f, 0.90f, -0.1f, 0.05f, 0.01f, -0.00005f* CFDS,1, 0, 0, 0, 20, 1, 1, 50, SC_POWDERS, R_TEMP-30.0f+273.15f, 46, "Light particles.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_ICEI, NULL}, - {"WOOD", PIXPACK(0xC0A040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 0, 15, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 164, "Solid. Flammable.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, NULL, NULL}, - {"NEUT", PIXPACK(0x20E0FF), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.01f, 0.002f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_NUCLEAR, R_TEMP+4.0f +273.15f, 60, "Neutrons. Interact with matter in odd ways.", ST_GAS, TYPE_ENERGY|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_NEUT, &graphics_NEUT}, - {"PLUT", PIXPACK(0x407020), 0.4f, 0.01f * CFDS, 0.99f, 0.95f, 0.0f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 90, SC_NUCLEAR, R_TEMP+4.0f +273.15f, 251, "Heavy particles. Fissile. Generates neutrons under pressure.", ST_SOLID, TYPE_PART|PROP_NEUTPENETRATE|PROP_RADIOACTIVE, &update_PLUT, NULL}, - {"PLNT", PIXPACK(0x0CAC00), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 0, 10, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 65, "Plant, drinks water and grows.", ST_SOLID, TYPE_SOLID|PROP_NEUTPENETRATE|PROP_LIFE_DEC, &update_PLNT, NULL}, - {"ACID", PIXPACK(0xED55FF), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 40, 0, 0, 1, 1, 1, 10, SC_LIQUID, R_TEMP+0.0f +273.15f, 34, "Dissolves almost everything.", ST_LIQUID, TYPE_LIQUID|PROP_DEADLY, &update_ACID, &graphics_ACID}, - {"VOID", PIXPACK(0x790B0B), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0003f* CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Hole, will drain away any particles.", ST_SOLID, TYPE_SOLID, NULL, NULL}, - {"WTRV", PIXPACK(0xA0A0FF), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, -0.1f, 0.75f, 0.0003f * CFDS, 0, 0, 0, 0, 4, 1, 1, 1, SC_GAS, R_TEMP+100.0f+273.15f, 48, "Steam, heats up air, produced from hot water.", ST_GAS, TYPE_GAS, &update_WTRV, NULL}, - {"CNCT", PIXPACK(0xC0C0C0), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 55, SC_POWDERS, R_TEMP+0.0f +273.15f, 100, "Concrete, stronger than stone.", ST_SOLID, TYPE_PART|PROP_HOT_GLOW, NULL, NULL}, - {"DSTW", PIXPACK(0x1020C0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP-2.0f +273.15f, 23, "Distilled water, does not conduct electricity.", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE, &update_DSTW, NULL}, - {"SALT", PIXPACK(0xFFFFFF), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 1, 1, 1, 75, SC_POWDERS, R_TEMP+0.0f +273.15f, 110, "Salt, dissolves in water.", ST_SOLID, TYPE_PART, NULL, NULL}, - {"SLTW", PIXPACK(0x4050F0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 35, SC_LIQUID, R_TEMP+0.0f +273.15f, 75, "Saltwater, conducts electricity, difficult to freeze.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_SLTW, NULL}, - {"DMND", PIXPACK(0xCCFFFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 186, "Diamond. Indestructible.", ST_SOLID, TYPE_SOLID, NULL, NULL}, - {"BMTL", PIXPACK(0x505070), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Breakable metal.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, &update_BMTL, NULL}, - {"BRMT", PIXPACK(0x705060), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 211, "Broken metal.", ST_SOLID, TYPE_PART|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, &update_BRMT, NULL}, - {"PHOT", PIXPACK(0xFFFFFF), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_NUCLEAR, R_TEMP+900.0f+273.15f, 251, "Photons. Travel in straight lines.", ST_GAS, TYPE_ENERGY|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_PHOT, &graphics_PHOT}, - {"URAN", PIXPACK(0x707020), 0.4f, 0.01f * CFDS, 0.99f, 0.95f, 0.0f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 90, SC_NUCLEAR, R_TEMP+30.0f+273.15f, 251, "Heavy particles. Generates heat under pressure.", ST_SOLID, TYPE_PART | PROP_RADIOACTIVE, &update_URAN, NULL}, - {"WAX", PIXPACK(0xF0F0BB), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 10, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 44, "Wax. Melts at moderately high temperatures.", ST_SOLID, TYPE_SOLID, NULL, NULL}, - {"MWAX", PIXPACK(0xE0E0AA), 0.3f, 0.02f * CFDS, 0.95f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000001f* CFDS,2, 5, 0, 0, 2, 1, 1, 25, SC_LIQUID, R_TEMP+28.0f+273.15f, 44, "Liquid Wax.", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, - {"PSCN", PIXPACK(0x805050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "P-Type Silicon, Will transfer current to any conductor.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, - {"NSCN", PIXPACK(0x505080), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "N-Type Silicon, Will not transfer current to P-Type Silicon.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, - {"LN2", PIXPACK(0x80A0DF), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 0, 1, 1, 30, SC_LIQUID, 70.15f, 70, "Liquid Nitrogen. Very cold.", ST_SOLID, TYPE_LIQUID, NULL, NULL}, - {"INSL", PIXPACK(0x9EA3B6), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 7, 0, 0, 10, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 0, "Insulator, does not conduct heat or electricity.", ST_SOLID, TYPE_SOLID, NULL, NULL}, - {"VACU", PIXPACK(0x303030), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, -0.01f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+70.0f+273.15f, 255, "Vacuum, sucks in other particles and heats up.", ST_NONE, TYPE_SOLID, NULL, NULL}, - {"VENT", PIXPACK(0xEFEFEF), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.010f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP-16.0f+273.15f, 255, "Air vent, creates pressure and pushes other particles away.", ST_NONE, TYPE_SOLID, NULL, NULL}, - {"RBDM", PIXPACK(0xCCCCCC), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 1000, 1, 50, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 240, "Rubidium, explosive, especially on contact with water, low melting point", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, - {"LRBD", PIXPACK(0xAAAAAA), 0.3f, 0.02f * CFDS, 0.95f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000001f* CFDS,2, 1000, 1, 0, 2, 1, 1, 45, SC_EXPLOSIVE, R_TEMP+45.0f+273.15f, 170, "Liquid Rubidium.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, - {"NTCT", PIXPACK(0x505040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Semi-conductor. Only conducts electricity when hot (More than 100C)", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, &update_NPTCT, NULL}, - {"SAND", PIXPACK(0xFFD090), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 1, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Sand, Heavy particles. Meltable.", ST_SOLID, TYPE_PART, NULL, NULL}, - {"GLAS", PIXPACK(0x404040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 150, "Solid. Meltable. Shatters under pressure", ST_SOLID, TYPE_SOLID | PROP_NEUTPASS | PROP_HOT_GLOW | PROP_SPARKSETTLE, &update_GLAS, NULL}, - {"PTCT", PIXPACK(0x405050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Semi-conductor. Only conducts electricity when cold (Less than 100C)", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, &update_NPTCT, NULL}, - {"BGLA", PIXPACK(0x606060), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Broken Glass, Heavy particles. Meltable. Bagels.", ST_SOLID, TYPE_PART | PROP_HOT_GLOW, NULL, NULL}, - {"THDR", PIXPACK(0xFFFFA0), 0.0f, 0.00f * CFDS, 1.0f, 0.30f, -0.99f, 0.6f, 0.62f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_EXPLOSIVE, 9000.0f +273.15f, 1, "Lightning! Very hot, inflicts damage upon most materials, transfers current to metals.", ST_NONE, TYPE_ENERGY, &update_THDR, &graphics_THDR}, - {"PLSM", PIXPACK(0xBB99FF), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.30f, 0.001f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, 10000.0f +273.15f, 5, "Plasma, extremely hot.", ST_NONE, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, &update_PYRO, &graphics_PLSM}, - {"ETRD", PIXPACK(0x404040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Electrode. Creates a surface that allows Plasma arcs. (Use sparingly)", ST_NONE, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, - {"NICE", PIXPACK(0xC0E0FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0005f* CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, 35.0f, 46, "Nitrogen Ice.", ST_SOLID, TYPE_SOLID, NULL, NULL}, - {"NBLE", PIXPACK(0xEB4917), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 0.75f, 0.001f * CFDS, 0, 0, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+2.0f +273.15f, 106, "Noble Gas. Diffuses. Conductive. Ionizes into plasma when introduced to electricity", ST_GAS, TYPE_GAS|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, - {"BTRY", PIXPACK(0x858505), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Solid. Generates Electricity.", ST_SOLID, TYPE_SOLID, &update_BTRY, NULL}, - {"LCRY", PIXPACK(0x505050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Liquid Crystal. Changes colour when charged. (PSCN Charges, NSCN Discharges)", ST_SOLID, TYPE_SOLID, &update_LCRY, &graphics_LCRY}, - {"STKM", PIXPACK(0x000000), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Stickman. Don't kill him!", ST_NONE, 0, &update_STKM, &graphics_STKM}, - {"SWCH", PIXPACK(0x103B11), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Solid. Only conducts when switched on. (PSCN switches on, NSCN switches off)", ST_SOLID, TYPE_SOLID, &update_SWCH, &graphics_SWCH}, - {"SMKE", PIXPACK(0x222222), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.001f * CFDS, 1, 0, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+320.0f+273.15f, 88, "Smoke", ST_SOLID, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, NULL, &graphics_SMKE}, - {"DESL", PIXPACK(0x440000), 1.0f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.0f, 0.0f * CFDS, 2, 2, 0, 0, 5, 1, 1, 15, SC_LIQUID, R_TEMP+0.0f +273.15f, 42, "Liquid. Explodes under high pressure and temperatures", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, - {"COAL", PIXPACK(0x222222), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 200, "Solid. Burns slowly.", ST_SOLID, TYPE_SOLID, &update_COAL, &graphics_COAL}, - {"LOXY", PIXPACK(0x80A0EF), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 5000, 0, 0, 0, 1, 1, 30, SC_LIQUID, 80.0f, 70, "Liquid Oxygen. Very cold. Reacts with fire", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, - {"OXYG", PIXPACK(0x80A0FF), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 3.0f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+0.0f +273.15f, 70, "Gas. Ignites easily.", ST_GAS, TYPE_GAS, &update_O2, NULL}, - {"INWR", PIXPACK(0x544141), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Insulated Wire. Doesn't conduct to metal or semiconductors.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, - {"YEST", PIXPACK(0xEEE0C0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 15, 0, 0, 30, 1, 1, 80, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Yeast, grows when warm (~37C).", ST_SOLID, TYPE_PART, &update_YEST, NULL}, - {"DYST", PIXPACK(0xBBB0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 20, 0, 0, 30, 0, 1, 80, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Dead Yeast.", ST_SOLID, TYPE_PART, NULL, NULL}, - {"THRM", PIXPACK(0xA08090), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 211, "Thermite. Burns at extremely high temperature.", ST_SOLID, TYPE_PART, &update_THRM, NULL}, - {"GLOW", PIXPACK(0x445464), 0.3f, 0.02f * CFDS, 0.98f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 2, 1, 1, 40, SC_LIQUID, R_TEMP+20.0f+273.15f, 44, "Glow, Glows under pressure", ST_LIQUID, TYPE_LIQUID|PROP_LIFE_DEC, &update_GLOW, &graphics_GLOW}, - {"BRCK", PIXPACK(0x808080), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Brick, breakable building material.", ST_SOLID, TYPE_SOLID|PROP_HOT_GLOW, NULL, NULL}, - {"CFLM", PIXPACK(0x8080FF), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.0005f * CFDS, 1, 0, 0, 0, 1, 1, 1, 2, SC_EXPLOSIVE, 0.0f, 88, "Sub-zero flame.", ST_LIQUID, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, NULL, &graphics_HFLM}, - {"FIRW", PIXPACK(0xFFA040), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, -0.99f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 55, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 70, "Fireworks!", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_FIRW, &graphics_FIRW}, - {"FUSE", PIXPACK(0x0A5706), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 200, "Solid. Burns slowly. Ignites at somewhat high temperatures and electricity.", ST_SOLID, TYPE_SOLID, &update_FUSE, NULL}, - {"FSEP", PIXPACK(0x63AD5F), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 70, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Fuse Powder. See FUSE.", ST_SOLID, TYPE_PART, &update_FSEP, NULL}, - {"AMTR", PIXPACK(0x808080), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.00f, 0.10f, 1.00f, 0.0000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_NUCLEAR, R_TEMP+0.0f +273.15f, 70, "Anti-Matter, Destroys a majority of particles", ST_NONE, TYPE_PART, &update_AMTR, NULL}, //Maybe TYPE_ENERGY? - {"BCOL", PIXPACK(0x333333), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Broken Coal. Heavy particles. See COAL", ST_SOLID, TYPE_PART, &update_BCOL, NULL}, - {"PCLN", PIXPACK(0x3B3B0A), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Solid. When activated, duplicates any particles it touches.", ST_NONE, TYPE_SOLID, &update_PCLN, &graphics_PCLN}, - {"HSWC", PIXPACK(0x3B0A0A), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Heat switch. Conducts Heat only when activated", ST_NONE, TYPE_SOLID, &update_HSWC, &graphics_HSWC}, - {"IRON", PIXPACK(0x707070), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 50, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Rusts with salt, can be used for electrolysis of WATR", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, &update_IRON, NULL}, - {"MORT", PIXPACK(0xE0E0E0), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.01f, 0.002f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_CRACKER2, R_TEMP+4.0f +273.15f, 60, "Steam Train.", ST_NONE, TYPE_PART, &update_MORT, NULL}, - {"LIFE", PIXPACK(0x0CAC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 1, 100, SC_LIFE, 9000.0f, 40, "Game Of Life! B3/S23", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, &graphics_LIFE}, - {"DLAY", PIXPACK(0x753590), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, 4.0f+273.15f, 0, "Conducts with temperature-dependent delay. (use HEAT/COOL).", ST_SOLID, TYPE_SOLID, &update_DLAY, &graphics_DLAY}, - {"CO2", PIXPACK(0x666666), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.1f, 0.1f, 1.0f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+273.15f, 88, "Carbon Dioxide", ST_GAS, TYPE_GAS, &update_CO2, NULL}, - {"DRIC", PIXPACK(0xE0E0E0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0005f* CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, 172.65f, 2, "Dry Ice.", ST_SOLID, TYPE_SOLID, NULL, NULL}, - {"BUBW", PIXPACK(0x2030D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Carbonated water. Conducts electricity. Freezes. Extinguishes fires.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_CBNW, &graphics_CBNW}, - {"STOR", PIXPACK(0x50DFDF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Solid. Stores a single particle, releases when charged with PSCN, also passes to PIPE", ST_NONE, TYPE_SOLID, &update_STOR, &graphics_STOR}, - {"PVOD", PIXPACK(0x792020), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Solid. When activated, destroys entering particles", ST_NONE, TYPE_SOLID, &update_PVOD, &graphics_PVOD}, - {"CONV", PIXPACK(0x0AAB0A), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Solid. Converts whatever touches it into its ctype.", ST_NONE, TYPE_SOLID, &update_CONV, NULL}, - {"CAUS", PIXPACK(0x80FFA0), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 1.50f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+0.0f +273.15f, 70, "Caustic Gas, acts like Acid", ST_GAS, TYPE_GAS|PROP_DEADLY, &update_CAUS, NULL}, - {"LIGH", PIXPACK(0xFFFFC0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 0, "More realistic lightning. Set pen size to set the size of the lightning.", ST_SOLID, TYPE_SOLID, &update_LIGH, &graphics_LIGH}, - {"TESC", PIXPACK(0x707040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Tesla coil!", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, NULL, NULL}, - {"DEST", PIXPACK(0xFF3311), -0.05f, 0.00f * CFDS, 0.95f, 0.95f, -0.1f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 101, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 150, "More destructive Bomb.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_DEST, &graphics_DEST}, - {"SPNG", PIXPACK(0xFFBE30), 0.00f, 0.00f * CFDS, 0.00f, 1.00f, 0.00f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 1, 30, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "A sponge, absorbs water.", ST_SOLID, TYPE_SOLID, &update_SPNG, &graphics_SPNG}, - {"RIME", PIXPACK(0xCCCCCC), 0.00f, 0.00f * CFDS, 0.00f, 1.00f, 0.00f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 30, 1, 1, 100, SC_CRACKER2, 243.15f, 100, "Not quite Ice", ST_SOLID, TYPE_SOLID, &update_RIME, NULL}, - {"FOG", PIXPACK(0xAAAAAA), 0.8f, 0.00f * CFDS, 0.4f, 0.70f, -0.1f, 0.0f, 0.99f, 0.000f * CFDS, 0, 0, 0, 0, 30, 1, 1, 1, SC_CRACKER2, 243.15f, 100, "Not quite Steam", ST_GAS, TYPE_GAS|PROP_LIFE_DEC, &update_FOG, NULL}, - {"BCLN", PIXPACK(0xFFD040), 0.0f, 0.00f * CFDS, 0.97f, 0.50f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 12, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Breakable Clone.", ST_NONE, TYPE_SOLID|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_BCLN, NULL}, - {"LOVE", PIXPACK(0xFF30FF), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.0f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_CRACKER2, 373.0f, 40, "Love...", ST_GAS, TYPE_SOLID, &update_MISC, NULL}, - {"DEUT", PIXPACK(0x00153F), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 31, SC_NUCLEAR, R_TEMP-2.0f +273.15f, 251, "Deuterium oxide. Volume changes with temp, radioactive with neutrons.", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE, &update_DEUT, &graphics_DEUT}, - {"WARP", PIXPACK(0x000000), 0.8f, 0.00f * CFDS, 0.9f, 0.70f, -0.1f, 0.0f, 3.00f, 0.000f * CFDS, 0, 0, 0, 0, 30, 1, 1, 1, SC_NUCLEAR, R_TEMP +273.15f, 100, "Displaces other elements.", ST_GAS, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, &update_WARP, NULL}, - {"PUMP", PIXPACK(0x0A0A3B), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 10, 1, 1, 100, SC_POWERED, 273.15f, 0, "Changes pressure to its temp when activated. (use HEAT/COOL).", ST_SOLID, TYPE_SOLID, &update_PUMP, &graphics_PUMP}, - {"FWRK", PIXPACK(0x666666), 0.4f, 0.01f * CFDS, 0.99f, 0.95f, 0.0f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 1, 1, 1, 97, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 100, "First fireworks made, activated by heat/neutrons.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_FWRK, NULL}, - {"PIPE", PIXPACK(0x444444), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, 273.15f, 0, "Moves elements around, read FAQ on website for help.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_PIPE, &graphics_PIPE}, - {"FRZZ", PIXPACK(0xC0E0FF), 0.7f, 0.01f * CFDS, 0.96f, 0.90f, -0.1f, 0.05f, 0.01f, -0.00005f* CFDS,1, 0, 0, 0, 20, 1, 1, 50, SC_POWDERS, 90.0f, 46, "FREEZE", ST_SOLID, TYPE_PART, &update_FRZZ, NULL}, - {"FRZW", PIXPACK(0x1020C0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_CRACKER2, 120.0f, 29, "FREEZE WATER", ST_LIQUID, TYPE_LIQUID||PROP_LIFE_DEC, &update_FRZW, NULL}, - {"GRAV", PIXPACK(0xFFE0A0), 0.7f, 0.00f * CFDS, 1.00f, 1.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 1, 85, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Very light dust. Changes colour based on velocity.", ST_SOLID, TYPE_PART, &update_MISC, &graphics_GRAV}, - {"BIZR", PIXPACK(0x00FF77), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP+0.0f +273.15f, 29, "Bizarre... contradicts the normal state changes.", ST_LIQUID, TYPE_LIQUID, &update_BIZR, &graphics_BIZR}, - {"BIZG", PIXPACK(0x00FFBB), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 2.75f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 1, SC_CRACKER2, R_TEMP-200.0f+273.15f, 42, "Bizarre gas", ST_GAS, TYPE_GAS, &update_BIZR, &graphics_BIZR}, - {"BIZS", PIXPACK(0x00E455), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_CRACKER2, R_TEMP+300.0f+273.15f, 251, "Bizarre solid", ST_SOLID, TYPE_SOLID, &update_BIZR, &graphics_BIZR}, - {"INST", PIXPACK(0x404039), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Instantly conducts, PSCN to charge, NSCN to take.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, NULL, NULL}, - {"ISOZ", PIXPACK(0xAA30D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 0, 1, 1, 24, SC_NUCLEAR, R_TEMP-2.0f +273.15f, 29, "Radioactive liquid", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE, &update_ISZ, NULL}, - {"ISZS", PIXPACK(0x662089), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0007f* CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_NUCLEAR, 140.00f, 251, "Solid form of ISOZ, slowly decays.", ST_SOLID, TYPE_SOLID, &update_ISZ, NULL}, - {"PRTI", PIXPACK(0xEB5917), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.005f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 0, "Portal IN. Things go in here, now with channels (same as WIFI)", ST_SOLID, TYPE_SOLID, &update_PRTI, &graphics_PRTI}, - {"PRTO", PIXPACK(0x0020EB), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.005f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 0, "Portal OUT. Things come out here, now with channels (same as WIFI)", ST_SOLID, TYPE_SOLID, &update_PRTO, &graphics_PRTO}, - {"PSTE", PIXPACK(0xAA99AA), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 31, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Colloid, Hardens under pressure", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, - {"PSTS", PIXPACK(0x776677), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 20, 0, 1, 100, SC_CRACKER, R_TEMP-2.0f +273.15f, 29, "Solid form of PSTE, temporary", ST_SOLID, TYPE_SOLID, NULL, NULL}, - {"ANAR", PIXPACK(0xFFFFEE), -0.7f, -0.02f * CFDS, 0.96f, 0.80f, 0.1f, -0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 85, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Very light dust. Behaves opposite gravity", ST_SOLID, TYPE_PART, &update_ANAR, NULL}, - {"VINE", PIXPACK(0x079A00), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 0, 10, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 65, "Vine, grows", ST_SOLID, TYPE_SOLID, &update_VINE, NULL}, - {"INVS", PIXPACK(0x00CCCC), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 15, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 164, "Invisible to everything while under pressure.", ST_SOLID, TYPE_SOLID | PROP_NEUTPASS, NULL, &graphics_INVS}, - {"EQVE", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 0, 1, 85, SC_CRACKER2, R_TEMP+0.0f +273.15f, 70, "Shared velocity test", ST_SOLID, TYPE_PART, NULL, NULL}, - {"SPWN2", PIXPACK(0xAAAAAA), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 0, "STK2 spawn point", ST_SOLID, TYPE_SOLID, &update_SPAWN2, NULL}, - {"SPWN", PIXPACK(0xAAAAAA), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 0, "STKM spawn point", ST_SOLID, TYPE_SOLID, &update_SPAWN, NULL}, - {"SHLD", PIXPACK(0xAAAAAA), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 0, "Shield, spark it to grow", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD1, NULL}, - {"SHD2", PIXPACK(0x777777), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_CRACKER2, R_TEMP+0.0f +273.15f, 0, "Shield lvl 2", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD2, NULL}, - {"SHD3", PIXPACK(0x444444), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_CRACKER2, R_TEMP+0.0f +273.15f, 0, "Shield lvl 3", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD3, NULL}, - {"SHD4", PIXPACK(0x212121), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_CRACKER2, R_TEMP+0.0f +273.15f, 0, "Shield lvl 4", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD4, NULL}, - {"LOLZ", PIXPACK(0x569212), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.0f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_CRACKER2, 373.0f, 40, "Lolz", ST_GAS, TYPE_SOLID, &update_MISC, NULL}, - {"WIFI", PIXPACK(0x40A060), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 2, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 0, "Wireless transmitter, color coded.", ST_SOLID, TYPE_SOLID, &update_WIFI, &graphics_WIFI}, - {"FILT", PIXPACK(0x000056), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Filter for photons, changes the color.", ST_SOLID, TYPE_SOLID, NULL, &graphics_FILT}, - {"ARAY", PIXPACK(0xFFBB00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 0, "Ray Emitter. Rays create points when they collide", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_ARAY, NULL}, - {"BRAY", PIXPACK(0xFFFFFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 0, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Ray Point. Rays create points when they collide", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC|PROP_LIFE_KILL, NULL, &graphics_BRAY}, - {"STK2", PIXPACK(0x000000), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Stickman. Don't kill him!", ST_NONE, 0, &update_STKM2, &graphics_STKM2}, - {"BOMB", PIXPACK(0xFFF288), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 20, 1, 1, 30, SC_EXPLOSIVE, R_TEMP-2.0f +273.15f, 29, "Bomb.", ST_NONE, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC|PROP_SPARKSETTLE, &update_BOMB, &graphics_BOMB}, - {"C-5", PIXPACK(0x2050E0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Cold explosive", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, &update_C5, NULL}, - {"SING", PIXPACK(0x242424), 0.7f, 0.36f * CFDS, 0.96f, 0.80f, 0.1f, 0.12f, 0.00f, -0.001f * CFDS, 1, 0, 0, 0, 0, 1, 1, 86, SC_NUCLEAR, R_TEMP+0.0f +273.15f, 70, "Singularity", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_SING, NULL}, - {"QRTZ", PIXPACK(0xAADDDD), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 3, "Quartz, breakable mineral. Conducts but becomes brittle at lower temperatures.", ST_SOLID, TYPE_SOLID|PROP_HOT_GLOW|PROP_LIFE_DEC, &update_QRTZ, &graphics_QRTZ}, - {"PQRT", PIXPACK(0x88BBBB), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.27f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 3, "Broken quartz.", ST_SOLID, TYPE_PART| PROP_HOT_GLOW, &update_QRTZ, &graphics_QRTZ}, - {"EMP", PIXPACK(0x66AAFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 3, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 121, "Breaks activated electronics.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_EMP, &graphics_EMP}, - {"BREL", PIXPACK(0x707060), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.18f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 211, "Broken electronics", ST_SOLID, TYPE_PART|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, NULL, NULL}, - {"ELEC", PIXPACK(0xDFEFFF), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_NUCLEAR, R_TEMP+200.0f+273.15f, 251, "Electrons", ST_GAS, TYPE_ENERGY|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_ELEC, &graphics_ELEC}, - {"ACEL", PIXPACK(0x0099CC), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Accelerator", ST_NONE, TYPE_SOLID, &update_ACEL, &graphics_ACEL}, - {"DCEL", PIXPACK(0x99CC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Decelerator", ST_NONE, TYPE_SOLID, &update_DCEL, &graphics_DCEL}, - {"TNT", PIXPACK(0xC05050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Explosive.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, &update_BANG, NULL}, - {"IGNC", PIXPACK(0xC0B050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Ignition cord.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE | PROP_SPARKSETTLE | PROP_LIFE_KILL, &update_IGNT, NULL}, - {"BOYL", PIXPACK(0x0A3200), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 0.18f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+2.0f +273.15f, 42, "Boyle, variable pressure gas. Expands when heated.", ST_GAS, TYPE_GAS, &update_BOYL, NULL}, - /*FREE*/{"LOTE", PIXPACK(0xFF0000), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Behaves kinda like Living on the Edge S3458/B37/4", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, - /*FREE*/{"FRG2", PIXPACK(0x00FF00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Like Frogs rule S124/B3/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, - /*FREE*/{"STAR", PIXPACK(0x0000FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Like Star Wars rule S3456/B278/6", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, - /*FREE*/{"FROG", PIXPACK(0x00AA00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Frogs S12/B34/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, - /*FREE*/{"BRAN", PIXPACK(0xCCCC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Brian 6 S6/B246/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, - /*FREE*/{"WIND", PIXPACK(0x101010), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_SPECIAL, 0.0f, 40, "", ST_NONE, ST_NONE, NULL, NULL}, - {"HYGN", PIXPACK(0x5070FF), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.10f, 0.00f, 3.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+0.0f +273.15f, 251, "Combines with O2 to make WATR", ST_GAS, TYPE_GAS, &update_H2, NULL}, - {"SOAP", PIXPACK(0xF5F5DC), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 35, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Soap. Creates bubbles.", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE|PROP_LIFE_DEC, &update_SOAP, NULL}, - {"BHOL", PIXPACK(0x202020), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 186, "Black hole (Requires newtonian gravity)", ST_SOLID, TYPE_SOLID, &update_NBHL, NULL}, - {"WHOL", PIXPACK(0xFFFFFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 186, "White hole (Requires newtonian gravity)", ST_SOLID, TYPE_SOLID, &update_NWHL, NULL}, - {"MERC", PIXPACK(0x736B6D), 0.4f, 0.04f * CFDS, 0.94f, 0.80f, 0.0f, 0.3f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 91, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Mercury. Volume changes with temperature, Conductive.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_NEUTABSORB|PROP_LIFE_DEC, &update_MERC, NULL}, - {"PBCN", PIXPACK(0x3B1D0A), 0.0f, 0.00f * CFDS, 0.97f, 0.50f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 12, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Powered breakable clone", ST_NONE, TYPE_SOLID, &update_PBCN, &graphics_PBCN}, - {"GPMP", PIXPACK(0x0A3B3B), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, 0.0f +273.15f, 0, "Changes gravity to its temp when activated. (use HEAT/COOL).", ST_NONE, TYPE_SOLID, &update_GPMP, &graphics_GPMP}, - {"CLST", PIXPACK(0xE4A4A4), 0.7f, 0.02f * CFDS, 0.94f, 0.95f, 0.0f, 0.2f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 55, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Clay dust. Produces paste when mixed with water.", ST_SOLID, TYPE_PART, &update_CLST, &graphics_CLST}, - {"WIRE", PIXPACK(0xFFCC00), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 250, "WireWorld wires.",ST_SOLID,TYPE_SOLID,&update_WIRE, &graphics_WIRE}, - {"GBMB", PIXPACK(0x1144BB), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 20, 1, 1, 30, SC_EXPLOSIVE, R_TEMP-2.0f +273.15f, 29, "Sticks to first object it touches then produces strong gravity push.", ST_NONE, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_GBMB, &graphics_GBMB}, - {"FIGH", PIXPACK(0x000000), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Fighter. Tries to kill stickmen.", ST_NONE, 0, &update_FIGH, &graphics_FIGH}, - //Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description - }; - memcpy(ptypes, ptypest, sizeof(part_type)*PT_NUM); - -#define IPL -257.0f -#define IPH 257.0f -#define ITL MIN_TEMP-1 -#define ITH MAX_TEMP+1 -// no transition (PT_NONE means kill part) -#define NT -1 -// special transition - lava ctypes etc need extra code, which is only found and run if ST is given -#define ST PT_NUM -part_transition ptransitionst[PT_NUM] = -{ // if low pressure if high pressure if low temperature if high temperature - // Name plv plt phv pht tlv tlt thv tht - /* NONE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* DUST */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* WATR */ {IPL, NT, IPH, NT, 273.15f,PT_ICEI, 373.0f, PT_WTRV}, - /* OIL */ {IPL, NT, IPH, NT, ITL, NT, 333.0f, PT_GAS}, - /* FIRE */ {IPL, NT, IPH, NT, ITL, NT, 2773.0f,PT_PLSM}, - /* STNE */ {IPL, NT, IPH, NT, ITL, NT, 983.0f, PT_LAVA}, - /* LAVA */ {IPL, NT, IPH, NT, 2573.15f,ST, ITH, NT}, // 2573.15f is highest melt pt of possible ctypes - /* GUN */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, - /* NITR */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, - /* CLNE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* GAS */ {IPL, NT, 6.0f, PT_OIL, ITL, NT, 573.0f, PT_FIRE}, - /* C-4 */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, - /* GOO */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* ICE */ {IPL, NT, 0.8f, PT_SNOW, ITL, NT, 233.0f, ST}, - /* METL */ {IPL, NT, IPH, NT, ITL, NT, 1273.0f,PT_LAVA}, - /* SPRK */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SNOW */ {IPL, NT, IPH, NT, ITL, NT, 273.0f, PT_WATR}, - /* WOOD */ {IPL, NT, IPH, NT, ITL, NT, 873.0f, PT_FIRE}, - /* NEUT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PLUT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PLNT */ {IPL, NT, IPH, NT, ITL, NT, 573.0f, PT_FIRE}, - /* ACID */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* VOID */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* WTRV */ {IPL, NT, IPH, NT, 371.0f, ST, ITH, NT}, - /* CNCT */ {IPL, NT, IPH, NT, ITL, NT, 1123.0f,PT_LAVA}, - /* DSTW */ {IPL, NT, IPH, NT, 273.15f,PT_ICEI, 373.0f, PT_WTRV}, - /* SALT */ {IPL, NT, IPH, NT, ITL, NT, 1173.0f,PT_LAVA}, - /* SLTW */ {IPL, NT, IPH, NT, 233.0f, PT_ICEI, 483.0f, ST}, - /* DMND */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* BMTL */ {IPL, NT, 1.0f, ST, ITL, NT, 1273.0f,PT_LAVA}, - /* BRMT */ {IPL, NT, IPH, NT, ITL, NT, 1273.0f,PT_LAVA}, - /* PHOT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* URAN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* WAX */ {IPL, NT, IPH, NT, ITL, NT, 319.0f, PT_MWAX}, - /* MWAX */ {IPL, NT, IPH, NT, 318.0f, PT_WAX, 673.0f, PT_FIRE}, - /* PSCN */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, - /* NSCN */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, - /* LN2 */ {IPL, NT, IPH, NT, 63.0f, PT_NICE, 77.0f, PT_NONE}, - /* INSL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* VACU */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* VENT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* RBDM */ {IPL, NT, IPH, NT, ITL, NT, 312.0f, PT_LRBD}, - /* LRBD */ {IPL, NT, IPH, NT, 311.0f, PT_RBDM, 961.0f, PT_FIRE}, - /* NTCT */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, - /* SAND */ {IPL, NT, IPH, NT, ITL, NT, 1973.0f,PT_LAVA}, - /* GLAS */ {IPL, NT, IPH, NT, ITL, NT, 1973.0f,PT_LAVA}, - /* PTCT */ {IPL, NT, IPH, NT, ITL, NT, 1414.0f,PT_LAVA}, - /* BGLA */ {IPL, NT, IPH, NT, ITL, NT, 1973.0f,PT_LAVA}, - /* THDR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PLSM */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* ETRD */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* NICE */ {IPL, NT, IPH, NT, ITL, NT, 63.1f, PT_LNTG}, - /* NBLE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* BTRY */ {IPL, NT, IPH, NT, ITL, NT, 2273.0f,PT_PLSM}, - /* LCRY */ {IPL, NT, IPH, NT, ITL, NT, 1273.0f,PT_BGLA}, - /* STKM */ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE}, - /* SWCH */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SMKE */ {IPL, NT, IPH, NT, ITL, NT, 625.0f, PT_FIRE}, - /* DESL */ {IPL, NT, 5.0f, PT_FIRE, ITL, NT, 335.0f, PT_FIRE}, - /* COAL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* LO2 */ {IPL, NT, IPH, NT, ITL, NT, 90.1f, PT_O2}, - /* O2 */ {IPL, NT, IPH, NT, 90.0f, PT_LO2, ITH, NT}, - /* INWR */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, - /* YEST */ {IPL, NT, IPH, NT, ITL, NT, 373.0f, PT_DYST}, - /* DYST */ {IPL, NT, IPH, NT, ITL, NT, 473.0f, PT_DUST}, - /* THRM */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* GLOW */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* BRCK */ {IPL, NT, 8.8f, PT_STNE, ITL, NT, 1223.0f,PT_LAVA}, - /* CFLM */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* FIRW */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* FUSE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* FSEP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* AMTR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* BCOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PCLN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* HSWC */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* IRON */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, - /* MORT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* LIFE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* DLAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* CO2 */ {IPL, NT, IPH, NT, 194.65f,PT_DRIC, ITH, NT}, - /* DRIC */ {IPL, NT, IPH, NT, ITL, NT, 195.65f,PT_CO2}, - /* CBNW */ {IPL, NT, IPH, NT, 273.15f,PT_ICEI, 373.0f, PT_WTRV}, - /* STOR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* STOR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SPNG */ {IPL, NT, IPH, NT, ITL, NT, 2730.0f,PT_FIRE}, - /* RIME */ {IPL, NT, IPH, NT, ITL, NT, 273.15f,PT_WATR}, - /* FOG */ {IPL, NT, IPH, NT, ITL, NT, 373.15f,PT_WTRV}, - /* BCLN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* LOVE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* DEUT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* WARP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PUMP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* FWRK */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PIPE */ {IPL, NT, 10.0f, PT_BRMT, ITL, NT, ITH, NT}, - /* FRZZ */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* FRZW */ {IPL, NT, IPH, NT, ITL, NT, 53.0f, PT_ICEI}, - /* GRAV */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* BIZR */ {IPL, NT, IPH, NT, 100.0f, PT_BIZRG, 400.0f, PT_BIZRS}, - /* BIZRG*/ {IPL, NT, IPH, NT, ITL, NT, 100.0f, PT_BIZR},//, 400.0f, PT_BIZRS}, - /* BIZRS*/ {IPL, NT, IPH, NT, 400.0f, PT_BIZR, ITH, NT},// 100.0f, PT_BIZRG}, - /* INST */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* ISOZ */ {IPL, NT, IPH, NT, 160.0f, PT_ISZS, ITH, NT}, - /* ISZS */ {IPL, NT, IPH, NT, ITL, NT, 300.0f, PT_ISOZ}, - /* PRTI */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PRTO */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PSTE */ {IPL, NT, 0.5f, PT_PSTS, ITL, NT, 747.0f, PT_BRCK}, - /* PSTS */ {0.5f, PT_PSTE, IPH, NT, ITL, NT, ITH, NT}, - /* ANAR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* VINE */ {IPL, NT, IPH, NT, ITL, NT, 573.0f, PT_FIRE}, - /* INVS */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* EQVE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SPWN2*/ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SPAWN*/ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SHLD1*/ {IPL, NT, 7.0f, PT_NONE, ITL, NT, ITH, NT}, - /* SHLD2*/ {IPL, NT, 15.0f, PT_NONE, ITL, NT, ITH, NT}, - /* SHLD3*/ {IPL, NT, 25.0f, PT_NONE, ITL, NT, ITH, NT}, - /* SHLD4*/ {IPL, NT, 40.0f, PT_NONE, ITL, NT, ITH, NT}, - /* LOlZ */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* WIFI */ {IPL, NT, 15.0f, PT_BRMT, ITL, NT, ITH, NT}, - /* FILT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* ARAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* BRAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* STKM2*/ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE}, - /* BOMB */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* C-5 */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SING */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* QRTZ */ {IPL, NT, IPH, NT, ITL, NT, 2573.15f,PT_LAVA}, - /* PQRT */ {IPL, NT, IPH, NT, ITL, NT, 2573.15f,PT_LAVA}, - /* EMP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* BREL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* ELEC */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* ACEL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* DCEL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* TNT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* IGNP */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, - /* BOYL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* WIND */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* H2 */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* SOAP */ {IPL, NT, IPH, NT, ITL, NT, ITL, NT}, - /* NBHL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* NWHL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* MERC */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* PBCN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* GPMP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* CLST */ {IPL, NT, IPH, NT, ITL, NT, 1256.0f, PT_LAVA}, - /* WIRE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* GBMB */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, - /* FIGH */ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE}, -}; -#undef IPL -#undef IPH -#undef ITL -#undef ITH -#undef NT -#undef ST*/ - memcpy(ptransitions, ptransitionst, sizeof(part_transition) * PT_NUM); - init_can_move(); - clear_sim(); -} diff --git a/src/Simulation.h b/src/Simulation.h deleted file mode 100644 index b3c51af..0000000 --- a/src/Simulation.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Simulation.h - * - * Created on: Jan 2, 2012 - * Author: Simon - */ - -#ifndef SIMULATION_H_ -#define SIMULATION_H_ -#include -#include "Config.h" -#include "Renderer.h" -#include "Graphics.h" -#include "Elements.h" -#include "misc.h" - -#define CHANNELS ((int)(MAX_TEMP-73)/100+2) - -class Simulation; -class Renderer; -class Gravity; -class Air; - -struct Particle -{ - int type; - int life, ctype; - float x, y, vx, vy; - float temp; - float pavg[2]; - int flags; - int tmp; - int tmp2; - unsigned int dcolour; -}; -typedef struct Particle Particle; - -struct sign -{ - int x,y,ju; - char text[256]; -}; -typedef struct sign sign; - -struct part_type -{ - char *name; - pixel pcolors; - float advection; - float airdrag; - float airloss; - float loss; - float collision; - float gravity; - float diffusion; - float hotair; - int falldown; - int flammable; - int explosive; - int meltable; - int hardness; - int menu; - int enabled; - int weight; - int menusection; - float heat; - unsigned char hconduct; - char *descs; - char state; - unsigned int properties; - int (*update_func) (UPDATE_FUNC_ARGS); - int (*graphics_func) (GRAPHICS_FUNC_ARGS); -}; -typedef struct part_type part_type; - -struct part_transition -{ - float plv; // transition occurs if pv is lower than this - int plt; - float phv; // transition occurs if pv is higher than this - int pht; - float tlv; // transition occurs if t is lower than this - int tlt; - float thv; // transition occurs if t is higher than this - int tht; -}; -typedef struct part_transition part_transition; - -struct playerst -{ - char comm; //command cell - char pcomm; //previous command - int elem; //element power - float legs[16]; //legs' positions - float accs[8]; //accelerations - char spwn; //if stick man was spawned - unsigned int frames; //frames since last particle spawn - used when spawning LIGH -}; -typedef struct playerst playerst; - -struct wall_type -{ - pixel colour; - pixel eglow; // if emap set, add this to fire glow - int drawstyle; - const char *descs; -}; -typedef struct wall_type wall_type; - -struct gol_menu -{ - const char *name; - pixel colour; - int goltype; - const char *description; -}; -typedef struct gol_menu gol_menu; - -//#ifdef _cplusplus -class Simulation -{ -private: -public: - - Gravity * grav; - Air * air; - part_type ptypes[PT_NUM]; - part_transition ptransitions[PT_NUM]; - wall_type wtypes[UI_WALLCOUNT]; - gol_menu gmenu[NGOL]; - int goltype[NGOL]; - int grule[NGOL+1][10]; - playerst player; - playerst player2; - playerst fighters[256]; //255 is the maximum number of fighters - unsigned char fighcount; //Contains the number of fighters - int lighting_recreate; - int gravwl_timeout; - Particle portalp[CHANNELS][8][80]; - Particle emptyparticle; - int portal_rx[8]; - int portal_ry[8]; - int wireless[CHANNELS][2]; - char can_move[PT_NUM][PT_NUM]; - int parts_lastActiveIndex;// = NPART-1; - int pfree; - int NUM_PARTS; - int elementCount[PT_NUM]; - int ISWIRE; - sign * signs; - //Gol sim - int CGOL; - int ISGOL; - int GSPEED; - unsigned char gol[XRES][YRES]; - unsigned char gol2[XRES][YRES][NGOL+1]; - //Air sim - float (*vx)[XRES/CELL]; - float (*vy)[XRES/CELL]; - float (*pv)[XRES/CELL]; - float (*hv)[XRES/CELL]; - //Gravity sim - float *gravx;//gravx[(YRES/CELL) * (XRES/CELL)]; - float *gravy;//gravy[(YRES/CELL) * (XRES/CELL)]; - float *gravp;//gravp[(YRES/CELL) * (XRES/CELL)]; - float *gravmap;//gravmap[(YRES/CELL) * (XRES/CELL)]; - //Walls - unsigned char bmap[YRES/CELL][XRES/CELL]; - unsigned char emap[YRES/CELL][XRES/CELL]; - float fvx[YRES/CELL][XRES/CELL]; - float fvy[YRES/CELL][XRES/CELL]; - //Particles - Particle parts[NPART]; - int pmap[YRES][XRES]; - int photons[YRES][XRES]; - // - int gravityMode; - int airMode; - int ngrav_enable; - int legacy_enable; - int aheat_enable; - int VINE_MODE; - int water_equal_test; - int sys_pause; - int framerender; - int pretty_powder; - // - int sandcolour_r; - int sandcolour_g; - int sandcolour_b; //TODO: Make a single variable - //Stuff - int is_blocking(int t, int x, int y); - int is_boundary(int pt, int x, int y); - int find_next_boundary(int pt, int *x, int *y, int dm, int *em); - int pn_junction_sprk(int x, int y, int pt); - void photoelectric_effect(int nx, int ny); - unsigned direction_to_map(float dx, float dy, int t); - int do_move(int i, int x, int y, float nxf, float nyf); - int try_move(int i, int x, int y, int nx, int ny); - int eval_move(int pt, int nx, int ny, unsigned *rr); - void init_can_move(); - void create_cherenkov_photon(int pp); - void create_gain_photon(int pp); - void kill_part(int i); - int flood_prop(int x, int y, size_t propoffset, void * propvalue, int proptype); - int flood_prop_2(int x, int y, size_t propoffset, void * propvalue, int proptype, int parttype, char * bitmap); - int flood_water(int x, int y, int i, int originaly, int check); - void detach(int i); - void part_change_type(int i, int x, int y, int t); - int create_part_add_props(int p, int x, int y, int tv, int rx, int ry); - //int InCurrentBrush(int i, int j, int rx, int ry); - //int get_brush_flags(); - int create_part(int p, int x, int y, int t); - void delete_part(int x, int y, int flags); - int is_wire(int x, int y); - int is_wire_off(int x, int y); - void set_emap(int x, int y); - int parts_avg(int ci, int ni, int t); - void create_arc(int sx, int sy, int dx, int dy, int midpoints, int variance, int type, int flags); - int nearest_part(int ci, int t, int max_d); - void update_particles_i(int start, int inc); - void update_particles(); - 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 create_box(int x1, int y1, int x2, int y2, int c, int flags); - int flood_parts(int x, int y, int c, int cm, int bm, int flags); - int create_parts(int x, int y, int rx, int ry, int c, int flags); - void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flags); - void *transform_save(void *odata, int *size, matrix2d transform, vector2d translate); - 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); - int get_normal(int pt, int x, int y, float dx, float dy, float *nx, float *ny); - int get_normal_interp(int pt, float x0, float y0, float dx, float dy, float *nx, float *ny); - void clear_sim(); - void UpdateParticles(); - Simulation(); -}; -//#endif - -#endif /* SIMULATION_H_ */ diff --git a/src/client/Client.cpp b/src/client/Client.cpp new file mode 100644 index 0000000..3545414 --- /dev/null +++ b/src/client/Client.cpp @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include "Config.h" +#include "Client.h" +#include "interface/Point.h" +#include "Graphics.h" + +/* + static Thumbnail* thumbnailCache[120]; + static void * activeThumbRequests[5]; + static int activeThumbRequestTimes[5]; + static std::string activeThumbRequestIDs[5]; +*/ + +Client::Client() +{ + int i = 0; + http_init(NULL); + for(i = 0; i < 120; i++) + { + thumbnailCache[i] = NULL; + } + for(i = 0; i < 5; i++) + { + activeThumbRequests[i] = NULL; + activeThumbRequestTimes[i] = 0; + } +} + +Client::~Client() +{ + http_done(); +} + +void Client::ClearThumbnailRequests() +{ + for(int i = 0; i < 5; i++) + { + if(activeThumbRequests[i]) + { + http_async_req_close(activeThumbRequests[i]); + activeThumbRequests[i] = NULL; + } + } +} + +Thumbnail * Client::GetThumbnail(int saveID, int saveDate) +{ + std::stringstream urlStream; + std::stringstream idStream; + int i = 0; + for(i = 0; i < 120; i++) + { + if(thumbnailCache[i] && thumbnailCache[i]->ID == saveID && thumbnailCache[i]->Datestamp == saveDate) + return thumbnailCache[i]; + } + urlStream << "http://" << SERVER << "/Get.api?Op=thumbsmall&ID=" << saveID; + if(saveDate) + { + urlStream << "&Date=" << saveDate; + } + idStream << saveID << ":" << saveDate; + std::string idString = idStream.str(); + bool found = false; + for(i = 0; i < 5; i++) + { + if(activeThumbRequests[i] && activeThumbRequestIDs[i] == idString) + { + found = true; + if(http_async_req_status(activeThumbRequests[i])) + { + pixel * thumbData; + char * data; + int status, data_size, imgw, imgh; + data = http_async_req_stop(activeThumbRequests[i], &status, &data_size); + activeThumbRequests[i] = NULL; + if (status == 200 && data) + { + thumbData = Graphics::ptif_unpack(data, data_size, &imgw, &imgh); + if(data) + { + free(data); + } + thumbnailCacheNextID %= 120; + if(thumbnailCache[thumbnailCacheNextID]) + { + delete thumbnailCache[thumbnailCacheNextID]; + } + if(thumbData) + { + thumbnailCache[thumbnailCacheNextID] = new Thumbnail(saveID, saveDate, thumbData, ui::Point(imgw, imgh)); + } + else + { + thumbnailCache[thumbnailCacheNextID] = new Thumbnail(saveID, saveDate, (pixel *)malloc((128*128) * PIXELSIZE), ui::Point(128, 128)); + } + return thumbnailCache[thumbnailCacheNextID++]; + } + else + { + if(data) + { + free(data); + } + thumbnailCacheNextID %= 120; + if(thumbnailCache[thumbnailCacheNextID]) + { + delete thumbnailCache[thumbnailCacheNextID]; + } + thumbnailCache[thumbnailCacheNextID] = new Thumbnail(saveID, saveDate, (pixel *)malloc((128*128) * PIXELSIZE), ui::Point(128, 128)); + return thumbnailCache[thumbnailCacheNextID++]; + } + } + } + } + if(!found) + { + for(i = 0; i < 5; i++) + { + if(!activeThumbRequests[i]) + { + activeThumbRequests[i] = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 1); + std::cout << "ThumbCache: Requesting " << urlStream.str() << " : " << idString << std::endl; + activeThumbRequestIDs[i] = idString; + return NULL; + } + } + } + //http_async_req_start(http, urlStream.str().c_str(), NULL, 0, 1); + return NULL; +} diff --git a/src/client/Client.h b/src/client/Client.h new file mode 100644 index 0000000..37d0ad6 --- /dev/null +++ b/src/client/Client.h @@ -0,0 +1,24 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include +#include "HTTP.h" +#include "search/Thumbnail.h" +#include "Singleton.h" + +class Client: public Singleton +{ +private: + int thumbnailCacheNextID; + Thumbnail * thumbnailCache[120]; + void * activeThumbRequests[5]; + int activeThumbRequestTimes[5]; + std::string activeThumbRequestIDs[5]; +public: + Client(); + ~Client(); + void ClearThumbnailRequests(); + Thumbnail * GetThumbnail(int saveID, int saveDate); +}; + +#endif // CLIENT_H diff --git a/src/client/HTTP.cpp b/src/client/HTTP.cpp new file mode 100644 index 0000000..7514515 --- /dev/null +++ b/src/client/HTTP.cpp @@ -0,0 +1,1076 @@ +/** + * Powder Toy - HTTP Library + * + * Copyright (c) 2008 - 2010 Stanislaw Skowronek. + * Copyright (c) 2010 Simon Robertshaw + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + + +#include +#include +#include +#ifndef MACOSX +#include +#endif +#include +#ifdef WIN32 +#define _WIN32_WINNT 0x0501 +//#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "Config.h" +#include "HTTP.h" +#include "MD5.h" + +#ifdef WIN32 +#define PERROR SOCKET_ERROR +#define PERRNO WSAGetLastError() +#define PEAGAIN WSAEWOULDBLOCK +#define PEINTR WSAEINTR +#define PEINPROGRESS WSAEINPROGRESS +#define PEALREADY WSAEALREADY +#define PCLOSE closesocket +#else +#define PERROR -1 +#define PERRNO errno +#define PEAGAIN EAGAIN +#define PEINTR EINTR +#define PEINPROGRESS EINPROGRESS +#define PEALREADY EALREADY +#define PCLOSE close +#endif + +static int http_up = 0; +static long http_timeout = 15; +static int http_use_proxy = 0; +static struct sockaddr_in http_proxy; + +static char *mystrdup(char *s) +{ + char *x; + if (s) + { + x = (char *)malloc(strlen(s)+1); + strcpy(x, s); + return x; + } + return s; +} + +static int splituri(char *uri, char **host, char **path) +{ + char *p=uri,*q,*x,*y; + if (!strncmp(p, "http://", 7)) + p += 7; + q = strchr(p, '/'); + if (!q) + q = p + strlen(p); + x = (char *)malloc(q-p+1); + if (*q) + y = mystrdup(q); + else + y = mystrdup("/"); + strncpy(x, p, q-p); + x[q-p] = 0; + if (q==p || x[q-p-1]==':') + { + free(x); + free(y); + return 1; + } + *host = x; + *path = y; + return 0; +} + +static char *getserv(char *host) +{ + char *q, *x = mystrdup(host); + q = strchr(x, ':'); + if (q) + *q = 0; + return x; +} + +static char *getport(char *host) +{ + char *p, *q; + q = strchr(host, ':'); + if (q) + p = mystrdup(q+1); + else + p = mystrdup("80"); + return p; +} + +static int resolve(char *dns, char *srv, struct sockaddr_in *addr) +{ + struct addrinfo hnt, *res = 0; + if (http_use_proxy) + { + memcpy(addr, &http_proxy, sizeof(struct sockaddr_in)); + return 0; + } + memset(&hnt, 0, sizeof(hnt)); + hnt.ai_family = AF_INET; + hnt.ai_socktype = SOCK_STREAM; + if (getaddrinfo(dns, srv, &hnt, &res)) + return 1; + if (res) + { + if (res->ai_family != AF_INET) + { + freeaddrinfo(res); + return 1; + } + memcpy(addr, res->ai_addr, res->ai_addrlen); + freeaddrinfo(res); + return 0; + } + return 1; +} + +void http_init(char *proxy) +{ + char *host, *port; +#ifdef WIN32 + WSADATA wsadata; + if (!WSAStartup(MAKEWORD(2,2), &wsadata)) + http_up = 1; +#else + signal(SIGPIPE, SIG_IGN); + http_up = 1; +#endif + if (proxy) + { + host = getserv(proxy); + port = getport(proxy); + if (resolve(host, port, &http_proxy)) + http_up = 0; + else + http_use_proxy = 1; + free(host); + free(port); + } +} + +void http_done(void) +{ +#ifdef WIN32 + WSACleanup(); +#endif + http_up = 0; +} + +#define CHUNK 4096 + +#define HTS_STRT 0 +#define HTS_RSLV 1 +#define HTS_CONN 2 +#define HTS_IDLE 3 +#define HTS_XMIT 4 +#define HTS_RECV 5 +#define HTS_DONE 6 +struct http_ctx +{ + int state; + time_t last; + int keep; + int ret; + char *host, *path; + char *thdr; + int thlen; + char *txd; + int txdl; + struct sockaddr_in addr; + char *tbuf; + int tlen, tptr; + char *hbuf; + int hlen, hptr; + char *rbuf; + int rlen, rptr; + int chunked, chunkhdr, rxtogo, contlen, cclose; + int fd; + char *fdhost; +}; +void *http_async_req_start(void *ctx, char *uri, char *data, int dlen, int keep) +{ + struct http_ctx *cx = (http_ctx *)ctx; + if (!ctx) + { + ctx = calloc(1, sizeof(struct http_ctx)); + cx = (http_ctx *)ctx; + cx->fd = PERROR; + } + + if (!cx->hbuf) + { + cx->hbuf = (char *)malloc(256); + cx->hlen = 256; + } + + if (!http_up) + { + cx->ret = 604; + cx->state = HTS_DONE; + return ctx; + } + + if (cx->state!=HTS_STRT && cx->state!=HTS_IDLE) + { + fprintf(stderr, "HTTP: unclean request restart state.\n"); + exit(1); + } + + cx->keep = keep; + cx->ret = 600; + if (splituri(uri, &cx->host, &cx->path)) + { + cx->ret = 601; + cx->state = HTS_DONE; + return ctx; + } + if (http_use_proxy) + { + free(cx->path); + cx->path = mystrdup(uri); + } + if (cx->fdhost && strcmp(cx->host, cx->fdhost)) + { + free(cx->fdhost); + cx->fdhost = NULL; + PCLOSE(cx->fd); + cx->fd = PERROR; + cx->state = HTS_STRT; + } + if (data) + { + if (!dlen) + dlen = strlen(data); + cx->txd = (char*)malloc(dlen); + memcpy(cx->txd, data, dlen); + cx->txdl = dlen; + } + else + cx->txdl = 0; + + cx->contlen = 0; + cx->chunked = 0; + cx->chunkhdr = 0; + cx->rxtogo = 0; + cx->cclose = 0; + + cx->tptr = 0; + cx->tlen = 0; + + cx->last = time(NULL); + + return ctx; +} + +void http_async_add_header(void *ctx, char *name, char *data) +{ + struct http_ctx *cx = (http_ctx *)ctx; + cx->thdr = (char *)realloc(cx->thdr, cx->thlen + strlen(name) + strlen(data) + 4); + cx->thlen += sprintf(cx->thdr+cx->thlen, "%s: %s\n", name, data); +} + +static void process_header(struct http_ctx *cx, char *str) +{ + char *p; + if (cx->chunkhdr) + { + p = strchr(str, ';'); + if (p) + *p = 0; + cx->rxtogo = strtoul(str, NULL, 16); + cx->chunkhdr = 0; + if (!cx->rxtogo) + cx->chunked = 0; + } + if (!str[0]) + { + cx->rxtogo = cx->contlen; + cx->chunkhdr = cx->chunked; + if (!cx->contlen && !cx->chunked && cx->ret!=100) + cx->state = HTS_DONE; + return; + } + if (!strncmp(str, "HTTP/", 5)) + { + p = strchr(str, ' '); + if (!p) + { + cx->ret = 603; + cx->state = HTS_DONE; + return; + } + p++; + cx->ret = atoi(p); + return; + } + if (!strncmp(str, "Content-Length: ", 16)) + { + cx->contlen = atoi(str+16); + return; + } + if (!strcmp(str, "Transfer-Encoding: chunked")) + { + cx->chunked = 1; + return; + } + if (!strcmp(str, "Connection: close")) + { + cx->cclose = 1; + return; + } +} + +static void process_byte(struct http_ctx *cx, char ch) +{ + if (cx->rxtogo) + { + cx->rxtogo--; + + if (!cx->rbuf) + { + cx->rbuf = (char *)malloc(256); + cx->rlen = 256; + } + if (cx->rptr >= cx->rlen-1) + { + cx->rlen *= 2; + cx->rbuf = (char *)realloc(cx->rbuf, cx->rlen); + } + cx->rbuf[cx->rptr++] = ch; + + if (!cx->rxtogo && !cx->chunked) + cx->state = HTS_DONE; + } + else + { + if (ch == '\n') + { + cx->hbuf[cx->hptr] = 0; + process_header(cx, cx->hbuf); + cx->hptr = 0; + } + else if (ch != '\r') + { + if (cx->hptr >= cx->hlen-1) + { + cx->hlen *= 2; + cx->hbuf = (char *)realloc(cx->hbuf, cx->hlen); + } + cx->hbuf[cx->hptr++] = ch; + } + } +} + +int http_async_req_status(void *ctx) +{ + struct http_ctx *cx = (http_ctx *)ctx; + char *dns,*srv,buf[CHUNK]; + int tmp, i; + time_t now = time(NULL); +#ifdef WIN32 + unsigned long tmp2; +#endif + + switch (cx->state) + { + case HTS_STRT: + dns = getserv(cx->host); + srv = getport(cx->host); + if (resolve(dns, srv, &cx->addr)) + { + free(dns); + free(srv); + cx->state = HTS_DONE; + cx->ret = 602; + return 1; + } + free(dns); + free(srv); + cx->state = HTS_RSLV; + return 0; + case HTS_RSLV: + cx->state = HTS_CONN; + cx->last = now; + return 0; + case HTS_CONN: + if (cx->fd == PERROR) + { + cx->fd = socket(AF_INET, SOCK_STREAM, 0); + if (cx->fd == PERROR) + goto fail; + cx->fdhost = mystrdup(cx->host); +#ifdef WIN32 + tmp2 = 1; + if (ioctlsocket(cx->fd, FIONBIO, &tmp2) == SOCKET_ERROR) + goto fail; +#else + tmp = fcntl(cx->fd, F_GETFL); + if (tmp < 0) + goto fail; + if (fcntl(cx->fd, F_SETFL, tmp|O_NONBLOCK) < 0) + goto fail; +#endif + } + if (!connect(cx->fd, (struct sockaddr *)&cx->addr, sizeof(cx->addr))) + cx->state = HTS_IDLE; +#ifdef WIN32 + else if (PERRNO==WSAEISCONN) + cx->state = HTS_IDLE; +#endif +#ifdef MACOSX + else if (PERRNO==EISCONN) + cx->state = HTS_IDLE; +#endif + else if (PERRNO!=PEINPROGRESS && PERRNO!=PEALREADY +#ifdef WIN32 + && PERRNO!=PEAGAIN && PERRNO!=WSAEINVAL +#endif + ) + goto fail; + if (now-cx->last>http_timeout) + goto timeout; + return 0; + case HTS_IDLE: + if (cx->txdl) + { + // generate POST + cx->tbuf = (char *)malloc(strlen(cx->host) + strlen(cx->path) + 121 + cx->txdl + cx->thlen); + cx->tptr = 0; + cx->tlen = 0; + cx->tlen += sprintf(cx->tbuf+cx->tlen, "POST %s HTTP/1.1\n", cx->path); + cx->tlen += sprintf(cx->tbuf+cx->tlen, "Host: %s\n", cx->host); + if (!cx->keep) + cx->tlen += sprintf(cx->tbuf+cx->tlen, "Connection: close\n"); + if (cx->thdr) + { + memcpy(cx->tbuf+cx->tlen, cx->thdr, cx->thlen); + cx->tlen += cx->thlen; + free(cx->thdr); + cx->thdr = NULL; + cx->thlen = 0; + } + cx->tlen += sprintf(cx->tbuf+cx->tlen, "Content-Length: %d\n", cx->txdl); +#ifdef BETA + cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dB%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); +#else + cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dS%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); +#endif + cx->tlen += sprintf(cx->tbuf+cx->tlen, "\n"); + memcpy(cx->tbuf+cx->tlen, cx->txd, cx->txdl); + cx->tlen += cx->txdl; + free(cx->txd); + cx->txd = NULL; + cx->txdl = 0; + } + else + { + // generate GET + cx->tbuf = (char *)malloc(strlen(cx->host) + strlen(cx->path) + 89 + cx->thlen); + cx->tptr = 0; + cx->tlen = 0; + cx->tlen += sprintf(cx->tbuf+cx->tlen, "GET %s HTTP/1.1\n", cx->path); + cx->tlen += sprintf(cx->tbuf+cx->tlen, "Host: %s\n", cx->host); + if (cx->thdr) + { + memcpy(cx->tbuf+cx->tlen, cx->thdr, cx->thlen); + cx->tlen += cx->thlen; + free(cx->thdr); + cx->thdr = NULL; + cx->thlen = 0; + } + if (!cx->keep) + cx->tlen += sprintf(cx->tbuf+cx->tlen, "Connection: close\n"); +#ifdef BETA + cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dB%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); +#else + cx->tlen += sprintf(cx->tbuf+cx->tlen, "X-Powder-Version: %s%dS%d\n", IDENT_VERSION, SAVE_VERSION, MINOR_VERSION); +#endif + cx->tlen += sprintf(cx->tbuf+cx->tlen, "\n"); + } + cx->state = HTS_XMIT; + cx->last = now; + return 0; + case HTS_XMIT: + tmp = send(cx->fd, cx->tbuf+cx->tptr, cx->tlen-cx->tptr, 0); + if (tmp==PERROR && PERRNO!=PEAGAIN && PERRNO!=PEINTR) + goto fail; + if (tmp!=PERROR) + { + cx->tptr += tmp; + if (cx->tptr == cx->tlen) + { + cx->tptr = 0; + cx->tlen = 0; + if (cx->tbuf) + free(cx->tbuf); + cx->state = HTS_RECV; + } + cx->last = now; + } + if (now-cx->last>http_timeout) + goto timeout; + return 0; + case HTS_RECV: + tmp = recv(cx->fd, buf, CHUNK, 0); + if (tmp==PERROR && PERRNO!=PEAGAIN && PERRNO!=PEINTR) + goto fail; + if (tmp!=PERROR) + { + for (i=0; istate == HTS_DONE) + return 1; + } + cx->last = now; + } + if (now-cx->last>http_timeout) + goto timeout; + return 0; + case HTS_DONE: + return 1; + } + return 0; + +fail: + cx->ret = 600; + cx->state = HTS_DONE; + return 1; + +timeout: + cx->ret = 605; + cx->state = HTS_DONE; + return 1; +} + +char *http_async_req_stop(void *ctx, int *ret, int *len) +{ + struct http_ctx *cx = (http_ctx *)ctx; + char *rxd; + + if (cx->state != HTS_DONE) + while (!http_async_req_status(ctx)) ; + + if (cx->host) + { + free(cx->host); + cx->host = NULL; + } + if (cx->path) + { + free(cx->path); + cx->path = NULL; + } + if (cx->txd) + { + free(cx->txd); + cx->txd = NULL; + cx->txdl = 0; + } + if (cx->hbuf) + { + free(cx->hbuf); + cx->hbuf = NULL; + } + if (cx->thdr) + { + free(cx->thdr); + cx->thdr = NULL; + cx->thlen = 0; + } + + if (ret) + *ret = cx->ret; + if (len) + *len = cx->rptr; + if (cx->rbuf) + cx->rbuf[cx->rptr] = 0; + rxd = cx->rbuf; + cx->rbuf = NULL; + cx->rlen = 0; + cx->rptr = 0; + cx->contlen = 0; + + if (!cx->keep) + http_async_req_close(ctx); + else if (cx->cclose) + { + PCLOSE(cx->fd); + cx->fd = PERROR; + if (cx->fdhost) + { + free(cx->fdhost); + cx->fdhost = NULL; + } + cx->state = HTS_STRT; + } + else + cx->state = HTS_IDLE; + + return rxd; +} + +void http_async_get_length(void *ctx, int *total, int *done) +{ + struct http_ctx *cx = (http_ctx *)ctx; + if (done) + *done = cx->rptr; + if (total) + *total = cx->contlen; +} + +void http_async_req_close(void *ctx) +{ + struct http_ctx *cx = (http_ctx *)ctx; + void *tmp; + if (cx->host) + { + cx->keep = 1; + tmp = http_async_req_stop(ctx, NULL, NULL); + if (tmp) + free(tmp); + } + if (cx->fdhost) + free(cx->fdhost); + PCLOSE(cx->fd); + free(ctx); +} + +char *http_simple_get(char *uri, int *ret, int *len) +{ + void *ctx = http_async_req_start(NULL, uri, NULL, 0, 0); + if (!ctx) + { + if (ret) + *ret = 600; + if (len) + *len = 0; + return NULL; + } + return http_async_req_stop(ctx, ret, len); +} +static char hex[] = "0123456789abcdef"; +void http_auth_headers(void *ctx, char *user, char *pass, char *session_id) +{ + char *tmp; + int i; + unsigned char hash[16]; + unsigned int m; + struct md5_context md5; + + if (user) + { + if (pass) + { + md5_init(&md5); + md5_update(&md5, (unsigned char *)user, strlen(user)); + md5_update(&md5, (unsigned char *)"-", 1); + m = 0; + + md5_update(&md5, (unsigned char *)pass, strlen(pass)); + md5_final(hash, &md5); + tmp = (char *)malloc(33); + for (i=0; i<16; i++) + { + tmp[i*2] = hex[hash[i]>>4]; + tmp[i*2+1] = hex[hash[i]&15]; + } + tmp[32] = 0; + http_async_add_header(ctx, "X-Auth-Hash", tmp); + free(tmp); + } + if (session_id) + { + http_async_add_header(ctx, "X-Auth-User-Id", user); + http_async_add_header(ctx, "X-Auth-Session-Key", session_id); + } + else + { + http_async_add_header(ctx, "X-Auth-User", user); + } + } +} +char *http_auth_get(char *uri, char *user, char *pass, char *session_id, int *ret, int *len) +{ + void *ctx = http_async_req_start(NULL, uri, NULL, 0, 0); + + if (!ctx) + { + if (ret) + *ret = 600; + if (len) + *len = 0; + return NULL; + } + return http_async_req_stop(ctx, ret, len); +} + +char *http_simple_post(char *uri, char *data, int dlen, int *ret, int *len) +{ + void *ctx = http_async_req_start(NULL, uri, data, dlen, 0); + if (!ctx) + { + if (ret) + *ret = 600; + if (len) + *len = 0; + return NULL; + } + return http_async_req_stop(ctx, ret, len); +} + +char *http_ret_text(int ret) +{ + switch (ret) + { + case 100: + return "Continue"; + case 101: + return "Switching Protocols"; + case 102: + return "Processing"; + + case 200: + return "OK"; + case 201: + return "Created"; + case 202: + return "Accepted"; + case 203: + return "Non-Authoritative Information"; + case 204: + return "No Content"; + case 205: + return "Reset Content"; + case 206: + return "Partial Content"; + case 207: + return "Multi-Status"; + + case 300: + return "Multiple Choices"; + case 301: + return "Moved Permanently"; + case 302: + return "Found"; + case 303: + return "See Other"; + case 304: + return "Not Modified"; + case 305: + return "Use Proxy"; + case 306: + return "Switch Proxy"; + case 307: + return "Temporary Redirect"; + + case 400: + return "Bad Request"; + case 401: + return "Unauthorized"; + case 402: + return "Payment Required"; + case 403: + return "Forbidden"; + case 404: + return "Not Found"; + case 405: + return "Method Not Allowed"; + case 406: + return "Not Acceptable"; + case 407: + return "Proxy Authentication Required"; + case 408: + return "Request Timeout"; + case 409: + return "Conflict"; + case 410: + return "Gone"; + case 411: + return "Length Required"; + case 412: + return "Precondition Failed"; + case 413: + return "Request Entity Too Large"; + case 414: + return "Request URI Too Long"; + case 415: + return "Unsupported Media Type"; + case 416: + return "Requested Range Not Satisfiable"; + case 417: + return "Expectation Failed"; + case 418: + return "I'm a teapot"; + case 422: + return "Unprocessable Entity"; + case 423: + return "Locked"; + case 424: + return "Failed Dependency"; + case 425: + return "Unordered Collection"; + case 426: + return "Upgrade Required"; + case 444: + return "No Response"; + case 450: + return "Blocked by Windows Parental Controls"; + case 499: + return "Client Closed Request"; + + case 500: + return "Internal Server Error"; + case 501: + return "Not Implemented"; + case 502: + return "Bad Gateway"; + case 503: + return "Service Unavailable"; + case 504: + return "Gateway Timeout"; + case 505: + return "HTTP Version Not Supported"; + case 506: + return "Variant Also Negotiates"; + case 507: + return "Insufficient Storage"; + case 509: + return "Bandwidth Limit Exceeded"; + case 510: + return "Not Extended"; + + case 600: + return "Internal Client Error"; + case 601: + return "Unsupported Protocol"; + case 602: + return "Server Not Found"; + case 603: + return "Malformed Response"; + case 604: + return "Network Not Available"; + case 605: + return "Request Timed Out"; + default: + return "Unknown Status Code"; + } +} +char *http_multipart_post(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char *session_id, int *ret, int *len) +{ + void *ctx; + char *data = NULL, *tmp, *p; + int dlen = 0, i, j; + unsigned char hash[16]; + unsigned char boundary[32], ch; + int blen = 0; + unsigned int map[62], m; + struct md5_context md5; + //struct md5_context md52; + int own_plen = 0; + + if (names) + { + if (!plens) + { + own_plen = 1; + for (i=0; names[i]; i++) ; + plens = (int *)calloc(i, sizeof(int)); + for (i=0; names[i]; i++) + plens[i] = strlen(parts[i]); + } + +retry: + if (blen >= 31) + goto fail; + memset(map, 0, 62*sizeof(int)); + for (i=0; names[i]; i++) + { + for (j=0; j='0' && ch<='9') + map[ch-'0']++; + else if (ch>='A' && ch<='Z') + map[ch-'A'+10]++; + else if (ch>='a' && ch<='z') + map[ch-'a'+36]++; + } + } + m = ~0; + j = 61; + for (i=0; i<62; i++) + if (map[i]>4]; + tmp[i*2+1] = hex[hash[i]&15]; + } + tmp[32] = 0; + http_async_add_header(ctx, "X-Auth-Hash", tmp); + free(tmp); + } + if (session_id) + { + http_async_add_header(ctx, "X-Auth-User-Id", user); + http_async_add_header(ctx, "X-Auth-Session-Key", session_id); + } + else + { + http_async_add_header(ctx, "X-Auth-User", user); + } + } + + if (data) + { + tmp = (char *)malloc(32+strlen((char *)boundary)); + sprintf(tmp, "multipart/form-data, boundary=%s", boundary); + http_async_add_header(ctx, "Content-type", tmp); + free(tmp); + free(data); + } + + if (own_plen) + free(plens); + return http_async_req_stop(ctx, ret, len); + +fail: + if (data) + free(data); + if (own_plen) + free(plens); + if (ret) + *ret = 600; + if (len) + *len = 0; + return NULL; +} diff --git a/src/client/HTTP.h b/src/client/HTTP.h new file mode 100644 index 0000000..af0971c --- /dev/null +++ b/src/client/HTTP.h @@ -0,0 +1,43 @@ +/** + * Powder Toy - HTTP Library (Header) + * + * Copyright (c) 2008 - 2010 Stanislaw Skowronek. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ +#ifndef HTTP_H +#define HTTP_H + +void http_init(char *proxy); +void http_done(void); + +char *http_simple_get(char *uri, int *ret, int *len); +char *http_auth_get(char *uri, char *user, char *pass, char * session_id, int *ret, int *len); +char *http_simple_post(char *uri, char *data, int dlen, int *ret, int *len); + +void http_auth_headers(void *ctx, char *user, char *pass, char * session_id); + +void *http_async_req_start(void *ctx, char *uri, char *data, int dlen, int keep); +void http_async_add_header(void *ctx, char *name, char *data); +int http_async_req_status(void *ctx); +void http_async_get_length(void *ctx, int *total, int *done); +char *http_async_req_stop(void *ctx, int *ret, int *len); +void http_async_req_close(void *ctx); + +char *http_multipart_post(char *uri, char **names, char **parts, int *plens, char *user, char *pass, char * session_id, int *ret, int *len); + +char *http_ret_text(int ret); + +#endif diff --git a/src/client/MD5.cpp b/src/client/MD5.cpp new file mode 100644 index 0000000..9cb398c --- /dev/null +++ b/src/client/MD5.cpp @@ -0,0 +1,231 @@ +// based on public-domain code from Colin Plumb (1993) +#include +#include "MD5.h" + +static unsigned getu32(const unsigned char *addr) +{ + return (((((unsigned long)addr[3] << 8) | addr[2]) << 8) | addr[1]) << 8 | addr[0]; +} + +static void putu32(unsigned data, unsigned char *addr) +{ + addr[0] = (unsigned char)data; + addr[1] = (unsigned char)(data >> 8); + addr[2] = (unsigned char)(data >> 16); + addr[3] = (unsigned char)(data >> 24); +} + +void md5_init(struct md5_context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +void md5_update(struct md5_context *ctx, unsigned char const *buf, unsigned len) +{ + unsigned t; + + // update bit count + t = ctx->bits[0]; + if ((ctx->bits[0] = (t + ((unsigned)len << 3)) & 0xffffffff) < t) + ctx->bits[1]++; // carry + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; + + // use leading data to top up the buffer + + if (t) + { + unsigned char *p = ctx->in + t; + + t = 64-t; + if (len < t) + { + memcpy(p, buf, len); + return; + } + memcpy(p, buf, t); + md5_transform(ctx->buf, ctx->in); + buf += t; + len -= t; + } + + // following 64-byte chunks + + while (len >= 64) + { + memcpy(ctx->in, buf, 64); + md5_transform(ctx->buf, ctx->in); + buf += 64; + len -= 64; + } + + // save rest of bytes for later + + memcpy(ctx->in, buf, len); +} + +void md5_final(unsigned char digest[16], struct md5_context *ctx) +{ + unsigned count; + unsigned char *p; + + // #bytes mod64 + count = (ctx->bits[0] >> 3) & 0x3F; + + // first char of padding = 0x80 + p = ctx->in + count; + *p++ = 0x80; + + // calculate # of bytes to pad + count = 64 - 1 - count; + + // Pad out to 56 mod 64 + if (count < 8) + { + // we need to finish a whole block before padding + memset(p, 0, count); + md5_transform(ctx->buf, ctx->in); + memset(ctx->in, 0, 56); + } + else + { + // just pad to 56 bytes + memset(p, 0, count-8); + } + + // append length & final transform + putu32(ctx->bits[0], ctx->in + 56); + putu32(ctx->bits[1], ctx->in + 60); + + md5_transform(ctx->buf, ctx->in); + putu32(ctx->buf[0], digest); + putu32(ctx->buf[1], digest + 4); + putu32(ctx->buf[2], digest + 8); + putu32(ctx->buf[3], digest + 12); + memset(ctx, 0, sizeof(ctx)); +} + +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w &= 0xffffffff, w = w<>(32-s), w += x ) + +void md5_transform(unsigned buf[4], const unsigned char inraw[64]) +{ + unsigned a, b, c, d; + unsigned in[16]; + int i; + + for (i = 0; i < 16; ++i) + in[i] = getu32 (inraw + 4 * i); + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} + +static char hex[] = "0123456789abcdef"; +void md5_ascii(char *result, unsigned char const *buf, unsigned len) +{ + struct md5_context md5; + unsigned char hash[16]; + int i; + + if (len==0) + len = strlen((char *)buf); + + md5_init(&md5); + md5_update(&md5, buf, len); + md5_final(hash, &md5); + + for (i=0; i<16; i++) + { + result[i*2] = hex[(hash[i]>>4)&0xF]; + result[i*2+1] = hex[hash[i]&0x0F]; + } + result[32] = 0; +} diff --git a/src/client/MD5.h b/src/client/MD5.h new file mode 100644 index 0000000..a8ef123 --- /dev/null +++ b/src/client/MD5.h @@ -0,0 +1,18 @@ +#ifndef MD5_H +#define MD5_H + +struct md5_context +{ + unsigned buf[4]; + unsigned bits[2]; + unsigned char in[64]; +}; + +void md5_init(struct md5_context *context); +void md5_update(struct md5_context *context, unsigned char const *buf, unsigned len); +void md5_final(unsigned char digest[16], struct md5_context *context); +void md5_transform(unsigned buf[4], const unsigned char in[64]); + +void md5_ascii(char *result, unsigned char const *buf, unsigned len); + +#endif diff --git a/src/elements/O2.cpp b/src/elements/O2.cpp index 78b4229..864d9e8 100644 --- a/src/elements/O2.cpp +++ b/src/elements/O2.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_O2(UPDATE_FUNC_ARGS) { diff --git a/src/elements/acel.cpp b/src/elements/acel.cpp index 7ab9684..0d69894 100644 --- a/src/elements/acel.cpp +++ b/src/elements/acel.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_ACEL(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/acid.cpp b/src/elements/acid.cpp index 3a72b9d..8d881fd 100644 --- a/src/elements/acid.cpp +++ b/src/elements/acid.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_ACID(UPDATE_FUNC_ARGS) { int r, rx, ry, trade, np; diff --git a/src/elements/amtr.cpp b/src/elements/amtr.cpp index d119cc9..5ff4529 100644 --- a/src/elements/amtr.cpp +++ b/src/elements/amtr.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_AMTR(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/anar.cpp b/src/elements/anar.cpp index 83eaf5a..6db0d2e 100644 --- a/src/elements/anar.cpp +++ b/src/elements/anar.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_ANAR(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/aray.cpp b/src/elements/aray.cpp index 65b0d53..2ab9b40 100644 --- a/src/elements/aray.cpp +++ b/src/elements/aray.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_ARAY(UPDATE_FUNC_ARGS) { int r, nxx, nyy, docontinue, nxi, nyi, rx, ry, nr, ry1, rx1; diff --git a/src/elements/bang.cpp b/src/elements/bang.cpp index 658a567..7a1f673 100644 --- a/src/elements/bang.cpp +++ b/src/elements/bang.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BANG(UPDATE_FUNC_ARGS) { int r, rx, ry, nb; diff --git a/src/elements/bcln.cpp b/src/elements/bcln.cpp index 8c00f95..702b322 100644 --- a/src/elements/bcln.cpp +++ b/src/elements/bcln.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BCLN(UPDATE_FUNC_ARGS) { if (!parts[i].life && sim->pv[y/CELL][x/CELL]>4.0f) diff --git a/src/elements/bcol.cpp b/src/elements/bcol.cpp index d941508..d727abf 100644 --- a/src/elements/bcol.cpp +++ b/src/elements/bcol.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BCOL(UPDATE_FUNC_ARGS) { int r, rx, ry, trade, temp; diff --git a/src/elements/bizr.cpp b/src/elements/bizr.cpp index 538b87f..aae09d9 100644 --- a/src/elements/bizr.cpp +++ b/src/elements/bizr.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" //Used by ALL 3 BIZR states int update_BIZR(UPDATE_FUNC_ARGS) { diff --git a/src/elements/bmtl.cpp b/src/elements/bmtl.cpp index a3dc4b8..8682561 100644 --- a/src/elements/bmtl.cpp +++ b/src/elements/bmtl.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BMTL(UPDATE_FUNC_ARGS) { int r, rx, ry, rt, tempFactor; diff --git a/src/elements/bomb.cpp b/src/elements/bomb.cpp index b2e9e7d..b696b19 100644 --- a/src/elements/bomb.cpp +++ b/src/elements/bomb.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BOMB(UPDATE_FUNC_ARGS) { int r, rx, ry, nb; diff --git a/src/elements/boyl.cpp b/src/elements/boyl.cpp index e4ee6d2..7c0fc24 100644 --- a/src/elements/boyl.cpp +++ b/src/elements/boyl.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BOYL(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/brmt.cpp b/src/elements/brmt.cpp index c23bd99..0e49cd1 100644 --- a/src/elements/brmt.cpp +++ b/src/elements/brmt.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BRMT(UPDATE_FUNC_ARGS) { int r, rx, ry, rt, tempFactor; diff --git a/src/elements/btry.cpp b/src/elements/btry.cpp index 3f11003..0168e08 100644 --- a/src/elements/btry.cpp +++ b/src/elements/btry.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_BTRY(UPDATE_FUNC_ARGS) { int r, rx, ry, rt; diff --git a/src/elements/c5.cpp b/src/elements/c5.cpp index 412245f..8a10915 100644 --- a/src/elements/c5.cpp +++ b/src/elements/c5.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_C5(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/caus.cpp b/src/elements/caus.cpp index 2ec268e..fb71969 100644 --- a/src/elements/caus.cpp +++ b/src/elements/caus.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_CAUS(UPDATE_FUNC_ARGS) { int r, rx, ry, trade, np; diff --git a/src/elements/cbnw.cpp b/src/elements/cbnw.cpp index cf0c13e..37625b0 100644 --- a/src/elements/cbnw.cpp +++ b/src/elements/cbnw.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_CBNW(UPDATE_FUNC_ARGS) { int r, rx, ry, oldt; diff --git a/src/elements/clne.cpp b/src/elements/clne.cpp index 13b25b9..303908e 100644 --- a/src/elements/clne.cpp +++ b/src/elements/clne.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_CLNE(UPDATE_FUNC_ARGS) { if (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || (parts[i].ctype==PT_LIFE && (parts[i].tmp<0 || parts[i].tmp>=NGOLALT))) diff --git a/src/elements/clst.cpp b/src/elements/clst.cpp index 2c31d87..f8653be 100644 --- a/src/elements/clst.cpp +++ b/src/elements/clst.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_CLST(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/co2.cpp b/src/elements/co2.cpp index 5a3bbf5..62bc646 100644 --- a/src/elements/co2.cpp +++ b/src/elements/co2.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_CO2(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/coal.cpp b/src/elements/coal.cpp index 256aa69..23d20ba 100644 --- a/src/elements/coal.cpp +++ b/src/elements/coal.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_COAL(UPDATE_FUNC_ARGS) { int r, rx, ry, trade, temp; diff --git a/src/elements/conv.cpp b/src/elements/conv.cpp index ce4ee48..a62cd55 100644 --- a/src/elements/conv.cpp +++ b/src/elements/conv.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_CONV(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/dest.cpp b/src/elements/dest.cpp index 014fad4..fa5faf8 100644 --- a/src/elements/dest.cpp +++ b/src/elements/dest.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_DEST(UPDATE_FUNC_ARGS) { int r,rx,ry,topv; diff --git a/src/elements/deut.cpp b/src/elements/deut.cpp index 03de364..cee38de 100644 --- a/src/elements/deut.cpp +++ b/src/elements/deut.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_DEUT(UPDATE_FUNC_ARGS) { int r, rx, ry, trade, np; diff --git a/src/elements/dlay.cpp b/src/elements/dlay.cpp index 4643b30..e40c362 100644 --- a/src/elements/dlay.cpp +++ b/src/elements/dlay.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_DLAY(UPDATE_FUNC_ARGS) { int r, rx, ry, oldl; diff --git a/src/elements/dstw.cpp b/src/elements/dstw.cpp index 03ae7dd..21d7db2 100644 --- a/src/elements/dstw.cpp +++ b/src/elements/dstw.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_DSTW(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/elec.cpp b/src/elements/elec.cpp index 6b06f8f..e8ddf5e 100644 --- a/src/elements/elec.cpp +++ b/src/elements/elec.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_ELEC(UPDATE_FUNC_ARGS) { int r, rt, rx, ry, nb, rrx, rry; diff --git a/src/elements/elementmisc.cpp b/src/elements/elementmisc.cpp index a169e80..4df53f4 100644 --- a/src/elements/elementmisc.cpp +++ b/src/elements/elementmisc.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_MISC(UPDATE_FUNC_ARGS) { /*int t = parts[i].type; diff --git a/src/elements/emp.cpp b/src/elements/emp.cpp index a187196..2b3db86 100644 --- a/src/elements/emp.cpp +++ b/src/elements/emp.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_EMP(UPDATE_FUNC_ARGS) { int r,rx,ry,ok=0,t,n,nx,ny; diff --git a/src/elements/figh.cpp b/src/elements/figh.cpp index 8b18871..35b5a20 100644 --- a/src/elements/figh.cpp +++ b/src/elements/figh.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FIGH(UPDATE_FUNC_ARGS) { diff --git a/src/elements/fire.cpp b/src/elements/fire.cpp index 1f9c0c2..3f36916 100644 --- a/src/elements/fire.cpp +++ b/src/elements/fire.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int graphics_FIRE(GRAPHICS_FUNC_ARGS) { diff --git a/src/elements/firw.cpp b/src/elements/firw.cpp index 74605b0..ffd7941 100644 --- a/src/elements/firw.cpp +++ b/src/elements/firw.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FIRW(UPDATE_FUNC_ARGS) { int r, rx, ry, rt, np; diff --git a/src/elements/fog.cpp b/src/elements/fog.cpp index 28952e9..24ea953 100644 --- a/src/elements/fog.cpp +++ b/src/elements/fog.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FOG(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/frzw.cpp b/src/elements/frzw.cpp index 932bccb..4569911 100644 --- a/src/elements/frzw.cpp +++ b/src/elements/frzw.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FRZW(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/frzz.cpp b/src/elements/frzz.cpp index 8e09c1d..b412cbc 100644 --- a/src/elements/frzz.cpp +++ b/src/elements/frzz.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FRZZ(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/fsep.cpp b/src/elements/fsep.cpp index 3db5ba5..347fc46 100644 --- a/src/elements/fsep.cpp +++ b/src/elements/fsep.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FSEP(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/fuse.cpp b/src/elements/fuse.cpp index e1db1ff..9081b21 100644 --- a/src/elements/fuse.cpp +++ b/src/elements/fuse.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FUSE(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/fwrk.cpp b/src/elements/fwrk.cpp index d217ad9..1838dde 100644 --- a/src/elements/fwrk.cpp +++ b/src/elements/fwrk.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_FWRK(UPDATE_FUNC_ARGS) { int r, rx, ry, np; diff --git a/src/elements/gbmb.cpp b/src/elements/gbmb.cpp index 95afc4e..d1d7c20 100644 --- a/src/elements/gbmb.cpp +++ b/src/elements/gbmb.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_GBMB(UPDATE_FUNC_ARGS) { int rx,ry,r; if (parts[i].life<=0) diff --git a/src/elements/glas.cpp b/src/elements/glas.cpp index e8c0a6c..ef9e7f7 100644 --- a/src/elements/glas.cpp +++ b/src/elements/glas.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_GLAS(UPDATE_FUNC_ARGS) { parts[i].pavg[0] = parts[i].pavg[1]; diff --git a/src/elements/glow.cpp b/src/elements/glow.cpp index e83e2f4..38f7140 100644 --- a/src/elements/glow.cpp +++ b/src/elements/glow.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_GLOW(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/goo.cpp b/src/elements/goo.cpp index c305182..6e66468 100644 --- a/src/elements/goo.cpp +++ b/src/elements/goo.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_GOO(UPDATE_FUNC_ARGS) { if (!parts[i].life && sim->pv[y/CELL][x/CELL]>1.0f) diff --git a/src/elements/gpmp.cpp b/src/elements/gpmp.cpp index dcde7a9..3ad552b 100644 --- a/src/elements/gpmp.cpp +++ b/src/elements/gpmp.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_GPMP(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/graphics_default.cpp b/src/elements/graphics_default.cpp index 1270977..cf394aa 100644 --- a/src/elements/graphics_default.cpp +++ b/src/elements/graphics_default.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int graphics_DEFAULT(GRAPHICS_FUNC_ARGS) { diff --git a/src/elements/h2.cpp b/src/elements/h2.cpp index da39ad0..3a92cfe 100644 --- a/src/elements/h2.cpp +++ b/src/elements/h2.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_H2(UPDATE_FUNC_ARGS) { diff --git a/src/elements/hswc.cpp b/src/elements/hswc.cpp index c727395..a279947 100644 --- a/src/elements/hswc.cpp +++ b/src/elements/hswc.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_HSWC(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/ice.cpp b/src/elements/ice.cpp index aece17b..aab4e0e 100644 --- a/src/elements/ice.cpp +++ b/src/elements/ice.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_ICEI(UPDATE_FUNC_ARGS) { //currently used for snow as well int r, rx, ry; diff --git a/src/elements/ignt.cpp b/src/elements/ignt.cpp index 1d7ea64..66b0e18 100644 --- a/src/elements/ignt.cpp +++ b/src/elements/ignt.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_IGNT(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/iron.cpp b/src/elements/iron.cpp index b887cf8..391b708 100644 --- a/src/elements/iron.cpp +++ b/src/elements/iron.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_IRON(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/isz.cpp b/src/elements/isz.cpp index 25446d2..22e6c77 100644 --- a/src/elements/isz.cpp +++ b/src/elements/isz.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_ISZ(UPDATE_FUNC_ARGS) { // for both ISZS and ISOZ float rr, rrr; diff --git a/src/elements/lava.cpp b/src/elements/lava.cpp index 3d7827b..cc0fbb3 100644 --- a/src/elements/lava.cpp +++ b/src/elements/lava.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int graphics_LAVA(GRAPHICS_FUNC_ARGS) { diff --git a/src/elements/lcry.cpp b/src/elements/lcry.cpp index 546c2ca..0ecb84c 100644 --- a/src/elements/lcry.cpp +++ b/src/elements/lcry.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_LCRY(UPDATE_FUNC_ARGS) { diff --git a/src/elements/legacy.cpp b/src/elements/legacy.cpp index dd58173..f1fcf03 100644 --- a/src/elements/legacy.cpp +++ b/src/elements/legacy.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" // Interactions which only occur when legacy_enable is on int update_legacy_all(UPDATE_FUNC_ARGS) { diff --git a/src/elements/ligh.cpp b/src/elements/ligh.cpp index 8108c4b..5249c4f 100644 --- a/src/elements/ligh.cpp +++ b/src/elements/ligh.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" #define LIGHTING_POWER 0.65 diff --git a/src/elements/merc.cpp b/src/elements/merc.cpp index 2df113b..58b19a3 100644 --- a/src/elements/merc.cpp +++ b/src/elements/merc.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_MERC(UPDATE_FUNC_ARGS) { int r, rx, ry, trade, np; diff --git a/src/elements/mort.cpp b/src/elements/mort.cpp index bbb6264..9de088f 100644 --- a/src/elements/mort.cpp +++ b/src/elements/mort.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_MORT(UPDATE_FUNC_ARGS) { sim->create_part(-1, x, y-1, PT_SMKE); diff --git a/src/elements/nbhl.cpp b/src/elements/nbhl.cpp index 056313c..565416f 100644 --- a/src/elements/nbhl.cpp +++ b/src/elements/nbhl.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_NBHL(UPDATE_FUNC_ARGS) { sim->gravmap[(y/CELL)*(XRES/CELL)+(x/CELL)] += 0.1f; diff --git a/src/elements/neut.cpp b/src/elements/neut.cpp index a48fc09..c804106 100644 --- a/src/elements/neut.cpp +++ b/src/elements/neut.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int create_n_parts(Simulation * sim, int n, int x, int y, float vx, float vy, float temp, int t)//testing a new deut create part diff --git a/src/elements/newgraphics.cpp b/src/elements/newgraphics.cpp index 83da27b..036a6a7 100644 --- a/src/elements/newgraphics.cpp +++ b/src/elements/newgraphics.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" #include "hmap.h" int graphics_QRTZ(GRAPHICS_FUNC_ARGS) //QRTZ and PQRT diff --git a/src/elements/none.cpp b/src/elements/none.cpp index 50f301f..6974e6c 100644 --- a/src/elements/none.cpp +++ b/src/elements/none.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_(UPDATE_FUNC_ARGS) { diff --git a/src/elements/nptct.cpp b/src/elements/nptct.cpp index 2d68a9b..f8e29e6 100644 --- a/src/elements/nptct.cpp +++ b/src/elements/nptct.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_NPTCT(UPDATE_FUNC_ARGS) { if (parts[i].temp>295.0f) diff --git a/src/elements/nwhl.cpp b/src/elements/nwhl.cpp index f53b657..cae189a 100644 --- a/src/elements/nwhl.cpp +++ b/src/elements/nwhl.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_NWHL(UPDATE_FUNC_ARGS) { sim->gravmap[(y/CELL)*(XRES/CELL)+(x/CELL)] -= 0.1f; diff --git a/src/elements/pbcn.cpp b/src/elements/pbcn.cpp index 7e99397..a6bbe5a 100644 --- a/src/elements/pbcn.cpp +++ b/src/elements/pbcn.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PBCN(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/pcln.cpp b/src/elements/pcln.cpp index cd1ed4f..beb4a9a 100644 --- a/src/elements/pcln.cpp +++ b/src/elements/pcln.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PCLN(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/phot.cpp b/src/elements/phot.cpp index 3ed6b5d..407ac2e 100644 --- a/src/elements/phot.cpp +++ b/src/elements/phot.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PHOT(UPDATE_FUNC_ARGS) { int r, rt, rx, ry; diff --git a/src/elements/pipe.cpp b/src/elements/pipe.cpp index 08432f5..40ef411 100644 --- a/src/elements/pipe.cpp +++ b/src/elements/pipe.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" signed char pos_1_rx[] = {-1,-1,-1, 0, 0, 1, 1, 1}; signed char pos_1_ry[] = {-1, 0, 1,-1, 1,-1, 0, 1}; diff --git a/src/elements/plnt.cpp b/src/elements/plnt.cpp index a44c8c2..ef7985f 100644 --- a/src/elements/plnt.cpp +++ b/src/elements/plnt.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PLNT(UPDATE_FUNC_ARGS) { int r, rx, ry, np; diff --git a/src/elements/plsm.cpp b/src/elements/plsm.cpp index c6f7c20..f8b3865 100644 --- a/src/elements/plsm.cpp +++ b/src/elements/plsm.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" #include "hmap.h" int graphics_PLSM(GRAPHICS_FUNC_ARGS) diff --git a/src/elements/plut.cpp b/src/elements/plut.cpp index 3e2820d..7c51b2d 100644 --- a/src/elements/plut.cpp +++ b/src/elements/plut.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PLUT(UPDATE_FUNC_ARGS) { if (1>rand()%100 && ((int)(5.0f*sim->pv[y/CELL][x/CELL]))>(rand()%1000)) diff --git a/src/elements/prti.cpp b/src/elements/prti.cpp index df212d4..9bbbf26 100644 --- a/src/elements/prti.cpp +++ b/src/elements/prti.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" /*these are the count values of where the particle gets stored, depending on where it came from 0 1 2 7 . 3 diff --git a/src/elements/prto.cpp b/src/elements/prto.cpp index ee61abf..32e7251 100644 --- a/src/elements/prto.cpp +++ b/src/elements/prto.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" /*these are the count values of where the particle gets stored, depending on where it came from 0 1 2 7 . 3 diff --git a/src/elements/pump.cpp b/src/elements/pump.cpp index 8a7254e..af05c02 100644 --- a/src/elements/pump.cpp +++ b/src/elements/pump.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PUMP(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/pvod.cpp b/src/elements/pvod.cpp index e645d0a..1a48ca8 100644 --- a/src/elements/pvod.cpp +++ b/src/elements/pvod.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PVOD(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/pyro.cpp b/src/elements/pyro.cpp index 790e295..81f00f7 100644 --- a/src/elements/pyro.cpp +++ b/src/elements/pyro.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_PYRO(UPDATE_FUNC_ARGS) { int r, rx, ry, rt, t = parts[i].type; diff --git a/src/elements/qrtz.cpp b/src/elements/qrtz.cpp index 7768765..c33cacb 100644 --- a/src/elements/qrtz.cpp +++ b/src/elements/qrtz.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_QRTZ(UPDATE_FUNC_ARGS) { int r, tmp, trade, rx, ry, np, t; diff --git a/src/elements/rime.cpp b/src/elements/rime.cpp index 617414b..878b928 100644 --- a/src/elements/rime.cpp +++ b/src/elements/rime.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_RIME(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/shld.cpp b/src/elements/shld.cpp index cbe8306..ade7edb 100644 --- a/src/elements/shld.cpp +++ b/src/elements/shld.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SHLD1(UPDATE_FUNC_ARGS) { int r, nnx, nny, rx, ry; diff --git a/src/elements/sing.cpp b/src/elements/sing.cpp index fa6121c..de1e329 100644 --- a/src/elements/sing.cpp +++ b/src/elements/sing.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SING(UPDATE_FUNC_ARGS) { int r, rx, ry, cry, crx, rad, nxi, nxj, nb, j, spawncount; diff --git a/src/elements/sltw.cpp b/src/elements/sltw.cpp index c965fd4..507602c 100644 --- a/src/elements/sltw.cpp +++ b/src/elements/sltw.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SLTW(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/smke.cpp b/src/elements/smke.cpp index d19bd0a..e9311bd 100644 --- a/src/elements/smke.cpp +++ b/src/elements/smke.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int graphics_SMKE(GRAPHICS_FUNC_ARGS) { diff --git a/src/elements/soap.cpp b/src/elements/soap.cpp index 0d31292..0d1054f 100644 --- a/src/elements/soap.cpp +++ b/src/elements/soap.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SOAP(UPDATE_FUNC_ARGS) { diff --git a/src/elements/spng.cpp b/src/elements/spng.cpp index 28b3e1b..868b1e6 100644 --- a/src/elements/spng.cpp +++ b/src/elements/spng.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SPNG(UPDATE_FUNC_ARGS) { int r, trade, rx, ry, tmp, np; diff --git a/src/elements/sprk.cpp b/src/elements/sprk.cpp index 244e831..80f66a2 100644 --- a/src/elements/sprk.cpp +++ b/src/elements/sprk.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SPRK(UPDATE_FUNC_ARGS) { int r, rx, ry, rt, conduct_sprk, nearp, pavg, ct = parts[i].ctype; diff --git a/src/elements/stkm.cpp b/src/elements/stkm.cpp index 322eba1..c457b62 100644 --- a/src/elements/stkm.cpp +++ b/src/elements/stkm.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SPAWN(UPDATE_FUNC_ARGS) { if (!sim->player.spwn) diff --git a/src/elements/stkm2.cpp b/src/elements/stkm2.cpp index 967bea2..d18a7ac 100644 --- a/src/elements/stkm2.cpp +++ b/src/elements/stkm2.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SPAWN2(UPDATE_FUNC_ARGS) { if (!sim->player2.spwn) diff --git a/src/elements/stor.cpp b/src/elements/stor.cpp index 66eb072..414caad 100644 --- a/src/elements/stor.cpp +++ b/src/elements/stor.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_STOR(UPDATE_FUNC_ARGS) { int r, rx, ry, np, rx1, ry1; diff --git a/src/elements/swch.cpp b/src/elements/swch.cpp index ee2c467..f37192b 100644 --- a/src/elements/swch.cpp +++ b/src/elements/swch.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_SWCH(UPDATE_FUNC_ARGS) { int r, rt, rx, ry; diff --git a/src/elements/thdr.cpp b/src/elements/thdr.cpp index f7f95b4..1e3d0ab 100644 --- a/src/elements/thdr.cpp +++ b/src/elements/thdr.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_THDR(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/thrm.cpp b/src/elements/thrm.cpp index 91939e6..2075e13 100644 --- a/src/elements/thrm.cpp +++ b/src/elements/thrm.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_THRM(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/uran.cpp b/src/elements/uran.cpp index a8b2a06..31e93a7 100644 --- a/src/elements/uran.cpp +++ b/src/elements/uran.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_URAN(UPDATE_FUNC_ARGS) { if (!sim->legacy_enable && sim->pv[y/CELL][x/CELL]>0.0f) diff --git a/src/elements/vine.cpp b/src/elements/vine.cpp index 165d391..c8d51ba 100644 --- a/src/elements/vine.cpp +++ b/src/elements/vine.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_VINE(UPDATE_FUNC_ARGS) { int r, np, rx =(rand()%3)-1, ry=(rand()%3)-1; diff --git a/src/elements/warp.cpp b/src/elements/warp.cpp index ddc1b81..88315a9 100644 --- a/src/elements/warp.cpp +++ b/src/elements/warp.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_WARP(UPDATE_FUNC_ARGS) { int trade, r, rx, ry; diff --git a/src/elements/watr.cpp b/src/elements/watr.cpp index 09b66a9..b44fa22 100644 --- a/src/elements/watr.cpp +++ b/src/elements/watr.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/element.h" int update_WATR(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/wifi.cpp b/src/elements/wifi.cpp index ee5e264..cb77dd9 100644 --- a/src/elements/wifi.cpp +++ b/src/elements/wifi.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_WIFI(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/wire.cpp b/src/elements/wire.cpp index 49d3720..f7202e4 100644 --- a/src/elements/wire.cpp +++ b/src/elements/wire.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_WIRE(UPDATE_FUNC_ARGS) { int s,r,rx,ry,count; diff --git a/src/elements/wtrv.cpp b/src/elements/wtrv.cpp index de0eae4..2e3838a 100644 --- a/src/elements/wtrv.cpp +++ b/src/elements/wtrv.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_WTRV(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/elements/yest.cpp b/src/elements/yest.cpp index c6c7db6..5b3fc95 100644 --- a/src/elements/yest.cpp +++ b/src/elements/yest.cpp @@ -1,4 +1,4 @@ -#include "element.h" +#include "simulation/Element.h" int update_YEST(UPDATE_FUNC_ARGS) { int r, rx, ry; diff --git a/src/game/GameController.cpp b/src/game/GameController.cpp index becb540..e029fc9 100644 --- a/src/game/GameController.cpp +++ b/src/game/GameController.cpp @@ -4,6 +4,7 @@ #include "Config.h" #include "GameController.h" #include "GameModel.h" +#include "search/SearchController.h" #include "interface/Point.h" using namespace std; @@ -60,3 +61,9 @@ void GameController::SetPaused(bool pauseState) { gameModel->SetPaused(pauseState); } + +void GameController::OpenSearch() +{ + SearchController * search = new SearchController(); + ui::Engine::Ref().ShowWindow(search->GetView()); +} diff --git a/src/game/GameController.h b/src/game/GameController.h index c3c8273..d9755a1 100644 --- a/src/game/GameController.h +++ b/src/game/GameController.h @@ -5,7 +5,7 @@ #include "GameView.h" #include "GameModel.h" #include "interface/Point.h" -#include "Simulation.h" +#include "simulation/Simulation.h" using namespace std; @@ -23,6 +23,7 @@ public: void DrawPoints(queue & pointQueue); void Tick(); void SetPaused(bool pauseState); + void OpenSearch(); }; #endif // GAMECONTROLLER_H diff --git a/src/game/GameModel.cpp b/src/game/GameModel.cpp index 96b29a9..3d5a800 100644 --- a/src/game/GameModel.cpp +++ b/src/game/GameModel.cpp @@ -1,7 +1,7 @@ #include "interface/Engine.h" #include "GameModel.h" #include "GameView.h" -#include "Simulation.h" +#include "simulation/Simulation.h" #include "Renderer.h" GameModel::GameModel(): diff --git a/src/game/GameModel.h b/src/game/GameModel.h index a2eb3ce..6cb74cb 100644 --- a/src/game/GameModel.h +++ b/src/game/GameModel.h @@ -2,7 +2,7 @@ #define GAMEMODEL_H #include -#include "Simulation.h" +#include "simulation/Simulation.h" #include "Renderer.h" #include "GameView.h" diff --git a/src/game/GameView.cpp b/src/game/GameView.cpp index 2576527..2fbed31 100644 --- a/src/game/GameView.cpp +++ b/src/game/GameView.cpp @@ -24,6 +24,21 @@ GameView::GameView(): pauseButton->SetTogglable(true); pauseButton->SetActionCallback(new PauseAction(this)); AddComponent(pauseButton); + + class SearchAction : public ui::ButtonAction + { + GameView * v; + public: + SearchAction(GameView * _v) { v = _v; } + void ActionCallback(ui::Button * sender) + { + v->c->OpenSearch(); + } + }; + searchButton = new ui::Button(ui::Point(1, Size.Y-18), ui::Point(16, 16), "\x81"); //Open + searchButton->SetTogglable(false); + searchButton->SetActionCallback(new SearchAction(this)); + AddComponent(searchButton); } void GameView::NotifyRendererChanged(GameModel * sender) diff --git a/src/game/GameView.h b/src/game/GameView.h index 531a4b9..f34aedc 100644 --- a/src/game/GameView.h +++ b/src/game/GameView.h @@ -21,20 +21,13 @@ private: Renderer * ren; //UI Elements ui::Button * pauseButton; + ui::Button * searchButton; public: GameView(); void AttachController(GameController * _c){ c = _c; } void NotifyRendererChanged(GameModel * sender); void NotifySimulationChanged(GameModel * sender); void NotifyPausedChanged(GameModel * sender); - /*virtual void DoMouseMove(int x, int y, int dx, int dy); - virtual void DoMouseDown(int x, int y, unsigned button); - virtual void DoMouseUp(int x, int y, unsigned button); - //virtual void DoMouseWheel(int x, int y, int d); - //virtual void DoKeyPress(int key, bool shift, bool ctrl, bool alt); - //virtual void DoKeyRelease(int key, bool shift, bool ctrl, bool alt); - virtual void DoTick(float dt); - virtual void DoDraw();*/ virtual void OnMouseMove(int x, int y, int dx, int dy); virtual void OnMouseDown(int x, int y, unsigned button); virtual void OnMouseUp(int x, int y, unsigned button); diff --git a/src/interface/Button.cpp b/src/interface/Button.cpp index a3f76b9..affa75d 100644 --- a/src/interface/Button.cpp +++ b/src/interface/Button.cpp @@ -11,6 +11,7 @@ #include "Graphics.h" #include "Global.h" #include "Engine.h" +#include "Misc.h" namespace ui { @@ -20,9 +21,12 @@ Button::Button(Window* parent_state, std::string buttonText): isMouseInside(false), isButtonDown(false), isTogglable(false), - actionCallback(NULL) + actionCallback(NULL), + textPosition(ui::Point(0, 0)), + textVAlign(AlignMiddle), + textHAlign(AlignCentre) { - + TextPosition(); } Button::Button(Point position, Point size, std::string buttonText): @@ -31,9 +35,12 @@ Button::Button(Point position, Point size, std::string buttonText): isMouseInside(false), isButtonDown(false), isTogglable(false), - actionCallback(NULL) + actionCallback(NULL), + textPosition(ui::Point(0, 0)), + textVAlign(AlignMiddle), + textHAlign(AlignCentre) { - + TextPosition(); } Button::Button(std::string buttonText): @@ -42,9 +49,48 @@ Button::Button(std::string buttonText): isMouseInside(false), isButtonDown(false), isTogglable(false), - actionCallback(NULL) + actionCallback(NULL), + textPosition(ui::Point(0, 0)), + textVAlign(AlignMiddle), + textHAlign(AlignCentre) { + TextPosition(); +} + +void Button::TextPosition() +{ + //Position.X+(Size.X-Graphics::textwidth((char *)ButtonText.c_str()))/2, Position.Y+(Size.Y-10)/2 + switch(textVAlign) + { + case AlignTop: + textPosition.Y = 3; + break; + case AlignMiddle: + textPosition.Y = (Size.Y-10)/2; + break; + case AlignBottom: + textPosition.Y = Size.Y-11; + break; + } + switch(textHAlign) + { + case AlignLeft: + textPosition.X = 3; + break; + case AlignCentre: + textPosition.X = (Size.X-Graphics::textwidth((char *)ButtonText.c_str()))/2; + break; + case AlignRight: + textPosition.X = (Size.X-Graphics::textwidth((char *)ButtonText.c_str()))-2; + break; + } +} + +void Button::SetText(std::string buttonText) +{ + ButtonText = buttonText; + TextPosition(); } void Button::SetTogglable(bool togglable) @@ -68,25 +114,21 @@ inline void Button::SetToggleState(bool state) toggle = state; } - - void Button::Draw(const Point& screenPos) { Graphics * g = ui::Engine::Ref().g; Point Position = screenPos; - // = reinterpret_cast(userdata); - //TODO: Cache text location, that way we don't have the text alignment code here if(isButtonDown || (isTogglable && toggle)) { g->fillrect(Position.X-1, Position.Y-1, Size.X+2, Size.Y+2, 255, 255, 255, 255); - g->drawtext(Position.X+(Size.X-Graphics::textwidth((char *)ButtonText.c_str()))/2, Position.Y+(Size.Y-10)/2, ButtonText, 0, 0, 0, 255); + g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, ButtonText, 0, 0, 0, 255); } else { if(isMouseInside) g->fillrect(Position.X, Position.Y, Size.X, Size.Y, 20, 20, 20, 255); g->drawrect(Position.X, Position.Y, Size.X, Size.Y, 255, 255, 255, 255); - g->drawtext(Position.X+(Size.X-Graphics::textwidth((char *)ButtonText.c_str()))/2, Position.Y+(Size.Y-10)/2, ButtonText, 255, 255, 255, 255); + g->drawtext(Position.X+textPosition.X, Position.Y+textPosition.Y, ButtonText, 255, 255, 255, 255); } /*sf::RenderWindow* rw = reinterpret_cast(userdata); //it better be a RenderWindow or so help your god diff --git a/src/interface/Button.h b/src/interface/Button.h index 5f2d71f..aabca91 100644 --- a/src/interface/Button.h +++ b/src/interface/Button.h @@ -9,7 +9,7 @@ #define BUTTON_H_ #include - +#include "Misc.h" #include "Component.h" namespace ui @@ -51,10 +51,18 @@ public: inline bool GetToggleState(); inline void SetToggleState(bool state); void SetActionCallback(ButtonAction * action); - + void TextPosition(); + void SetText(std::string buttonText); + HorizontalAlignment GetHAlignment() { return textHAlign; } + VerticalAlignment GetVAlignment() { return textVAlign; } + void SetAlignment(HorizontalAlignment hAlign, VerticalAlignment vAlign) { textHAlign = hAlign; textVAlign = vAlign; TextPosition(); } protected: bool isButtonDown, state, isMouseInside, isTogglable, toggle; ButtonAction * actionCallback; + ui::Point textPosition; + HorizontalAlignment textHAlign; + VerticalAlignment textVAlign; + }; } #endif /* BUTTON_H_ */ diff --git a/src/interface/Engine.cpp b/src/interface/Engine.cpp index 55a2370..130fc8e 100644 --- a/src/interface/Engine.cpp +++ b/src/interface/Engine.cpp @@ -47,10 +47,9 @@ void Engine::ShowWindow(Window * window) { if(state_) { - windows.push(window); + windows.push(state_); } state_ = window; - windows.push(window); } void Engine::CloseWindow() diff --git a/src/interface/Sandbox.cpp b/src/interface/Sandbox.cpp deleted file mode 100644 index 9a858f8..0000000 --- a/src/interface/Sandbox.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Sandbox.cpp - * - * Created on: Jan 8, 2012 - * Author: Simon - */ - -#include -#include - -#include "Config.h" -#include "Global.h" - -#include "interface/Point.h" -#include "interface/Sandbox.h" -#include "interface/Component.h" -#include "Renderer.h" -#include "Simulation.h" -#include "Engine.h" - -namespace ui { - -Sandbox::Sandbox(): - Component(Point(0, 0), Point(XRES, YRES)), - pointQueue(std::queue()), - ren(NULL), - isMouseDown(false), - activeElement(1) -{ - sim = new Simulation(); -} - -Simulation * Sandbox::GetSimulation() -{ - return sim; -} - -void Sandbox::OnMouseMoved(int localx, int localy, int dx, int dy) -{ - if(isMouseDown) - { - pointQueue.push(new Point(localx-dx, localy-dy)); - pointQueue.push(new Point(localx, localy)); - } -} - -void Sandbox::OnMouseClick(int localx, int localy, unsigned int button) -{ - isMouseDown = true; - pointQueue.push(new Point(localx, localy)); -} - -void Sandbox::OnMouseUp(int localx, int localy, unsigned int button) -{ - if(isMouseDown) - { - isMouseDown = false; - pointQueue.push(new Point(localx, localy)); - } -} - -void Sandbox::Draw(const Point& screenPos) -{ - Graphics * g = Engine::Ref().g; - if(!ren) - ren = new Renderer(g, sim); - ren->render_parts(); -} - -void Sandbox::Tick(float delta) -{ - if(!pointQueue.empty()) - { - Point * sPoint = NULL; - while(!pointQueue.empty()) - { - Point * fPoint = pointQueue.front(); - pointQueue.pop(); - if(sPoint) - { - sim->create_line(fPoint->X, fPoint->Y, sPoint->X, sPoint->Y, 1, 1, activeElement, 0); - delete sPoint; - } - else - { - sim->create_parts(fPoint->X, fPoint->Y, 1, 1, activeElement, 0); - } - sPoint = fPoint; - } - if(sPoint) - delete sPoint; - } - sim->update_particles(); - sim->sys_pause = 1; -} - -Sandbox::~Sandbox() { - // TODO Auto-generated destructor stub -} - -} /* namespace ui */ diff --git a/src/interface/Sandbox.h b/src/interface/Sandbox.h deleted file mode 100644 index fb4a668..0000000 --- a/src/interface/Sandbox.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Sandbox.h - * - * Created on: Jan 8, 2012 - * Author: Simon - */ - -#ifndef SANDBOX_H_ -#define SANDBOX_H_ - -#include -#include "Point.h" -#include "Component.h" -#include "Simulation.h" -#include "Renderer.h" - -namespace ui { - -class Sandbox: public ui::Component { -private: - int lastCoordX, lastCoordY; - int activeElement; - std::queue pointQueue; - bool isMouseDown; - Renderer * ren; - Simulation * sim; -public: - Sandbox(); - virtual Simulation * GetSimulation(); - virtual void OnMouseMoved(int localx, int localy, int dx, int dy); - virtual void OnMouseClick(int localx, int localy, unsigned int button); - virtual void OnMouseUp(int localx, int localy, unsigned int button); - virtual void Draw(const Point& screenPos); - virtual void Tick(float delta); - virtual ~Sandbox(); -}; - -} /* namespace ui */ -#endif /* SANDBOX_H_ */ diff --git a/src/interface/SaveButton.cpp b/src/interface/SaveButton.cpp new file mode 100644 index 0000000..18f3281 --- /dev/null +++ b/src/interface/SaveButton.cpp @@ -0,0 +1,157 @@ +#include + +#include "SaveButton.h" +#include "search/Save.h" +#include "Graphics.h" +#include "Global.h" +#include "Engine.h" +#include "client/Client.h" + +namespace ui { + +SaveButton::SaveButton(Window* parent_state, Save save): + Component(parent_state), + save(save), + thumbnail(NULL), + isMouseInside(false), + isButtonDown(false), + actionCallback(NULL) +{ + +} + +SaveButton::SaveButton(Point position, Point size, Save save): + Component(position, size), + save(save), + thumbnail(NULL), + isMouseInside(false), + isButtonDown(false), + actionCallback(NULL) +{ + +} + +SaveButton::SaveButton(Save save): + Component(), + save(save), + thumbnail(NULL), + isMouseInside(false), + isButtonDown(false), + actionCallback(NULL) +{ + +} + +SaveButton::~SaveButton() +{ + if(thumbnail) + delete thumbnail; +} + +void SaveButton::Tick(float dt) +{ + Thumbnail * tempThumb; + float scaleFactorY = 1.0f, scaleFactorX = 1.0f; + if(!thumbnail) + { + tempThumb = Client::Ref().GetThumbnail(save.GetID(), 0); + if(tempThumb) + { + thumbnail = tempThumb; //Store a local copy of the thumbnail + if(thumbnail->Data) + { + if(thumbnail->Size.Y > (Size.Y-25)) + { + scaleFactorY = ((float)(Size.Y-25))/((float)thumbnail->Size.Y); + } + if(thumbnail->Size.X > Size.X) + { + scaleFactorX = ((float)Size.X)/((float)thumbnail->Size.X); + } + if(scaleFactorY < 1.0f || scaleFactorX < 1.0f) + { + float scaleFactor = scaleFactorY < scaleFactorX ? scaleFactorY : scaleFactorX; + pixel * thumbData = thumbnail->Data; + thumbnail->Data = Graphics::resample_img(thumbData, thumbnail->Size.X, thumbnail->Size.Y, thumbnail->Size.X * scaleFactor, thumbnail->Size.Y * scaleFactor); + thumbnail->Size.X *= scaleFactor; + thumbnail->Size.Y *= scaleFactor; + free(thumbData); + } + } + } + } +} + +void SaveButton::Draw(const Point& screenPos) +{ + Graphics * g = ui::Engine::Ref().g; + float scaleFactor; + + if(thumbnail) + { + g->draw_image(thumbnail->Data, screenPos.X+(Size.X-thumbnail->Size.X)/2, screenPos.Y+((Size.Y-25)-thumbnail->Size.Y)/2, thumbnail->Size.X, thumbnail->Size.Y, 255); + g->drawrect(screenPos.X+(Size.X-thumbnail->Size.X)/2, screenPos.Y+((Size.Y-25)-thumbnail->Size.Y)/2, thumbnail->Size.X, thumbnail->Size.Y, 180, 180, 180, 255); + } + else + { + scaleFactor = (Size.Y-25)/((float)YRES); + g->drawrect(screenPos.X+(Size.X-((float)XRES)*scaleFactor)/2, screenPos.Y+((Size.Y-21)-((float)YRES)*scaleFactor)/2, ((float)XRES)*scaleFactor, ((float)YRES)*scaleFactor, 180, 180, 180, 255); + } + + if(isMouseInside) + { + g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, 255, 255, 255, 255); + g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)save.name.c_str()))/2, screenPos.Y+Size.Y - 21, save.name, 255, 255, 255, 255); + g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)save.userName.c_str()))/2, screenPos.Y+Size.Y - 10, save.userName, 200, 230, 255, 255); + } + else + { + g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)save.name.c_str()))/2, screenPos.Y+Size.Y - 21, save.name, 180, 180, 180, 255); + g->drawtext(screenPos.X+(Size.X-Graphics::textwidth((char *)save.userName.c_str()))/2, screenPos.Y+Size.Y - 10, save.userName, 100, 130, 160, 255); + } +} + +void SaveButton::OnMouseUnclick(int x, int y, unsigned int button) +{ + if(button != 1) + { + return; //left click only! + } + + if(isButtonDown) + { + DoAction(); + } + + isButtonDown = false; +} + +void SaveButton::OnMouseClick(int x, int y, unsigned int button) +{ + if(button != 1) return; //left click only! + isButtonDown = true; +} + +void SaveButton::OnMouseEnter(int x, int y) +{ + isMouseInside = true; +} + +void SaveButton::OnMouseLeave(int x, int y) +{ + isMouseInside = false; +} + +void SaveButton::DoAction() +{ + std::cout << "Do action!" << std::endl; + if(actionCallback) + actionCallback->ActionCallback(this); +} + +void SaveButton::SetActionCallback(SaveButtonAction * action) +{ + actionCallback = action; +} + +} /* namespace ui */ diff --git a/src/interface/SaveButton.h b/src/interface/SaveButton.h new file mode 100644 index 0000000..8834d8a --- /dev/null +++ b/src/interface/SaveButton.h @@ -0,0 +1,50 @@ +#ifndef SAVEBUTTON_H_ +#define SAVEBUTTON_H_ + +#include + +#include "Component.h" +#include "search/Save.h" +#include "Graphics.h" +#include "search/Thumbnail.h" + +namespace ui +{ +class SaveButton; +class SaveButtonAction +{ +public: + virtual void ActionCallback(ui::SaveButton * sender) {} +}; + +class SaveButton : public Component +{ + Save save; + Thumbnail * thumbnail; +public: + SaveButton(Window* parent_state, Save save); + + SaveButton(Point position, Point size, Save save); + + SaveButton(Save save); + virtual ~SaveButton(); + + virtual void OnMouseClick(int x, int y, unsigned int button); + virtual void OnMouseUnclick(int x, int y, unsigned int button); + + virtual void OnMouseEnter(int x, int y); + virtual void OnMouseLeave(int x, int y); + + virtual void Draw(const Point& screenPos); + virtual void Tick(float dt); + + inline bool GetState() { return state; } + virtual void DoAction(); + void SetActionCallback(SaveButtonAction * action); +protected: + bool isButtonDown, state, isMouseInside; + SaveButtonAction * actionCallback; +}; +} +#endif /* BUTTON_H_ */ + diff --git a/src/search/Save.h b/src/search/Save.h index a3ef485..91a1ec4 100644 --- a/src/search/Save.h +++ b/src/search/Save.h @@ -10,8 +10,6 @@ class Save private: int id; int votesUp, votesDown; - string userName; - string name; public: Save(int _id, int _votesUp, int _votesDown, string _userName, string _name): id(_id), @@ -22,6 +20,9 @@ public: { } + string userName; + string name; + void SetName(string name){ this->name = name; } string GetName(){ return name; } diff --git a/src/search/SearchController.cpp b/src/search/SearchController.cpp index cf13f2e..90750e0 100644 --- a/src/search/SearchController.cpp +++ b/src/search/SearchController.cpp @@ -8,6 +8,9 @@ SearchController::SearchController() searchModel = new SearchModel(); searchView = new SearchView(); searchModel->AddObserver(searchView); + searchView->AttachController(this); + + searchModel->UpdateSaveList(); //Set up interface //windowPanel.AddChild(); diff --git a/src/search/SearchController.h b/src/search/SearchController.h index 8755a07..10dd9bd 100644 --- a/src/search/SearchController.h +++ b/src/search/SearchController.h @@ -4,15 +4,16 @@ #include "interface/Panel.h" #include "SearchModel.h" #include "SearchView.h" - +class SearchView; +class SearchModel; class SearchController { private: SearchModel * searchModel; SearchView * searchView; - ui::Panel * windowPanel; public: SearchController(); + SearchView * GetView() { return searchView; } }; #endif // SEARCHCONTROLLER_H diff --git a/src/search/SearchModel.cpp b/src/search/SearchModel.cpp index 63188bd..494d490 100644 --- a/src/search/SearchModel.cpp +++ b/src/search/SearchModel.cpp @@ -9,10 +9,24 @@ void SearchModel::UpdateSaveList() { saveList.clear(); notifySaveListChanged(); - saveList.push_back(Save(1, 45, 5, "Simon", "Post logic gates")); + for(int i = 0; i < 16; i++) + { + saveList.push_back(Save(2198, 2333, 315, "dima-gord", "Destroyable city 5 (wth metro)")); + } notifySaveListChanged(); } +vector SearchModel::GetSaveList() +{ + return saveList; +} + +void SearchModel::AddObserver(SearchView * observer) +{ + observers.push_back(observer); + observer->NotifySaveListChanged(this); +} + void SearchModel::notifySaveListChanged() { for(int i = 0; i < observers.size(); i++) diff --git a/src/search/SearchModel.h b/src/search/SearchModel.h index 0951577..85d4177 100644 --- a/src/search/SearchModel.h +++ b/src/search/SearchModel.h @@ -7,6 +7,7 @@ using namespace std; +class SearchView; class SearchModel { private: @@ -15,7 +16,7 @@ private: void notifySaveListChanged(); public: SearchModel(); - void AddObserver(SearchView * observer){ observers.push_back(observer); } + void AddObserver(SearchView * observer); void UpdateSaveList(); vector GetSaveList(); }; diff --git a/src/search/SearchView.cpp b/src/search/SearchView.cpp index 4b551f3..29d6eef 100644 --- a/src/search/SearchView.cpp +++ b/src/search/SearchView.cpp @@ -1,10 +1,60 @@ #include "SearchView.h" +#include "interface/SaveButton.h" +#include "Misc.h" -SearchView::SearchView() +SearchView::SearchView(): + ui::Window(ui::Point(0, 0), ui::Point(XRES+BARSIZE, YRES+MENUSIZE)), + saveButtons(vector()) { + nextButton = new ui::Button(ui::Point(XRES+BARSIZE-52, YRES+MENUSIZE-18), ui::Point(50, 16), "Next \x95"); + previousButton = new ui::Button(ui::Point(1, YRES+MENUSIZE-18), ui::Point(50, 16), "\x96 Prev"); + + nextButton->SetAlignment(AlignRight, AlignBottom); + previousButton->SetAlignment(AlignLeft, AlignBottom); + AddComponent(nextButton); + AddComponent(previousButton); } -void SearchView::NotifySaveListChanged(SearchModel * sender) +SearchView::~SearchView() { +} +void SearchView::NotifySaveListChanged(SearchModel * sender) +{ + int i = 0; + int buttonWidth, buttonHeight, saveX = 0, saveY = 0, savesX = 4, savesY = 3, buttonPadding = 2; + int buttonAreaWidth, buttonAreaHeight, buttonXOffset, buttonYOffset; + buttonXOffset = 0; + buttonYOffset = 50; + buttonAreaWidth = Size.X; + buttonAreaHeight = Size.Y - buttonYOffset - 18; + buttonWidth = (buttonAreaWidth/savesX) - buttonPadding*2; + buttonHeight = (buttonAreaHeight/savesY) - buttonPadding*2; + for(i = 0; i < saveButtons.size(); i++) + { + RemoveComponent(saveButtons[i]); + delete saveButtons[i]; + } + vector saves = sender->GetSaveList(); + for(i = 0; i < saves.size(); i++) + { + if(saveX == savesX) + { + if(saveY == savesY-1) + break; + saveX = 0; + saveY++; + } + ui::SaveButton * saveButton; + saveButton = new ui::SaveButton( + ui::Point( + buttonXOffset + buttonPadding + saveX*(buttonWidth+buttonPadding*2), + buttonYOffset + buttonPadding + saveY*(buttonHeight+buttonPadding*2) + ), + ui::Point(buttonWidth, buttonHeight), + saves[i]); + saveButtons.push_back(saveButton); + AddComponent(saveButton); + saveX++; + } } diff --git a/src/search/SearchView.h b/src/search/SearchView.h index e540f21..c68d42c 100644 --- a/src/search/SearchView.h +++ b/src/search/SearchView.h @@ -1,13 +1,28 @@ #ifndef SEARCHVIEW_H #define SEARCHVIEW_H +#include +#include "SearchController.h" +#include "interface/SaveButton.h" +#include "interface/Button.h" + +using namespace std; + class SearchModel; +class SearchController; -class SearchView +class SearchView: public ui::Window { +private: + SearchController * c; + vector saveButtons; + ui::Button * nextButton; + ui::Button * previousButton; public: void NotifySaveListChanged(SearchModel * sender); SearchView(); + virtual ~SearchView(); + void AttachController(SearchController * _c) { c = _c; } }; #endif // SEARCHVIEW_H diff --git a/src/search/Thumbnail.h b/src/search/Thumbnail.h new file mode 100644 index 0000000..3b865ca --- /dev/null +++ b/src/search/Thumbnail.h @@ -0,0 +1,49 @@ +#ifndef THUMBNAIL_H +#define THUMBNAIL_H + +#include "Graphics.h" +#include "interface/Point.h" + +class Thumbnail +{ +public: + Thumbnail(const Thumbnail & thumb): + ID(thumb.ID), + Datestamp(thumb.Datestamp), + Data(thumb.Data), + Size(thumb.Size) + { + //Ensure the actual thumbnail data is copied + if(thumb.Data) + { + Data = (pixel *)malloc((thumb.Size.X*thumb.Size.Y) * PIXELSIZE); + memcpy(Data, thumb.Data, (thumb.Size.X*thumb.Size.Y) * PIXELSIZE); + } + else + { + Data = NULL; + } + } + + Thumbnail(int _id, int _datestamp, pixel * _data, ui::Point _size): + ID(_id), + Datestamp(_datestamp), + Data(_data), + Size(_size) + { + } + + ~Thumbnail() + { + if(Data) + { + free(Data); + } + } + + int ID, Datestamp; + ui::Point Size; + pixel * Data; +}; + +#endif // THUMBNAIL_H diff --git a/src/simulation/Air.cpp b/src/simulation/Air.cpp new file mode 100644 index 0000000..2d8d1b5 --- /dev/null +++ b/src/simulation/Air.cpp @@ -0,0 +1,301 @@ +#include +#include "Config.h" +#include "Air.h" +//#include +//#include +#include "gravity.h" + +/*float kernel[9]; + +float vx[YRES/CELL][XRES/CELL], ovx[YRES/CELL][XRES/CELL]; +float vy[YRES/CELL][XRES/CELL], ovy[YRES/CELL][XRES/CELL]; +float pv[YRES/CELL][XRES/CELL], opv[YRES/CELL][XRES/CELL]; +unsigned char bmap_blockair[YRES/CELL][XRES/CELL]; + +float cb_vx[YRES/CELL][XRES/CELL]; +float cb_vy[YRES/CELL][XRES/CELL]; +float cb_pv[YRES/CELL][XRES/CELL]; +float cb_hv[YRES/CELL][XRES/CELL]; + +float fvx[YRES/CELL][XRES/CELL], fvy[YRES/CELL][XRES/CELL]; + +float hv[YRES/CELL][XRES/CELL], ohv[YRES/CELL][XRES/CELL]; // For Ambient Heat */ + +void Air::make_kernel(void) //used for velocity +{ + int i, j; + float s = 0.0f; + for (j=-1; j<2; j++) + for (i=-1; i<2; i++) + { + kernel[(i+1)+3*(j+1)] = expf(-2.0f*(i*i+j*j)); + s += kernel[(i+1)+3*(j+1)]; + } + s = 1.0f / s; + for (j=-1; j<2; j++) + for (i=-1; i<2; i++) + kernel[(i+1)+3*(j+1)] *= s; +} +void Air::update_airh(void) +{ + int x, y, i, j; + float dh, dx, dy, f, tx, ty; + for (i=0; i0 && y+j0 && x+i=2 && i=2 && j0) + vy[y][x] -= airdiff/5000.0f; + } + ohv[y][x] = dh; + } + } + memcpy(hv, ohv, sizeof(hv)); +} + +void Air::update_air(void) +{ + int x, y, i, j; + float dp, dx, dy, f, tx, ty; + + for (y=0; y0 && y+j0 && x+i=2 && i=2 && j 256.0f) dp = 256.0f; + if (dp < -256.0f) dp = -256.0f; + if (dx > 256.0f) dx = 256.0f; + if (dx < -256.0f) dx = -256.0f; + if (dy > 256.0f) dy = 256.0f; + if (dy < -256.0f) dy = -256.0f; + + + switch (airMode) + { + default: + case 0: //Default + break; + case 1: //0 Pressure + dp = 0.0f; + break; + case 2: //0 Velocity + dx = 0.0f; + dy = 0.0f; + break; + case 3: //0 Air + dx = 0.0f; + dy = 0.0f; + dp = 0.0f; + break; + case 4: //No Update + break; + } + + ovx[y][x] = dx; + ovy[y][x] = dy; + opv[y][x] = dp; + } + memcpy(vx, ovx, sizeof(vx)); + memcpy(vy, ovy, sizeof(vy)); + memcpy(pv, opv, sizeof(pv)); + } +} +Air::Air() +{ + //Simulation should do this. + make_kernel(); +} diff --git a/src/simulation/Air.h b/src/simulation/Air.h new file mode 100644 index 0000000..8e4dc25 --- /dev/null +++ b/src/simulation/Air.h @@ -0,0 +1,33 @@ +#ifndef AIR_H +#define AIR_H +#include "Config.h" + +class Simulation; + +class Air +{ +public: + int airMode; + //Arrays from the simulation + unsigned char (*bmap)[XRES/CELL]; + unsigned char (*emap)[XRES/CELL]; + float (*fvx)[XRES/CELL]; + float (*fvy)[XRES/CELL]; + // + float vx[YRES/CELL][XRES/CELL]; + float ovx[YRES/CELL][XRES/CELL]; + float vy[YRES/CELL][XRES/CELL]; + float ovy[YRES/CELL][XRES/CELL]; + float pv[YRES/CELL][XRES/CELL]; + float opv[YRES/CELL][XRES/CELL]; + float hv[YRES/CELL][XRES/CELL]; + float ohv[YRES/CELL][XRES/CELL]; // Ambient Heat + unsigned char bmap_blockair[YRES/CELL][XRES/CELL]; + float kernel[9]; + void make_kernel(void); + void update_airh(void); + void update_air(void); + Air(); +}; + +#endif diff --git a/src/simulation/Element.h b/src/simulation/Element.h new file mode 100644 index 0000000..449bf51 --- /dev/null +++ b/src/simulation/Element.h @@ -0,0 +1,14 @@ +#ifndef ELEMENT_H +#define ELEMENT_H +// This header should be included by all files in src/elements/ + +#include +#include "Simulation.h" +#include "Renderer.h" +#include "ElementFunctions.h" +//#include "powder.h" +#include "Gravity.h" +#include "Misc.h" +#include "ElementGraphics.h" + +#endif diff --git a/src/simulation/ElementFunctions.h b/src/simulation/ElementFunctions.h new file mode 100644 index 0000000..ef80b6f --- /dev/null +++ b/src/simulation/ElementFunctions.h @@ -0,0 +1,168 @@ +/* + * ElementFunctions.h + * + * Created on: Jan 5, 2012 + * Author: Simon + */ + +#ifndef ELEMENTFUNCTIONS_H_ +#define ELEMENTFUNCTIONS_H_ +#include "Elements.h" + +int update_ACID(UPDATE_FUNC_ARGS); +int update_ANAR(UPDATE_FUNC_ARGS); +int update_AMTR(UPDATE_FUNC_ARGS); +int update_ARAY(UPDATE_FUNC_ARGS); +int update_BCLN(UPDATE_FUNC_ARGS); +int update_BCOL(UPDATE_FUNC_ARGS); +int update_BMTL(UPDATE_FUNC_ARGS); +int update_BRMT(UPDATE_FUNC_ARGS); +int update_BOMB(UPDATE_FUNC_ARGS); +int update_BOYL(UPDATE_FUNC_ARGS); +int update_BTRY(UPDATE_FUNC_ARGS); +int update_C5(UPDATE_FUNC_ARGS); +int update_CLNE(UPDATE_FUNC_ARGS); +int update_COAL(UPDATE_FUNC_ARGS); +int update_DEUT(UPDATE_FUNC_ARGS); +int update_DSTW(UPDATE_FUNC_ARGS); +int update_FOG(UPDATE_FUNC_ARGS); +int update_FRZW(UPDATE_FUNC_ARGS); +int update_FRZZ(UPDATE_FUNC_ARGS); +int update_FSEP(UPDATE_FUNC_ARGS); +int update_FUSE(UPDATE_FUNC_ARGS); +int update_FIRW(UPDATE_FUNC_ARGS); +int update_FWRK(UPDATE_FUNC_ARGS); +int update_GLAS(UPDATE_FUNC_ARGS); +int update_GLOW(UPDATE_FUNC_ARGS); +int update_GOO(UPDATE_FUNC_ARGS); +int update_HSWC(UPDATE_FUNC_ARGS); +int update_IRON(UPDATE_FUNC_ARGS); +int update_ICEI(UPDATE_FUNC_ARGS); +int update_ISZ(UPDATE_FUNC_ARGS); +int update_LCRY(UPDATE_FUNC_ARGS); +int update_MORT(UPDATE_FUNC_ARGS); +int update_NEUT(UPDATE_FUNC_ARGS); +int update_NPTCT(UPDATE_FUNC_ARGS); +int update_PCLN(UPDATE_FUNC_ARGS); +int update_PHOT(UPDATE_FUNC_ARGS); +int update_PIPE(UPDATE_FUNC_ARGS); +int update_PLNT(UPDATE_FUNC_ARGS); +int update_PLUT(UPDATE_FUNC_ARGS); +int update_PRTI(UPDATE_FUNC_ARGS); +int update_PRTO(UPDATE_FUNC_ARGS); +int update_PYRO(UPDATE_FUNC_ARGS); +int update_PUMP(UPDATE_FUNC_ARGS); +int update_QRTZ(UPDATE_FUNC_ARGS); +int update_RIME(UPDATE_FUNC_ARGS); +int update_SHLD1(UPDATE_FUNC_ARGS); +int update_SHLD2(UPDATE_FUNC_ARGS); +int update_SHLD3(UPDATE_FUNC_ARGS); +int update_SHLD4(UPDATE_FUNC_ARGS); +int update_SING(UPDATE_FUNC_ARGS); +int update_SLTW(UPDATE_FUNC_ARGS); +int update_SPAWN(UPDATE_FUNC_ARGS); +int update_SPAWN2(UPDATE_FUNC_ARGS); +int update_SPNG(UPDATE_FUNC_ARGS); +int update_SPRK(UPDATE_FUNC_ARGS); +int update_STKM(UPDATE_FUNC_ARGS); +int update_STKM2(UPDATE_FUNC_ARGS); +int update_SWCH(UPDATE_FUNC_ARGS); +int update_THDR(UPDATE_FUNC_ARGS); +int update_THRM(UPDATE_FUNC_ARGS); +int update_URAN(UPDATE_FUNC_ARGS); +int update_VINE(UPDATE_FUNC_ARGS); +int update_WARP(UPDATE_FUNC_ARGS); +int update_WATR(UPDATE_FUNC_ARGS); +int update_WIFI(UPDATE_FUNC_ARGS); +int update_WTRV(UPDATE_FUNC_ARGS); +int update_YEST(UPDATE_FUNC_ARGS); +int update_SOAP(UPDATE_FUNC_ARGS); +int update_O2(UPDATE_FUNC_ARGS); +int update_H2(UPDATE_FUNC_ARGS); +int update_NBHL(UPDATE_FUNC_ARGS); +int update_NWHL(UPDATE_FUNC_ARGS); +int update_MERC(UPDATE_FUNC_ARGS); +int update_PBCN(UPDATE_FUNC_ARGS); +int update_GPMP(UPDATE_FUNC_ARGS); +int update_CLST(UPDATE_FUNC_ARGS); +int update_DLAY(UPDATE_FUNC_ARGS); +int update_WIRE(UPDATE_FUNC_ARGS); +int update_GBMB(UPDATE_FUNC_ARGS); +int update_CO2(UPDATE_FUNC_ARGS); +int update_CBNW(UPDATE_FUNC_ARGS); +int update_STOR(UPDATE_FUNC_ARGS); +int update_BIZR(UPDATE_FUNC_ARGS); +int update_PVOD(UPDATE_FUNC_ARGS); +int update_CONV(UPDATE_FUNC_ARGS); +int update_CAUS(UPDATE_FUNC_ARGS); +int update_DEST(UPDATE_FUNC_ARGS); +int update_EMP(UPDATE_FUNC_ARGS); +int update_LIGH(UPDATE_FUNC_ARGS); +int update_FIGH(UPDATE_FUNC_ARGS); +int update_ELEC(UPDATE_FUNC_ARGS); +int update_ACEL(UPDATE_FUNC_ARGS); +int update_DCEL(UPDATE_FUNC_ARGS); +int update_BANG(UPDATE_FUNC_ARGS); +int update_IGNT(UPDATE_FUNC_ARGS); +int update_MISC(UPDATE_FUNC_ARGS); +int update_legacy_PYRO(UPDATE_FUNC_ARGS); +int update_legacy_all(UPDATE_FUNC_ARGS); +int run_stickman(playerst* playerp, UPDATE_FUNC_ARGS); +void STKM_init_legs(Simulation * sim, playerst* playerp, int i); +void STKM_interact(Simulation * sim, playerst* playerp, int i, int x, int y); + + +int graphics_FIRE(GRAPHICS_FUNC_ARGS); +int graphics_SMKE(GRAPHICS_FUNC_ARGS); +int graphics_PLSM(GRAPHICS_FUNC_ARGS); +int graphics_DEUT(GRAPHICS_FUNC_ARGS); +int graphics_PHOT(GRAPHICS_FUNC_ARGS); +int graphics_NEUT(GRAPHICS_FUNC_ARGS); +int graphics_LAVA(GRAPHICS_FUNC_ARGS); +int graphics_SPRK(GRAPHICS_FUNC_ARGS); +int graphics_QRTZ(GRAPHICS_FUNC_ARGS); +int graphics_CLST(GRAPHICS_FUNC_ARGS); +int graphics_CBNW(GRAPHICS_FUNC_ARGS); +int graphics_SPNG(GRAPHICS_FUNC_ARGS); +int graphics_LIFE(GRAPHICS_FUNC_ARGS); +int graphics_DUST(GRAPHICS_FUNC_ARGS); +int graphics_GRAV(GRAPHICS_FUNC_ARGS); +int graphics_WIFI(GRAPHICS_FUNC_ARGS); +int graphics_PRTI(GRAPHICS_FUNC_ARGS); +int graphics_PRTO(GRAPHICS_FUNC_ARGS); +int graphics_BIZR(GRAPHICS_FUNC_ARGS); +int graphics_PIPE(GRAPHICS_FUNC_ARGS); +int graphics_INVS(GRAPHICS_FUNC_ARGS); +int graphics_ACID(GRAPHICS_FUNC_ARGS); +int graphics_FILT(GRAPHICS_FUNC_ARGS); +int graphics_BRAY(GRAPHICS_FUNC_ARGS); +int graphics_SWCH(GRAPHICS_FUNC_ARGS); +int graphics_THDR(GRAPHICS_FUNC_ARGS); +int graphics_GLOW(GRAPHICS_FUNC_ARGS); +int graphics_LCRY(GRAPHICS_FUNC_ARGS); +int graphics_PCLN(GRAPHICS_FUNC_ARGS); +int graphics_PBCN(GRAPHICS_FUNC_ARGS); +int graphics_DLAY(GRAPHICS_FUNC_ARGS); +int graphics_HSWC(GRAPHICS_FUNC_ARGS); +int graphics_PVOD(GRAPHICS_FUNC_ARGS); +int graphics_STOR(GRAPHICS_FUNC_ARGS); +int graphics_PUMP(GRAPHICS_FUNC_ARGS); +int graphics_GPMP(GRAPHICS_FUNC_ARGS); +int graphics_HFLM(GRAPHICS_FUNC_ARGS); +int graphics_FIRW(GRAPHICS_FUNC_ARGS); +int graphics_BOMB(GRAPHICS_FUNC_ARGS); +int graphics_GBMB(GRAPHICS_FUNC_ARGS); +int graphics_COAL(GRAPHICS_FUNC_ARGS); +int graphics_STKM(GRAPHICS_FUNC_ARGS); +int graphics_STKM2(GRAPHICS_FUNC_ARGS); +int graphics_DEST(GRAPHICS_FUNC_ARGS); +int graphics_EMP(GRAPHICS_FUNC_ARGS); +int graphics_LIGH(GRAPHICS_FUNC_ARGS); +int graphics_FIGH(GRAPHICS_FUNC_ARGS); +int graphics_ELEC(GRAPHICS_FUNC_ARGS); +int graphics_WIRE(GRAPHICS_FUNC_ARGS); +int graphics_ACEL(GRAPHICS_FUNC_ARGS); +int graphics_DCEL(GRAPHICS_FUNC_ARGS); +int graphics_DEFAULT(GRAPHICS_FUNC_ARGS); + +#endif /* ELEMENTFUNCTIONS_H_ */ diff --git a/src/simulation/ElementGraphics.h b/src/simulation/ElementGraphics.h new file mode 100644 index 0000000..a880e71 --- /dev/null +++ b/src/simulation/ElementGraphics.h @@ -0,0 +1,52 @@ +#ifndef PGRAPHICS_H +#define PGRAPHICS_H + +#define PMODE 0x00000FFF +#define PMODE_NONE 0x00000000 +#define PMODE_FLAT 0x00000001 +#define PMODE_BLOB 0x00000002 +#define PMODE_BLUR 0x00000004 +#define PMODE_GLOW 0x00000008 +#define PMODE_SPARK 0x00000010 +#define PMODE_FLARE 0x00000020 +#define PMODE_LFLARE 0x00000040 +#define PMODE_ADD 0x00000080 +#define PMODE_BLEND 0x00000100 +#define PSPEC_STICKMAN 0x00000200 + +#define OPTIONS 0x0000F000 +#define NO_DECO 0x00001000 +#define DECO_FIRE 0x00002000 + +#define FIREMODE 0x00FF0000 +#define FIRE_ADD 0x00010000 +#define FIRE_BLEND 0x00020000 + +#define EFFECT 0xFF000000 +#define EFFECT_GRAVIN 0x01000000 +#define EFFECT_GRAVOUT 0x02000000 + +#define RENDER_EFFE OPTIONS | PSPEC_STICKMAN | EFFECT | PMODE_SPARK | PMODE_FLARE | PMODE_LFLARE +#define RENDER_FIRE OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_ADD | PMODE_BLEND | FIREMODE +#define RENDER_GLOW OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_GLOW | PMODE_ADD | PMODE_BLEND +#define RENDER_BLUR OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_BLUR | PMODE_ADD | PMODE_BLEND +#define RENDER_BLOB OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_BLOB | PMODE_ADD | PMODE_BLEND +#define RENDER_BASC OPTIONS | PSPEC_STICKMAN | PMODE_FLAT | PMODE_ADD | PMODE_BLEND +#define RENDER_NONE OPTIONS | PSPEC_STICKMAN | PMODE_FLAT + +#define COLOUR_HEAT 0x00000001 +#define COLOUR_LIFE 0x00000002 +#define COLOUR_GRAD 0x00000004 + +#define COLOUR_DEFAULT 0x00000000 + +#define DISPLAY_AIRC 0x00000001 +#define DISPLAY_AIRP 0x00000002 +#define DISPLAY_AIRV 0x00000004 +#define DISPLAY_AIRH 0x00000008 +#define DISPLAY_AIR 0x0000000F +#define DISPLAY_WARP 0x00000010 +#define DISPLAY_PERS 0x00000020 +#define DISPLAY_EFFE 0x00000040 + +#endif diff --git a/src/simulation/Elements.h b/src/simulation/Elements.h new file mode 100644 index 0000000..204460c --- /dev/null +++ b/src/simulation/Elements.h @@ -0,0 +1,280 @@ +/* + * Elements.h + * + * Created on: Jan 5, 2012 + * Author: Simon + */ + +//#ifndef ELEMENTS_H_ +//#define ELEMENTS_H_ + +//#include "Config.h" +//#include "Simulation.h" + +#define IPL -257.0f +#define IPH 257.0f +#define ITL MIN_TEMP-1 +#define ITH MAX_TEMP+1 +// no transition (PT_NONE means kill part) +#define NT -1 +// special transition - lava ctypes etc need extra code, which is only found and run if ST is given +#define ST PT_NUM + +#define R_TEMP 22 +#define MAX_TEMP 9999 +#define MIN_TEMP 0 +#define O_MAX_TEMP 3500 +#define O_MIN_TEMP -273 + +#define TYPE_PART 0x00001 //1 Powders +#define TYPE_LIQUID 0x00002 //2 Liquids +#define TYPE_SOLID 0x00004 //4 Solids +#define TYPE_GAS 0x00008 //8 Gasses (Includes plasma) +#define TYPE_ENERGY 0x00010 //16 Energy (Thunder, Light, Neutrons etc.) +#define PROP_CONDUCTS 0x00020 //32 Conducts electricity +#define PROP_BLACK 0x00040 //64 Absorbs Photons (not currently implemented or used, a photwl attribute might be better) +#define PROP_NEUTPENETRATE 0x00080 //128 Penetrated by neutrons +#define PROP_NEUTABSORB 0x00100 //256 Absorbs neutrons, reflect is default (not currently implemented or used) +#define PROP_NEUTPASS 0x00200 //512 Neutrons pass through, such as with glass +#define PROP_DEADLY 0x00400 //1024 Is deadly for stickman (not currently implemented or used) +#define PROP_HOT_GLOW 0x00800 //2048 Hot Metal Glow +#define PROP_LIFE 0x01000 //4096 Is a GoL type +#define PROP_RADIOACTIVE 0x02000 //8192 Radioactive +#define PROP_LIFE_DEC 0x04000 //2^14 Life decreases by one every frame if > zero +#define PROP_LIFE_KILL 0x08000 //2^15 Kill when life value is <= zero +#define PROP_LIFE_KILL_DEC 0x10000 //2^16 Kill when life value is decremented to <= zero +#define PROP_SPARKSETTLE 0x20000 //2^17 Allow Sparks/Embers to settle + +#define FLAG_STAGNANT 1 + +#define ST_NONE 0 +#define ST_SOLID 1 +#define ST_LIQUID 2 +#define ST_GAS 3 + +#define UPDATE_FUNC_ARGS Simulation* sim, int i, int x, int y, int surround_space, int nt, Particle *parts, int pmap[YRES][XRES] +// to call another update function with same arguments: +#define UPDATE_FUNC_SUBCALL_ARGS sim, i, x, y, surround_space, nt, parts, pmap + +#define GRAPHICS_FUNC_ARGS Renderer * ren, Particle *cpart, int nx, int ny, int *pixel_mode, int* cola, int *colr, int *colg, int *colb, int *firea, int *firer, int *fireg, int *fireb +#define GRAPHICS_FUNC_SUBCALL_ARGS ren, cpart, nx, ny, pixel_mode, cola, colr, colg, colb, firea, firer, fireg, fireb + +#define UI_WALLSTART 222 +#define UI_ACTUALSTART 122 +#define UI_WALLCOUNT 25 + +#define WL_WALLELEC 122 +#define WL_EWALL 123 +#define WL_DETECT 124 +#define WL_STREAM 125 +#define WL_SIGN 126 +#define WL_FAN 127 +#define WL_FANHELPER 255 +#define WL_ALLOWLIQUID 128 +#define WL_DESTROYALL 129 +#define WL_ERASE 130 +#define WL_WALL 131 +#define WL_ALLOWAIR 132 +#define WL_ALLOWSOLID 133 +#define WL_ALLOWALLELEC 134 +#define WL_EHOLE 135 + +#define SPC_AIR 236 +#define SPC_HEAT 237 +#define SPC_COOL 238 +#define SPC_VACUUM 239 +#define SPC_WIND 241 +#define SPC_PGRV 243 +#define SPC_NGRV 244 +#define SPC_PROP 246 + +#define WL_ALLOWGAS 140 +#define WL_GRAV 142 +#define WL_ALLOWENERGY 145 + +#define NGT_GOL 0 +#define NGT_HLIF 1 +#define NGT_ASIM 2 +#define NGT_2x2 3 +#define NGT_DANI 4 +#define NGT_AMOE 5 +#define NGT_MOVE 6 +#define NGT_PGOL 7 +#define NGT_DMOE 8 +#define NGT_34 9 +#define NGT_LLIF 10 +#define NGT_STAN 11 +#define NGT_SEED 12 +#define NGT_MAZE 13 +#define NGT_COAG 14 +#define NGT_WALL 15 +#define NGT_GNAR 16 +#define NGT_REPL 17 +#define NGT_MYST 18 +#define NGT_LOTE 19 +#define NGT_FRG2 20 +#define NGT_STAR 21 +#define NGT_FROG 22 +#define NGT_BRAN 23 + +#define PT_NONE 0 +#define PT_DUST 1 +#define PT_WATR 2 +#define PT_OIL 3 +#define PT_FIRE 4 +#define PT_STNE 5 +#define PT_LAVA 6 +#define PT_GUNP 7 +#define PT_NITR 8 +#define PT_CLNE 9 +#define PT_GAS 10 +#define PT_PLEX 11 +#define PT_GOO 12 +#define PT_ICEI 13 +#define PT_METL 14 +#define PT_SPRK 15 +#define PT_SNOW 16 +#define PT_WOOD 17 +#define PT_NEUT 18 +#define PT_PLUT 19 +#define PT_PLNT 20 +#define PT_ACID 21 +#define PT_VOID 22 +#define PT_WTRV 23 +#define PT_CNCT 24 +#define PT_DSTW 25 +#define PT_SALT 26 +#define PT_SLTW 27 +#define PT_DMND 28 +#define PT_BMTL 29 +#define PT_BRMT 30 +#define PT_PHOT 31 +#define PT_URAN 32 +#define PT_WAX 33 +#define PT_MWAX 34 +#define PT_PSCN 35 +#define PT_NSCN 36 +#define PT_LNTG 37 +#define PT_INSL 38 +#define PT_BHOL 39 +#define PT_WHOL 40 +#define PT_RBDM 41 +#define PT_LRBD 42 +#define PT_NTCT 43 +#define PT_SAND 44 +#define PT_GLAS 45 +#define PT_PTCT 46 +#define PT_BGLA 47 +#define PT_THDR 48 +#define PT_PLSM 49 +#define PT_ETRD 50 +#define PT_NICE 51 +#define PT_NBLE 52 +#define PT_BTRY 53 +#define PT_LCRY 54 +#define PT_STKM 55 +#define PT_SWCH 56 +#define PT_SMKE 57 +#define PT_DESL 58 +#define PT_COAL 59 +#define PT_LO2 60 +#define PT_O2 61 +#define PT_INWR 62 +#define PT_YEST 63 +#define PT_DYST 64 +#define PT_THRM 65 +#define PT_GLOW 66 +#define PT_BRCK 67 +#define PT_HFLM 68 +#define PT_FIRW 69 +#define PT_FUSE 70 +#define PT_FSEP 71 +#define PT_AMTR 72 +#define PT_BCOL 73 +#define PT_PCLN 74 +#define PT_HSWC 75 +#define PT_IRON 76 +#define PT_MORT 77 +#define PT_LIFE 78 +#define PT_DLAY 79 +#define PT_CO2 80 +#define PT_DRIC 81 +#define PT_CBNW 82 +#define PT_STOR 83 +#define PT_PVOD 84 +#define PT_CONV 85 +#define PT_CAUS 86 + +#define PT_LIGH 87 +#define PT_TESC 88 +#define PT_DEST 89 + +#define PT_SPNG 90 +#define PT_RIME 91 +#define PT_FOG 92 +#define PT_BCLN 93 +#define PT_LOVE 94 +#define PT_DEUT 95 +#define PT_WARP 96 +#define PT_PUMP 97 +#define PT_FWRK 98 +#define PT_PIPE 99 +#define PT_FRZZ 100 +#define PT_FRZW 101 +#define PT_GRAV 102 +#define PT_BIZR 103 +#define PT_BIZRG 104 +#define PT_BIZRS 105 +#define PT_INST 106 +#define PT_ISOZ 107 +#define PT_ISZS 108 +#define PT_PRTI 109 +#define PT_PRTO 110 +#define PT_PSTE 111 +#define PT_PSTS 112 +#define PT_ANAR 113 +#define PT_VINE 114 +#define PT_INVIS 115 +#define PT_EQUALVEL 116 //all particles equal their velocities +#define PT_SPAWN2 117 +#define PT_SPAWN 118 +#define PT_SHLD1 119 +#define PT_SHLD2 120 +#define PT_SHLD3 121 +#define PT_SHLD4 122 +#define PT_LOLZ 123 +#define PT_WIFI 124 +#define PT_FILT 125 +#define PT_ARAY 126 +#define PT_BRAY 127 +#define PT_STKM2 128 +#define PT_BOMB 129 +#define PT_C5 130 +#define PT_SING 131 +#define PT_QRTZ 132 +#define PT_PQRT 133 +#define PT_EMP 134 +#define PT_BREC 135 +#define PT_ELEC 136 +#define PT_ACEL 137 +#define PT_DCEL 138 +#define PT_BANG 139 +#define PT_IGNT 140 +#define PT_BOYL 141 + +#define OLD_PT_WIND 147 +#define PT_H2 148 +#define PT_SOAP 149 +#define PT_NBHL 150 +#define PT_NWHL 151 +#define PT_MERC 152 +#define PT_PBCN 153 +#define PT_GPMP 154 +#define PT_CLST 155 +#define PT_WIRE 156 +#define PT_GBMB 157 +#define PT_FIGH 158 +#define PT_NUM 159 + + +//#endif /* ELEMENTS_H_ */ diff --git a/src/simulation/Gravity.cpp b/src/simulation/Gravity.cpp new file mode 100644 index 0000000..cc20b2f --- /dev/null +++ b/src/simulation/Gravity.cpp @@ -0,0 +1,488 @@ +#include +#include +#include +#include "Config.h" +#include "Gravity.h" +//#include "powder.h" + +#ifdef GRAVFFT +#include +#endif + +void Gravity::bilinear_interpolation(float *src, float *dst, int sw, int sh, int rw, int rh) +{ + int y, x, fxceil, fyceil; + float fx, fy, fyc, fxc; + double intp; + float tr, tl, br, bl; + //Bilinear interpolation for upscaling + for (y=0; y=sw) fxceil = sw-1; + if (fyceil>=sh) fyceil = sh-1; + tr = src[sw*(int)floor(fy)+fxceil]; + tl = src[sw*(int)floor(fy)+(int)floor(fx)]; + br = src[sw*fyceil+fxceil]; + bl = src[sw*fyceil+(int)floor(fx)]; + dst[rw*y+x] = ((tl*(1.0f-fxc))+(tr*(fxc)))*(1.0f-fyc) + ((bl*(1.0f-fxc))+(br*(fxc)))*(fyc); + } +} + +void Gravity::gravity_init() +{ + //Allocate full size Gravmaps + th_ogravmap = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + th_gravmap = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + th_gravy = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + th_gravx = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + th_gravp = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + gravmap = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + gravy = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + gravx = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + gravp = (float *)calloc((XRES/CELL)*(YRES/CELL), sizeof(float)); + gravmask = (unsigned int *)calloc((XRES/CELL)*(YRES/CELL), sizeof(unsigned)); +} + +void Gravity::gravity_cleanup() +{ +#ifdef GRAVFFT + grav_fft_cleanup(); +#endif +} + +void Gravity::gravity_update_async() +{ + int result; + if(ngrav_enable) + { + pthread_mutex_lock(&gravmutex); + result = grav_ready; + if(result) //Did the gravity thread finish? + { + //if (!sys_pause||framerender){ //Only update if not paused + //Switch the full size gravmaps, we don't really need the two above any more + float *tmpf; + + if(th_gravchanged) + { + #if !defined(GRAVFFT) && defined(GRAV_DIFF) + memcpy(gravy, th_gravy, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memcpy(gravx, th_gravx, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memcpy(gravp, th_gravp, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + #else + tmpf = gravy; + gravy = th_gravy; + th_gravy = tmpf; + + tmpf = gravx; + gravx = th_gravx; + th_gravx = tmpf; + + tmpf = gravp; + gravp = th_gravp; + th_gravp = tmpf; + #endif + } + + tmpf = gravmap; + gravmap = th_gravmap; + th_gravmap = tmpf; + + grav_ready = 0; //Tell the other thread that we're ready for it to continue + pthread_cond_signal(&gravcv); + //} + } + pthread_mutex_unlock(&gravmutex); + //Apply the gravity mask + membwand(gravy, gravmask, (XRES/CELL)*(YRES/CELL)*sizeof(float), (XRES/CELL)*(YRES/CELL)*sizeof(unsigned)); + membwand(gravx, gravmask, (XRES/CELL)*(YRES/CELL)*sizeof(float), (XRES/CELL)*(YRES/CELL)*sizeof(unsigned)); + memset(gravmap, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + } +} + +void *Gravity::update_grav_async_helper(void * context) +{ + ((Gravity *)context)->update_grav_async(); +} + +void Gravity::update_grav_async() +{ + int done = 0; + int thread_done = 0; + memset(th_ogravmap, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(th_gravmap, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(th_gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(th_gravx, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(th_gravp, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + //memset(th_gravy, 0, XRES*YRES*sizeof(float)); + //memset(th_gravx, 0, XRES*YRES*sizeof(float)); + //memset(th_gravp, 0, XRES*YRES*sizeof(float)); +#ifdef GRAVFFT + grav_fft_init(); +#endif + while(!thread_done){ + if(!done){ + update_grav(); + done = 1; + pthread_mutex_lock(&gravmutex); + + grav_ready = done; + thread_done = gravthread_done; + + pthread_mutex_unlock(&gravmutex); + } else { + pthread_mutex_lock(&gravmutex); + pthread_cond_wait(&gravcv, &gravmutex); + + done = grav_ready; + thread_done = gravthread_done; + + pthread_mutex_unlock(&gravmutex); + } + } + pthread_exit(NULL); +} + +void Gravity::start_grav_async() +{ + if(!ngrav_enable){ + gravthread_done = 0; + grav_ready = 0; + pthread_mutex_init (&gravmutex, NULL); + pthread_cond_init(&gravcv, NULL); + pthread_create(&gravthread, NULL, &Gravity::update_grav_async_helper, this); //Start asynchronous gravity simulation + ngrav_enable = 1; + } + memset(gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(gravx, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(gravp, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); +} + +void Gravity::stop_grav_async() +{ + if(ngrav_enable){ + pthread_mutex_lock(&gravmutex); + gravthread_done = 1; + pthread_cond_signal(&gravcv); + pthread_mutex_unlock(&gravmutex); + pthread_join(gravthread, NULL); + pthread_mutex_destroy(&gravmutex); //Destroy the mutex + ngrav_enable = 0; + } + //Clear the grav velocities + memset(gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(gravx, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); + memset(gravp, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float)); +} + +#ifdef GRAVFFT +int grav_fft_status = 0; +float *th_ptgravx, *th_ptgravy, *th_gravmapbig, *th_gravxbig, *th_gravybig; +fftwf_complex *th_ptgravxt, *th_ptgravyt, *th_gravmapbigt, *th_gravxbigt, *th_gravybigt; +fftwf_plan plan_gravmap, plan_gravx_inverse, plan_gravy_inverse; + +void Gravity::grav_fft_init() +{ + int xblock2 = XRES/CELL*2; + int yblock2 = YRES/CELL*2; + int x, y, fft_tsize = (xblock2/2+1)*yblock2; + float distance, scaleFactor; + fftwf_plan plan_ptgravx, plan_ptgravy; + if (grav_fft_status) return; + + //use fftw malloc function to ensure arrays are aligned, to get better performance + th_ptgravx = fftwf_malloc(xblock2*yblock2*sizeof(float)); + th_ptgravy = fftwf_malloc(xblock2*yblock2*sizeof(float)); + th_ptgravxt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); + th_ptgravyt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); + th_gravmapbig = fftwf_malloc(xblock2*yblock2*sizeof(float)); + th_gravmapbigt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); + th_gravxbig = fftwf_malloc(xblock2*yblock2*sizeof(float)); + th_gravybig = fftwf_malloc(xblock2*yblock2*sizeof(float)); + th_gravxbigt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); + th_gravybigt = fftwf_malloc(fft_tsize*sizeof(fftwf_complex)); + + //select best algorithm, could use FFTW_PATIENT or FFTW_EXHAUSTIVE but that increases the time taken to plan, and I don't see much increase in execution speed + plan_ptgravx = fftwf_plan_dft_r2c_2d(yblock2, xblock2, th_ptgravx, th_ptgravxt, FFTW_MEASURE); + plan_ptgravy = fftwf_plan_dft_r2c_2d(yblock2, xblock2, th_ptgravy, th_ptgravyt, FFTW_MEASURE); + plan_gravmap = fftwf_plan_dft_r2c_2d(yblock2, xblock2, th_gravmapbig, th_gravmapbigt, FFTW_MEASURE); + plan_gravx_inverse = fftwf_plan_dft_c2r_2d(yblock2, xblock2, th_gravxbigt, th_gravxbig, FFTW_MEASURE); + plan_gravy_inverse = fftwf_plan_dft_c2r_2d(yblock2, xblock2, th_gravybigt, th_gravybig, FFTW_MEASURE); + + //(XRES/CELL)*(YRES/CELL)*4 is size of data array, scaling needed because FFTW calculates an unnormalized DFT + scaleFactor = -M_GRAV/((XRES/CELL)*(YRES/CELL)*4); + //calculate velocity map caused by a point mass + for (y=0; y 0.0001f || th_gravmap[i*(XRES/CELL)+j]<-0.0001f) //Only calculate with populated or changed cells. + { +#endif + for (y = 0; y < YRES / CELL; y++) { + for (x = 0; x < XRES / CELL; x++) { + if (x == j && y == i)//Ensure it doesn't calculate with itself + continue; + distance = sqrt(pow(j - x, 2) + pow(i - y, 2)); +#ifdef GRAV_DIFF + val = th_gravmap[i*(XRES/CELL)+j] - th_ogravmap[i*(XRES/CELL)+j]; +#else + val = th_gravmap[i*(XRES/CELL)+j]; +#endif + th_gravx[y*(XRES/CELL)+x] += M_GRAV * val * (j - x) / pow(distance, 3); + th_gravy[y*(XRES/CELL)+x] += M_GRAV * val * (i - y) / pow(distance, 3); + th_gravp[y*(XRES/CELL)+x] += M_GRAV * val / pow(distance, 2); + } + } + } + } + } +fin: + memcpy(th_ogravmap, th_gravmap, (XRES/CELL)*(YRES/CELL)*sizeof(float)); +} +#endif + + + +void Gravity::grav_mask_r(int x, int y, char checkmap[YRES/CELL][XRES/CELL], char shape[YRES/CELL][XRES/CELL], char *shapeout) +{ + if(x < 0 || x >= XRES/CELL || y < 0 || y >= YRES/CELL) + return; + if(x == 0 || y ==0 || y == (YRES/CELL)-1 || x == (XRES/CELL)-1) + *shapeout = 1; + checkmap[y][x] = 1; + shape[y][x] = 1; + if(x-1 >= 0 && !checkmap[y][x-1] && bmap[y][x-1]!=WL_GRAV) + grav_mask_r(x-1, y, checkmap, shape, shapeout); + if(y-1 >= 0 && !checkmap[y-1][x] && bmap[y-1][x]!=WL_GRAV) + grav_mask_r(x, y-1, checkmap, shape, shapeout); + if(x+1 < XRES/CELL && !checkmap[y][x+1] && bmap[y][x+1]!=WL_GRAV) + grav_mask_r(x+1, y, checkmap, shape, shapeout); + if(y+1 < YRES/CELL && !checkmap[y+1][x] && bmap[y+1][x]!=WL_GRAV) + grav_mask_r(x, y+1, checkmap, shape, shapeout); + return; +} +void Gravity::mask_free(mask_el *c_mask_el){ + if(c_mask_el==NULL) + return; + if(c_mask_el->next!=NULL) + mask_free((mask_el*)c_mask_el->next); + free(c_mask_el->shape); + free(c_mask_el); +} +void Gravity::gravity_mask() +{ + char checkmap[YRES/CELL][XRES/CELL]; + int x = 0, y = 0, i, j; + unsigned maskvalue; + mask_el *t_mask_el = NULL; + mask_el *c_mask_el = NULL; + if(!gravmask) + return; + memset(checkmap, 0, sizeof(checkmap)); + for(x = 0; x < XRES/CELL; x++) + { + for(y = 0; y < YRES/CELL; y++) + { + if(bmap[y][x]!=WL_GRAV && checkmap[y][x] == 0) + { + //Create a new shape + if(t_mask_el==NULL){ + t_mask_el = (mask_el *)malloc(sizeof(mask_el)); + t_mask_el->shape = (char *)malloc((XRES/CELL)*(YRES/CELL)); + memset(t_mask_el->shape, 0, (XRES/CELL)*(YRES/CELL)); + t_mask_el->shapeout = 0; + t_mask_el->next = NULL; + c_mask_el = t_mask_el; + } else { + c_mask_el->next = (mask_el *)malloc(sizeof(mask_el)); + c_mask_el = (mask_el *)c_mask_el->next; + c_mask_el->shape = (char *)malloc((XRES/CELL)*(YRES/CELL)); + memset(c_mask_el->shape, 0, (XRES/CELL)*(YRES/CELL)); + c_mask_el->shapeout = 0; + c_mask_el->next = NULL; + } + //Fill the shape + grav_mask_r(x, y, (char (*)[XRES/CELL])checkmap, (char (*)[XRES/CELL])c_mask_el->shape, (char*)&c_mask_el->shapeout); + } + } + } + c_mask_el = t_mask_el; + memset(gravmask, 0, (XRES/CELL)*(YRES/CELL)*sizeof(unsigned)); + while(c_mask_el!=NULL) + { + char *cshape = c_mask_el->shape; + for(x = 0; x < XRES/CELL; x++) + { + for(y = 0; y < YRES/CELL; y++) + { + if(cshape[y*(XRES/CELL)+x]){ + if(c_mask_el->shapeout) + maskvalue = 0xFFFFFFFF; + else + maskvalue = 0x00000000; + gravmask[y*(XRES/CELL)+x] = maskvalue; + } + } + } + c_mask_el = (mask_el*)c_mask_el->next; + } + mask_free(t_mask_el); +} + +Gravity::Gravity() +{ + gravity_init(); +} diff --git a/src/simulation/Gravity.h b/src/simulation/Gravity.h new file mode 100644 index 0000000..9f36240 --- /dev/null +++ b/src/simulation/Gravity.h @@ -0,0 +1,108 @@ +#ifndef GRAVITY_H +#define GRAVITY_H + +#include +#include "Config.h" +#include "Simulation.h" + +class Simulation; + +struct mask_el { + char *shape; + char shapeout; + void *next; +}; +typedef struct mask_el mask_el; + + +/* + * float *gravmap = NULL;//Maps to be used by the main thread + float *gravp = NULL; + float *gravy = NULL; + float *gravx = NULL; + unsigned *gravmask = NULL; + + float *th_ogravmap = NULL;// Maps to be processed by the gravity thread + float *th_gravmap = NULL; + float *th_gravx = NULL; + float *th_gravy = NULL; + float *th_gravp = NULL; + + int th_gravchanged = 0; + + pthread_t gravthread; + pthread_mutex_t gravmutex; + pthread_cond_t gravcv; + int grav_ready = 0; + int gravthread_done = 0; + */ +class Gravity +{ +private: + unsigned *gravmask; + + float *th_ogravmap; + float *th_gravmap; + float *th_gravx; + float *th_gravy; + float *th_gravp; + + int th_gravchanged; + + pthread_t gravthread; + pthread_mutex_t gravmutex; + pthread_cond_t gravcv; + int grav_ready; + int gravthread_done; + + //Simulation * sim; +public: + float *gravmap; + float *gravp; + float *gravy; + float *gravx; + unsigned char (*bmap)[XRES/CELL]; + int ngrav_enable; + void grav_mask_r(int x, int y, char checkmap[YRES/CELL][XRES/CELL], char shape[YRES/CELL][XRES/CELL], char *shapeout); + void mask_free(mask_el *c_mask_el); + + void gravity_init(); + void gravity_cleanup(); + void gravity_update_async(); + + static void *update_grav_async_helper(void * context); + void update_grav_async(); + + void start_grav_async(); + void stop_grav_async(); + void update_grav(); + void gravity_mask(); + + void bilinear_interpolation(float *src, float *dst, int sw, int sh, int rw, int rh); + + #ifdef GRAVFFT + void grav_fft_init(); + void grav_fft_cleanup(); + #endif + + Gravity(); +}; + +/*extern int ngrav_enable; //Newtonian gravity +extern int gravwl_timeout; +extern int gravityMode;*/ + +/*float *gravmap;//Maps to be used by the main thread +float *gravp; +float *gravy; +float *gravx; +unsigned *gravmask; + +float *th_ogravmap;// Maps to be processed by the gravity thread +float *th_gravmap; +float *th_gravx; +float *th_gravy; +float *th_gravp;*/ + + +#endif diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp new file mode 100644 index 0000000..a1a785a --- /dev/null +++ b/src/simulation/Simulation.cpp @@ -0,0 +1,3593 @@ +#include +#include +#define _cplusplus +#include "Config.h" +#include "Simulation.h" +#include "Elements.h" +#include "ElementFunctions.h" +#include "Air.h" +#include "Gravity.h" +//#include "powder.h" + +void Simulation::clear_area(int area_x, int area_y, int area_w, int area_h) +{ + int cx = 0; + int cy = 0; + for (cy=0; cyx2) + { + i = x2; + x2 = x1; + x1 = i; + } + if (y1>y2) + { + j = y2; + y2 = y1; + y1 = j; + } + for (j=y1; j<=y2; j++) + for (i=x1; i<=x2; i++) + create_parts(i, j, 0, 0, c, flags); +} + +int Simulation::flood_prop_2(int x, int y, size_t propoffset, void * propvalue, int proptype, int parttype, char * bitmap) +{ + int x1, x2, i, dy = 1; + x1 = x2 = x; + while (x1>=CELL) + { + if ((pmap[y][x1-1]&0xFF)!=parttype || bitmap[(y*XRES)+x1-1]) + { + break; + } + x1--; + } + while (x2>8; + if(proptype==2){ + *((float*)(((char*)&parts[i])+propoffset)) = *((float*)propvalue); + } else if(proptype==0) { + *((int*)(((char*)&parts[i])+propoffset)) = *((int*)propvalue); + } else if(proptype==1) { + *((char*)(((char*)&parts[i])+propoffset)) = *((char*)propvalue); + } + bitmap[(y*XRES)+x] = 1; + } + if (y>=CELL+dy) + for (x=x1; x<=x2; x++) + if ((pmap[y-dy][x]&0xFF)==parttype && !bitmap[((y-dy)*XRES)+x]) + if (!flood_prop_2(x, y-dy, propoffset, propvalue, proptype, parttype, bitmap)) + return 0; + if (y=CELL) + { + if ((pmap[y][x1-1]&0xFF)!=cm || bmap[y/CELL][(x1-1)/CELL]!=bm) + { + break; + } + x1--; + } + while (x2=CELL+dy && x1==x2 && + ((pmap[y-1][x1-1]&0xFF)==PT_INST||(pmap[y-1][x1-1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1]&0xFF)==PT_INST||(pmap[y-1][x1]&0xFF)==PT_SPRK) && ((pmap[y-1][x1+1]&0xFF)==PT_INST || (pmap[y-1][x1+1]&0xFF)==PT_SPRK) && + (pmap[y-2][x1-1]&0xFF)!=PT_INST && ((pmap[y-2][x1]&0xFF)==PT_INST ||(pmap[y-2][x1]&0xFF)==PT_SPRK) && (pmap[y-2][x1+1]&0xFF)!=PT_INST) + flood_parts(x1, y-2, fullc, cm, bm, flags); + else if (y>=CELL+dy) + for (x=x1; x<=x2; x++) + if ((pmap[y-1][x]&0xFF)!=PT_SPRK) + { + if (x==x1 || x==x2 || y>=YRES-CELL-1 || + (pmap[y-1][x-1]&0xFF)==PT_INST || (pmap[y-1][x+1]&0xFF)==PT_INST || + (pmap[y+1][x-1]&0xFF)==PT_INST || ((pmap[y+1][x]&0xFF)!=PT_INST&&(pmap[y+1][x]&0xFF)!=PT_SPRK) || (pmap[y+1][x+1]&0xFF)==PT_INST) + flood_parts(x, y-dy, fullc, cm, bm, flags); + + } + + if (y=CELL+dy) + for (x=x1; x<=x2; x++) + if ((pmap[y-dy][x]&0xFF)==cm && bmap[(y-dy)/CELL][x/CELL]==bm) + if (!flood_parts(x, y-dy, fullc, cm, bm, flags)) + return 0; + if (y=CELL) + { + if ((ptypes[(pmap[y][x1-1]&0xFF)].falldown)!=2) + { + break; + } + x1--; + } + while (x2>8].tmp2 = !check;//flag it as checked, maybe shouldn't use .tmp2 + //check above, maybe around other sides too? + if ( ((y-1) > originaly) && !pmap[y-1][x] && eval_move(parts[i].type, x, y-1, NULL)) + { + int oldx = (int)(parts[i].x + 0.5f); + int oldy = (int)(parts[i].y + 0.5f); + pmap[y-1][x] = pmap[oldy][oldx]; + pmap[oldy][oldx] = 0; + parts[i].x = x; + parts[i].y = y-1; + return 0; + } + } + // fill children + + if (y>=CELL+1) + for (x=x1; x<=x2; x++) + if ((ptypes[(pmap[y-1][x]&0xFF)].falldown)==2 && parts[pmap[y-1][x]>>8].tmp2 == check) + if (!flood_water(x, y-1, i, originaly, check)) + return 0; + if (y>8].tmp2 == check) + if (!flood_water(x, y+1, i, originaly, check)) + return 0; + return 1; +} + +//wrapper around create_part to create TESC with correct tmp value +int Simulation::create_part_add_props(int p, int x, int y, int tv, int rx, int ry) +{ + p=create_part(p, x, y, tv); + if (tv==PT_TESC) + { + parts[p].tmp=rx*4+ry*4+7; + if (parts[p].tmp>300) + parts[p].tmp=300; + } + return p; +} + +//this creates particles from a brush, don't use if you want to create one particle +int Simulation::create_parts(int x, int y, int rx, int ry, int c, int flags) +{ + int i, j, r, f = 0, u, v, oy, ox, b = 0, dw = 0, stemp = 0, p;//n; + + int wall = c - 100; + if (c==SPC_WIND || c==PT_FIGH) + return 0; + + //if(c==SPC_PROP){ + // prop_edit_ui(vid_buf, x, y); + // return 0; + //} + for (r=UI_ACTUALSTART; r<=UI_ACTUALSTART+UI_WALLCOUNT; r++) + { + if (wall==r) + { + if (c == SPC_AIR || c == SPC_HEAT || c == SPC_COOL || c == SPC_VACUUM || c == SPC_PGRV || c == SPC_NGRV || wall == WL_SIGN) + break; + if (wall == WL_ERASE) + b = 0; + else + b = wall; + dw = 1; + } + } + if (c == WL_FANHELPER) + { + b = WL_FANHELPER; + dw = 1; + } + if (wall == WL_GRAV) + { + gravwl_timeout = 60; + } + if (c==PT_LIGH) + { + if (lighting_recreate>0 && rx+ry>0) + return 0; + p=create_part(-2, x, y, c); + if (p!=-1) + { + parts[p].life=rx+ry; + if (parts[p].life>55) + parts[p].life=55; + parts[p].temp=parts[p].life*150; // temperature of the lighting shows the power of the lighting + lighting_recreate+=parts[p].life/2+1; + return 1; + } + else return 0; + } + + if (dw==1) + { + ry = ry/CELL; + rx = rx/CELL; + x = x/CELL; + y = y/CELL; + x -= rx/2; + y -= ry/2; + for (ox=x; ox<=x+rx; ox++) + { + for (oy=y; oy<=y+rx; oy++) + { + if (ox>=0&&ox=0&&oy=0 && i+u=0 && j+v=XRES || y+j>=YRES) + continue; + //if (!REPLACE_MODE) + create_part(-2, x+i, y+j, c); + /*else if ((pmap[y+j][x+i]&0xFF)==SLALT&&SLALT!=0) + create_part(-2, x+i, y+j, c);*/ + } + return 1; + } + + /*if (flags&BRUSH_REPLACEMODE) + { + if (rx==0&&ry==0) + { + if ((pmap[y][x]&0xFF)==SLALT || SLALT==0) + { + if ((pmap[y][x])) + { + delete_part(x, y, 0); + if (c!=0) + create_part_add_props(-2, x, y, c, rx, ry); + } + } + } + else + for (j=-ry; j<=ry; j++) + for (i=-rx; i<=rx; i++) + if (InCurrentBrush(i ,j ,rx ,ry)) + { + if ( x+i<0 || y+j<0 || x+i>=XRES || y+j>=YRES) + continue; + if ((pmap[y+j][x+i]&0xFF)!=SLALT&&SLALT!=0) + continue; + if ((pmap[y+j][x+i])) + { + delete_part(x+i, y+j, 0); + if (c!=0) + create_part_add_props(-2, x+i, y+j, c, rx, ry); + } + } + return 1; + + }*/ + //else, no special modes, draw element like normal. + if (rx==0&&ry==0)//workaround for 1pixel brush/floodfill crashing. todo: find a better fix later. + { + if (create_part_add_props(-2, x, y, c, rx, ry)==-1) + f = 1; + } + else + for (j=-ry; j<=ry; j++) + for (i=-rx; i<=rx; i++) + //if (InCurrentBrush(i ,j ,rx ,ry)) + if (create_part_add_props(-2, x+i, y+j, c, rx, ry)==-1) + f = 1; + return !f; +} +/*int Simulation::InCurrentBrush(int i, int j, int rx, int ry) +{ + switch(CURRENT_BRUSH) + { + case CIRCLE_BRUSH: + return (pow(i,2)*pow(ry,2)+pow(j,2)*pow(rx,2)<=pow(rx,2)*pow(ry,2)); + break; + case SQUARE_BRUSH: + return (i*j<=ry*rx); + break; + case TRI_BRUSH: + return (j <= ry ) && ( j >= (((-2.0*ry)/rx)*i) -ry) && ( j >= (((-2.0*ry)/(-rx))*i)-ry ) ; + break; + } + return 0; +} +int Simulation::get_brush_flags() +{ + int flags = 0; + if (REPLACE_MODE) + flags |= BRUSH_REPLACEMODE; + if (sdl_mod & KMOD_CAPS) + flags |= BRUSH_SPECIFIC_DELETE; + if ((sdl_mod & KMOD_LALT) && (sdl_mod & (KMOD_CTRL))) + flags |= BRUSH_SPECIFIC_DELETE; + return flags; +}*/ +void Simulation::create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flags) +{ + int cp=abs(y2-y1)>abs(x2-x1), x, y, dx, dy, sy; + float e, de; + if (c==SPC_PROP) + return; + if (cp) + { + y = x1; + x1 = y1; + y1 = y; + y = x2; + x2 = y2; + y2 = y; + } + if (x1 > x2) + { + y = x1; + x1 = x2; + x2 = y; + y = y1; + y1 = y2; + y2 = y; + } + dx = x2 - x1; + dy = abs(y2 - y1); + e = 0.0f; + if (dx) + de = dy/(float)dx; + else + de = 0.0f; + y = y1; + sy = (y1= 0.5f) + { + y += sy; + if ((c==WL_EHOLE+100 || c==WL_ALLOWGAS+100 || c==WL_ALLOWENERGY+100 || c==WL_ALLOWALLELEC+100 || c==WL_ALLOWSOLID+100 || c==WL_ALLOWAIR+100 || c==WL_WALL+100 || c==WL_DESTROYALL+100 || c==WL_ALLOWLIQUID+100 || c==WL_FAN+100 || c==WL_STREAM+100 || c==WL_DETECT+100 || c==WL_EWALL+100 || c==WL_WALLELEC+100 || !(rx+ry)) + && ((y1=y2))) + { + if (cp) + create_parts(y, x, rx, ry, c, flags); + else + create_parts(x, y, rx, ry, c, flags); + } + e -= 1.0f; + } + } +} + +void *Simulation::transform_save(void *odata, int *size, matrix2d transform, vector2d translate) +{ + void *ndata; + unsigned char (*bmapo)[XRES/CELL] = (unsigned char (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(unsigned char)); + unsigned char (*bmapn)[XRES/CELL] = (unsigned char (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(unsigned char)); + Particle *partst = (Particle *)calloc(sizeof(Particle), NPART); + sign *signst = (sign *)calloc(MAXSIGNS, sizeof(sign)); + unsigned (*pmapt)[XRES] = (unsigned (*)[XRES])calloc(YRES*XRES, sizeof(unsigned)); + float (*fvxo)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*fvyo)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*fvxn)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + float (*fvyn)[XRES/CELL] = (float (*)[XRES/CELL])calloc((YRES/CELL)*(XRES/CELL), sizeof(float)); + int i, x, y, nx, ny, w, h, nw, nh; + vector2d pos, tmp, ctl, cbr; + vector2d cornerso[4]; + unsigned char *odatac = (unsigned char *)odata; + //*if (parse_save(odata, *size, 0, 0, 0, bmapo, fvxo, fvyo, signst, partst, pmapt)) TODO: IMPLEMENT + { + free(bmapo); + free(bmapn); + free(partst); + free(signst); + free(pmapt); + free(fvxo); + free(fvyo); + free(fvxn); + free(fvyn); + return odata; + } + w = odatac[6]*CELL; + h = odatac[7]*CELL; + // undo any translation caused by rotation + cornerso[0] = v2d_new(0,0); + cornerso[1] = v2d_new(w-1,0); + cornerso[2] = v2d_new(0,h-1); + cornerso[3] = v2d_new(w-1,h-1); + for (i=0; i<4; i++) + { + tmp = m2d_multiply_v2d(transform,cornerso[i]); + if (i==0) ctl = cbr = tmp; // top left, bottom right corner + if (tmp.xcbr.x) cbr.x = tmp.x; + if (tmp.y>cbr.y) cbr.y = tmp.y; + } + // casting as int doesn't quite do what we want with negative numbers, so use floor() + tmp = v2d_new(floor(ctl.x+0.5f),floor(ctl.y+0.5f)); + translate = v2d_sub(translate,tmp); + nw = floor(cbr.x+0.5f)-floor(ctl.x+0.5f)+1; + nh = floor(cbr.y+0.5f)-floor(ctl.y+0.5f)+1; + if (nw>XRES) nw = XRES; + if (nh>YRES) nh = YRES; + // rotate and translate signs, parts, walls + for (i=0; i=nw || ny<0 || ny>=nh) + { + signst[i].text[0] = 0; + continue; + } + signst[i].x = nx; + signst[i].y = ny; + } + for (i=0; i=nw || ny<0 || ny>=nh) + { + partst[i].type = PT_NONE; + continue; + } + partst[i].x = nx; + partst[i].y = ny; + } + for (y=0; y=nw || ny<0 || ny>=nh) + continue; + if (bmapo[y][x]) + { + bmapn[ny][nx] = bmapo[y][x]; + if (bmapo[y][x]==WL_FAN) + { + fvxn[ny][nx] = fvxo[y][x]; + fvyn[ny][nx] = fvyo[y][x]; + } + } + } + //ndata = build_save(size,0,0,nw,nh,bmapn,fvxn,fvyn,signst,partst); TODO: IMPLEMENT + free(bmapo); + free(bmapn); + free(partst); + free(signst); + free(pmapt); + free(fvxo); + free(fvyo); + free(fvxn); + free(fvyn); + return ndata; +} + +void Simulation::orbitalparts_get(int block1, int block2, int resblock1[], int resblock2[]) +{ + resblock1[0] = (block1&0x000000FF); + resblock1[1] = (block1&0x0000FF00)>>8; + resblock1[2] = (block1&0x00FF0000)>>16; + resblock1[3] = (block1&0xFF000000)>>24; + + resblock2[0] = (block2&0x000000FF); + resblock2[1] = (block2&0x0000FF00)>>8; + resblock2[2] = (block2&0x00FF0000)>>16; + resblock2[3] = (block2&0xFF000000)>>24; +} + +void Simulation::orbitalparts_set(int *block1, int *block2, int resblock1[], int resblock2[]) +{ + int block1tmp = 0; + int block2tmp = 0; + + block1tmp = (resblock1[0]&0xFF); + block1tmp |= (resblock1[1]&0xFF)<<8; + block1tmp |= (resblock1[2]&0xFF)<<16; + block1tmp |= (resblock1[3]&0xFF)<<24; + + block2tmp = (resblock2[0]&0xFF); + block2tmp |= (resblock2[1]&0xFF)<<8; + block2tmp |= (resblock2[2]&0xFF)<<16; + block2tmp |= (resblock2[3]&0xFF)<<24; + + *block1 = block1tmp; + *block2 = block2tmp; +} + +inline int Simulation::is_wire(int x, int y) +{ + return bmap[y][x]==WL_DETECT || bmap[y][x]==WL_EWALL || bmap[y][x]==WL_ALLOWLIQUID || bmap[y][x]==WL_WALLELEC || bmap[y][x]==WL_ALLOWALLELEC || bmap[y][x]==WL_EHOLE; +} + +inline int Simulation::is_wire_off(int x, int y) +{ + return (bmap[y][x]==WL_DETECT || bmap[y][x]==WL_EWALL || bmap[y][x]==WL_ALLOWLIQUID || bmap[y][x]==WL_WALLELEC || bmap[y][x]==WL_ALLOWALLELEC || bmap[y][x]==WL_EHOLE) && emap[y][x]<8; +} + +int Simulation::get_wavelength_bin(int *wm) +{ + int i, w0=30, wM=0; + + if (!*wm) + return -1; + + for (i=0; i<30; i++) + if (*wm & (1< wM) + wM = i; + } + + if (wM-w0 < 5) + return (wM+w0)/2; + + i = rand() % (wM-w0-3); + i += w0; + + *wm &= 0x1F << i; + return i + 2; +} + +void Simulation::set_emap(int x, int y) +{ + int x1, x2; + + if (!is_wire_off(x, y)) + return; + + // go left as far as possible + x1 = x2 = x; + while (x1>0) + { + if (!is_wire_off(x1-1, y)) + break; + x1--; + } + while (x21 && x1==x2 && + is_wire(x1-1, y-1) && is_wire(x1, y-1) && is_wire(x1+1, y-1) && + !is_wire(x1-1, y-2) && is_wire(x1, y-2) && !is_wire(x1+1, y-2)) + set_emap(x1, y-2); + else if (y>0) + for (x=x1; x<=x2; x++) + if (is_wire_off(x, y-1)) + { + if (x==x1 || x==x2 || y>=YRES/CELL-1 || + is_wire(x-1, y-1) || is_wire(x+1, y-1) || + is_wire(x-1, y+1) || !is_wire(x, y+1) || is_wire(x+1, y+1)) + set_emap(x, y-1); + } + + if (y>8].type; + else + return PT_NONE; + } + else + { + int pmr2 = pmap[(int)((parts[ci].y + parts[ni].y)/2+0.5f)][(int)((parts[ci].x + parts[ni].x)/2+0.5f)];//seems to be more accurate. + if (pmr2) + { + if (parts[pmr2>>8].type==t) + return t; + } + else + return PT_NONE; + } + return PT_NONE; +} + + +int Simulation::nearest_part(int ci, int t, int max_d) +{ + int distance = (max_d!=-1)?max_d:MAX_DISTANCE; + int ndistance = 0; + int id = -1; + int i = 0; + int cx = (int)parts[ci].x; + int cy = (int)parts[ci].y; + for (i=0; i<=parts_lastActiveIndex; i++) + { + if ((parts[i].type==t||(t==-1&&parts[i].type))&&!parts[i].life&&i!=ci) + { + ndistance = abs(cx-parts[i].x)+abs(cy-parts[i].y);// Faster but less accurate Older: sqrt(pow(cx-parts[i].x, 2)+pow(cy-parts[i].y, 2)); + if (ndistance=XRES || ny>=YRES) + return 0; + + r = pmap[ny][nx]; + if (r) + r = (r&~0xFF) | parts[r>>8].type; + if (rr) + *rr = r; + if (pt>=PT_NUM || (r&0xFF)>=PT_NUM) + return 0; + result = can_move[pt][r&0xFF]; + if (result==3) + { + if ((pt==PT_PHOT || pt==PT_ELEC) && (r&0xFF)==PT_LCRY) + result = (parts[r>>8].life > 5)? 2 : 0; + if ((r&0xFF)==PT_INVIS) + { + if (pv[ny/CELL][nx/CELL]>4.0f || pv[ny/CELL][nx/CELL]<-4.0f) result = 2; + else result = 0; + } + if ((r&0xFF)==PT_PVOD) + { + if (parts[r>>8].life == 10) result = 1; + else result = 0; + } + } + if (bmap[ny/CELL][nx/CELL]) + { + if (bmap[ny/CELL][nx/CELL]==WL_ALLOWGAS && !(ptypes[pt].properties&TYPE_GAS))// && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE) + return 0; + if (bmap[ny/CELL][nx/CELL]==WL_ALLOWENERGY && !(ptypes[pt].properties&TYPE_ENERGY))// && ptypes[pt].falldown!=0 && pt!=PT_FIRE && pt!=PT_SMKE) + return 0; + if (bmap[ny/CELL][nx/CELL]==WL_ALLOWLIQUID && ptypes[pt].falldown!=2) + return 0; + if (bmap[ny/CELL][nx/CELL]==WL_ALLOWSOLID && ptypes[pt].falldown!=1) + return 0; + if (bmap[ny/CELL][nx/CELL]==WL_ALLOWAIR || bmap[ny/CELL][nx/CELL]==WL_WALL || bmap[ny/CELL][nx/CELL]==WL_WALLELEC) + return 0; + if (bmap[ny/CELL][nx/CELL]==WL_EWALL && !emap[ny/CELL][nx/CELL]) + return 0; + if (bmap[ny/CELL][nx/CELL]==WL_EHOLE && !emap[ny/CELL][nx/CELL]) + return 2; + } + return result; +} + +int Simulation::try_move(int i, int x, int y, int nx, int ny) +{ + unsigned r, e; + + if (x==nx && y==ny) + return 1; + if (nx<0 || ny<0 || nx>=XRES || ny>=YRES) + return 1; + + e = eval_move(parts[i].type, nx, ny, &r); + + if ((r&0xFF)==PT_BOMB && parts[i].type==PT_BOMB && parts[i].tmp == 1) + e = 2; + + /* half-silvered mirror */ + if (!e && parts[i].type==PT_PHOT && + (((r&0xFF)==PT_BMTL && rand()>8].temp = parts[i].temp; + + if ((r & 0xFF) < PT_NUM && ptypes[r&0xFF].hconduct && ((r&0xFF)!=PT_HSWC||parts[r>>8].life==10) && (r&0xFF)!=PT_FILT) + parts[i].temp = parts[r>>8].temp = restrict_flt((parts[r>>8].temp+parts[i].temp)/2, MIN_TEMP, MAX_TEMP); + } + if ((parts[i].type==PT_NEUT || parts[i].type==PT_ELEC) && ((r&0xFF)==PT_CLNE || (r&0xFF)==PT_PCLN || (r&0xFF)==PT_BCLN || (r&0xFF)==PT_PBCN)) { + if (!parts[r>>8].ctype) + parts[r>>8].ctype = parts[i].type; + } + if ((r&0xFF)==PT_PRTI && (parts[i].type==PT_PHOT || parts[i].type==PT_NEUT || parts[i].type==PT_ELEC)) + { + int nnx, count; + for (count=0; count<8; count++) + { + if (isign(x-nx)==isign(portal_rx[count]) && isign(y-ny)==isign(portal_ry[count])) + break; + } + count = count%8; + parts[r>>8].tmp = (int)((parts[r>>8].temp-73.15f)/100+1); + if (parts[r>>8].tmp>=CHANNELS) parts[r>>8].tmp = CHANNELS-1; + else if (parts[r>>8].tmp<0) parts[r>>8].tmp = 0; + for ( nnx=0; nnx<80; nnx++) + if (!portalp[parts[r>>8].tmp][count][nnx].type) + { + portalp[parts[r>>8].tmp][count][nnx] = parts[i]; + parts[i].type=PT_NONE; + break; + } + } + return 0; + } + + if (e == 2) //if occupy same space + { + if (parts[i].type == PT_PHOT && (r&0xFF)==PT_GLOW && !parts[r>>8].life) + if (rand() < RAND_MAX/30) + { + parts[r>>8].life = 120; + create_gain_photon(i); + } + if (parts[i].type == PT_PHOT && (r&0xFF)==PT_FILT) + { + int temp_bin = (int)((parts[r>>8].temp-273.0f)*0.025f); + if (temp_bin < 0) temp_bin = 0; + if (temp_bin > 25) temp_bin = 25; + if(!parts[r>>8].tmp){ + parts[i].ctype = 0x1F << temp_bin; //Assign Colour + } else if(parts[r>>8].tmp==1){ + parts[i].ctype &= 0x1F << temp_bin; //Filter Colour + } else if(parts[r>>8].tmp==2){ + parts[i].ctype |= 0x1F << temp_bin; //Add Colour + } else if(parts[r>>8].tmp==3){ + parts[i].ctype &= ~(0x1F << temp_bin); //Subtract Colour + } + } + if (parts[i].type == PT_NEUT && (r&0xFF)==PT_GLAS) { + if (rand() < RAND_MAX/10) + create_cherenkov_photon(i); + } + if (parts[i].type == PT_PHOT && (r&0xFF)==PT_INVIS && pv[ny/CELL][nx/CELL]<=4.0f && pv[ny/CELL][nx/CELL]>=-4.0f) { + part_change_type(i,x,y,PT_NEUT); + parts[i].ctype = 0; + } + if ((parts[i].type==PT_BIZR||parts[i].type==PT_BIZRG) && (r&0xFF)==PT_FILT) + { + int temp_bin = (int)((parts[r>>8].temp-273.0f)*0.025f); + if (temp_bin < 0) temp_bin = 0; + if (temp_bin > 25) temp_bin = 25; + parts[i].ctype = 0x1F << temp_bin; + } + return 1; + } + //else e=1 , we are trying to swap the particles, return 0 no swap/move, 1 is still overlap/move, because the swap takes place later + + if ((r&0xFF)==PT_VOID || (r&0xFF)==PT_PVOD) //this is where void eats particles + { + if (parts[i].type == PT_STKM) + { + player.spwn = 0; + } + if (parts[i].type == PT_STKM2) + { + player2.spwn = 0; + } + if (parts[i].type == PT_FIGH) + { + fighters[(unsigned char)parts[i].tmp].spwn = 0; + fighcount--; + } + parts[i].type=PT_NONE; + return 0; + } + if ((r&0xFF)==PT_BHOL || (r&0xFF)==PT_NBHL) //this is where blackhole eats particles + { + if (parts[i].type == PT_STKM) + { + player.spwn = 0; + } + if (parts[i].type == PT_STKM2) + { + player2.spwn = 0; + } + if (parts[i].type == PT_FIGH) + { + fighters[(unsigned char)parts[i].tmp].spwn = 0; + fighcount--; + } + parts[i].type=PT_NONE; + if (!legacy_enable) + { + parts[r>>8].temp = restrict_flt(parts[r>>8].temp+parts[i].temp/2, MIN_TEMP, MAX_TEMP);//3.0f; + } + + return 0; + } + if (((r&0xFF)==PT_WHOL||(r&0xFF)==PT_NWHL) && parts[i].type==PT_ANAR) //whitehole eats anar + { + parts[i].type=PT_NONE; + if (!legacy_enable) + { + parts[r>>8].temp = restrict_flt(parts[r>>8].temp- (MAX_TEMP-parts[i].temp)/2, MIN_TEMP, MAX_TEMP); + } + + return 0; + } + + if (parts[i].type==PT_CNCT && y0) + return 0; + + e = r >> 8; //e is now the particle number at r (pmap[ny][nx]) + if (r)//the swap part, if we make it this far, swap + { + if (parts[i].type==PT_NEUT) { + // target material is NEUTPENETRATE, meaning it gets moved around when neutron passes + unsigned s = pmap[y][x]; + if (!(ptypes[s&0xFF].properties&PROP_NEUTPENETRATE)) + return 1; // if the element currently underneath neutron isn't NEUTPENETRATE, don't move anything except the neutron + // if nothing is currently underneath neutron, only move target particle + if (s) + { + pmap[ny][nx] = (s&~(0xFF))|parts[s>>8].type; + parts[s>>8].x = nx; + parts[s>>8].y = ny; + } + else pmap[ny][nx] = 0; + parts[e].x = x; + parts[e].y = y; + pmap[y][x] = (e<<8)|parts[e].type; + return 1; + } + + if ((pmap[ny][nx]>>8)==e) pmap[ny][nx] = 0; + parts[e].x += x-nx; + parts[e].y += y-ny; + pmap[(int)(parts[e].y+0.5f)][(int)(parts[e].x+0.5f)] = (e<<8)|parts[e].type; + } + return 1; +} + +// try to move particle, and if successful update pmap and parts[i].x,y +int Simulation::do_move(int i, int x, int y, float nxf, float nyf) +{ + int nx = (int)(nxf+0.5f), ny = (int)(nyf+0.5f); + int result = try_move(i, x, y, nx, ny); + if (result) + { + int t = parts[i].type; + parts[i].x = nxf; + parts[i].y = nyf; + if (ny!=y || nx!=x) + { + if ((pmap[y][x]>>8)==i) pmap[y][x] = 0; + else if ((photons[y][x]>>8)==i) photons[y][x] = 0; + if (nx=XRES-CELL || ny=YRES-CELL)//kill_part if particle is out of bounds + { + kill_part(i); + return -1; + } + if (t==PT_PHOT||t==PT_NEUT||t==PT_ELEC) + photons[ny][nx] = t|(i<<8); + else if (t) + pmap[ny][nx] = t|(i<<8); + } + } + return result; +} + +int Simulation::pn_junction_sprk(int x, int y, int pt) +{ + unsigned r = pmap[y][x]; + if ((r & 0xFF) != pt) + return 0; + r >>= 8; + if (parts[r].type != pt) + return 0; + if (parts[r].life != 0) + return 0; + + parts[r].ctype = pt; + part_change_type(r,x,y,PT_SPRK); + parts[r].life = 4; + return 1; +} + +void Simulation::photoelectric_effect(int nx, int ny)//create sparks from PHOT when hitting PSCN and NSCN +{ + unsigned r = pmap[ny][nx]; + + if ((r&0xFF) == PT_PSCN) { + if ((pmap[ny][nx-1] & 0xFF) == PT_NSCN || + (pmap[ny][nx+1] & 0xFF) == PT_NSCN || + (pmap[ny-1][nx] & 0xFF) == PT_NSCN || + (pmap[ny+1][nx] & 0xFF) == PT_NSCN) + pn_junction_sprk(nx, ny, PT_PSCN); + } +} + +unsigned Simulation::direction_to_map(float dx, float dy, int t) +{ + // TODO: + // Adding extra directions causes some inaccuracies. + // Not adding them causes problems with some diagonal surfaces (photons absorbed instead of reflected). + // For now, don't add them. + // Solution may involve more intelligent setting of initial i0 value in find_next_boundary? + // or rewriting normal/boundary finding code + + return (dx >= 0) | + (((dx + dy) >= 0) << 1) | /* 567 */ + ((dy >= 0) << 2) | /* 4+0 */ + (((dy - dx) >= 0) << 3) | /* 321 */ + ((dx <= 0) << 4) | + (((dx + dy) <= 0) << 5) | + ((dy <= 0) << 6) | + (((dy - dx) <= 0) << 7); + /* + return (dx >= -0.001) | + (((dx + dy) >= -0.001) << 1) | // 567 + ((dy >= -0.001) << 2) | // 4+0 + (((dy - dx) >= -0.001) << 3) | // 321 + ((dx <= 0.001) << 4) | + (((dx + dy) <= 0.001) << 5) | + ((dy <= 0.001) << 6) | + (((dy - dx) <= 0.001) << 7); + }*/ +} + +int Simulation::is_blocking(int t, int x, int y) +{ + if (t & REFRACT) { + if (x<0 || y<0 || x>=XRES || y>=YRES) + return 0; + if ((pmap[y][x] & 0xFF) == PT_GLAS) + return 1; + return 0; + } + + return !eval_move(t, x, y, NULL); +} + +int Simulation::is_boundary(int pt, int x, int y) +{ + if (!is_blocking(pt,x,y)) + return 0; + if (is_blocking(pt,x,y-1) && is_blocking(pt,x,y+1) && is_blocking(pt,x-1,y) && is_blocking(pt,x+1,y)) + return 0; + return 1; +} + +int Simulation::find_next_boundary(int pt, int *x, int *y, int dm, int *em) +{ + static int dx[8] = {1,1,0,-1,-1,-1,0,1}; + static int dy[8] = {0,1,1,1,0,-1,-1,-1}; + static int de[8] = {0x83,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC1}; + int i, ii, i0; + + if (*x <= 0 || *x >= XRES-1 || *y <= 0 || *y >= YRES-1) + return 0; + + if (*em != -1) { + i0 = *em; + dm &= de[i0]; + } else + i0 = 0; + + for (ii=0; ii<8; ii++) { + i = (ii + i0) & 7; + if ((dm & (1 << i)) && is_boundary(pt, *x+dx[i], *y+dy[i])) { + *x += dx[i]; + *y += dy[i]; + *em = i; + return 1; + } + } + + return 0; +} + +int Simulation::get_normal(int pt, int x, int y, float dx, float dy, float *nx, float *ny) +{ + int ldm, rdm, lm, rm; + int lx, ly, lv, rx, ry, rv; + int i, j; + float r, ex, ey; + + if (!dx && !dy) + return 0; + + if (!is_boundary(pt, x, y)) + return 0; + + ldm = direction_to_map(-dy, dx, pt); + rdm = direction_to_map(dy, -dx, pt); + lx = rx = x; + ly = ry = y; + lv = rv = 1; + lm = rm = -1; + + j = 0; + for (i=0; i= NORMAL_INTERP) + return 0; + + if (pt == PT_PHOT) + photoelectric_effect(x, y); + + return get_normal(pt, x, y, dx, dy, nx, ny); +} + +//For soap only +void Simulation::detach(int i) +{ + if ((parts[i].ctype&2) == 2) + { + if ((parts[parts[i].tmp].ctype&4) == 4) + parts[parts[i].tmp].ctype ^= 4; + } + + if ((parts[i].ctype&4) == 4) + { + if ((parts[parts[i].tmp2].ctype&2) == 2) + parts[parts[i].tmp2].ctype ^= 2; + } + + parts[i].ctype = 0; +} + +void Simulation::kill_part(int i)//kills particle number i +{ + int x, y; + + if(elementCount[parts[i].type] && parts[i].type) + elementCount[parts[i].type]--; + x = (int)(parts[i].x+0.5f); + y = (int)(parts[i].y+0.5f); + if (parts[i].type == PT_STKM) + { + player.spwn = 0; + } + if (parts[i].type == PT_STKM2) + { + player2.spwn = 0; + } + if (parts[i].type == PT_FIGH) + { + fighters[(unsigned char)parts[i].tmp].spwn = 0; + fighcount--; + } + if (parts[i].type == PT_SOAP) + { + detach(i); + } + if (x>=0 && y>=0 && x>8)==i) + pmap[y][x] = 0; + else if ((photons[y][x]>>8)==i) + photons[y][x] = 0; + } + + parts[i].type = PT_NONE; + parts[i].life = pfree; + pfree = i; +} + +void Simulation::part_change_type(int i, int x, int y, int t)//changes the type of particle number i, to t. This also changes pmap at the same time. +{ + if (x<0 || y<0 || x>=XRES || y>=YRES || i>=NPART || t<0 || t>=PT_NUM) + return; + if (!ptypes[t].enabled) + t = PT_NONE; + + if (parts[i].type == PT_STKM) + player.spwn = 0; + + if (parts[i].type == PT_STKM2) + player2.spwn = 0; + + if (parts[i].type == PT_FIGH) + { + fighters[(unsigned char)parts[i].tmp].spwn = 0; + fighcount--; + } + + parts[i].type = t; + if (t==PT_PHOT || t==PT_NEUT || t==PT_ELEC) + { + photons[y][x] = t|(i<<8); + if ((pmap[y][x]>>8)==i) + pmap[y][x] = 0; + } + else + { + pmap[y][x] = t|(i<<8); + if ((photons[y][x]>>8)==i) + photons[y][x] = 0; + } +} + +int Simulation::create_part(int p, int x, int y, int tv)//the function for creating a particle, use p=-1 for creating a new particle, -2 is from a brush, or a particle number to replace a particle. +{ + int i; + + int t = tv & 0xFF; + int v = (tv >> 8) & 0xFF; + + if (x<0 || y<0 || x>=XRES || y>=YRES || ((t<0 || t>=PT_NUM)&&t!=SPC_HEAT&&t!=SPC_COOL&&t!=SPC_AIR&&t!=SPC_VACUUM&&t!=SPC_PGRV&&t!=SPC_NGRV)) + return -1; + if (t>=0 && t>8].temp>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp + 0.1f, MIN_TEMP, MAX_TEMP); + } else if ((sdl_mod & (KMOD_SHIFT)) && (sdl_mod & (KMOD_CTRL))) { + parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp + 50.0f, MIN_TEMP, MAX_TEMP); + } else { + parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp + 4.0f, MIN_TEMP, MAX_TEMP); + } + } + if (t==SPC_COOL&&parts[pmap[y][x]>>8].temp>MIN_TEMP) + { + if ((pmap[y][x]&0xFF)==PT_PUMP || (pmap[y][x]&0xFF)==PT_GPMP) { + parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp - 0.1f, MIN_TEMP, MAX_TEMP); + } else if ((sdl_mod & (KMOD_SHIFT)) && (sdl_mod & (KMOD_CTRL))) { + parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp - 50.0f, MIN_TEMP, MAX_TEMP); + } else { + parts[pmap[y][x]>>8].temp = restrict_flt(parts[pmap[y][x]>>8].temp - 4.0f, MIN_TEMP, MAX_TEMP); + } + } + return pmap[y][x]>>8; + } + else + { + return -1; + } + }*/ + if (t==SPC_AIR) + { + pv[y/CELL][x/CELL] += 0.03f; + if (y+CELL>8].ctype=PT_DUST; + } + if (!((pmap[y][x]&0xFF)==PT_INST||(ptypes[pmap[y][x]&0xFF].properties&PROP_CONDUCTS))) + return -1; + if (parts[pmap[y][x]>>8].life!=0) + return -1; + parts[pmap[y][x]>>8].type = PT_SPRK; + parts[pmap[y][x]>>8].life = 4; + parts[pmap[y][x]>>8].ctype = pmap[y][x]&0xFF; + pmap[y][x] = (pmap[y][x]&~0xFF) | PT_SPRK; + return pmap[y][x]>>8; + } + if (t==PT_SPAWN&&elementCount[PT_SPAWN]) + return -1; + if (t==PT_SPAWN2&&elementCount[PT_SPAWN2]) + return -1; + if (p==-1)//creating from anything but brush + { + if (pmap[y][x] || (bmap[y/CELL][x/CELL] && !eval_move(t, x, y, NULL))) + { + if ((pmap[y][x]&0xFF)!=PT_SPAWN&&(pmap[y][x]&0xFF)!=PT_SPAWN2) + { + if (t!=PT_STKM&&t!=PT_STKM2&&t!=PT_FIGH) + { + return -1; + } + } + } + if (pfree == -1) + return -1; + i = pfree; + pfree = parts[i].life; + } + else if (p==-2)//creating from brush + { + if (pmap[y][x]) + { + if (( + ((pmap[y][x]&0xFF)==PT_STOR&&!(ptypes[t].properties&TYPE_SOLID))|| + (pmap[y][x]&0xFF)==PT_CLNE|| + (pmap[y][x]&0xFF)==PT_BCLN|| + (pmap[y][x]&0xFF)==PT_CONV|| + ((pmap[y][x]&0xFF)==PT_PCLN&&t!=PT_PSCN&&t!=PT_NSCN)|| + ((pmap[y][x]&0xFF)==PT_PBCN&&t!=PT_PSCN&&t!=PT_NSCN) + )&&( + t!=PT_CLNE&&t!=PT_PCLN&& + t!=PT_BCLN&&t!=PT_STKM&& + t!=PT_STKM2&&t!=PT_PBCN&& + t!=PT_STOR&&t!=PT_FIGH) + ) + { + parts[pmap[y][x]>>8].ctype = t; + if (t==PT_LIFE && v>8].tmp = v; + } + return -1; + } + if (photons[y][x] && (t==PT_PHOT||t==PT_NEUT||t==PT_ELEC)) + return -1; + if (pfree == -1) + return -1; + i = pfree; + pfree = parts[i].life; + } + else if (p==-3)//skip pmap checks, e.g. for sing explosion + { + if (pfree == -1) + return -1; + i = pfree; + pfree = parts[i].life; + } + else + { + int oldX = (int)(parts[p].x+0.5f); + int oldY = (int)(parts[p].y+0.5f); + if ((pmap[oldY][oldX]>>8)==p) + pmap[oldY][oldX] = 0; + if ((photons[oldY][oldX]>>8)==p) + photons[oldY][oldX] = 0; + i = p; + } + + if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; + + parts[i].dcolour = 0; + if (t==PT_GLAS) + { + parts[i].pavg[1] = pv[y/CELL][x/CELL]; + } + else if (t==PT_QRTZ) + { + parts[i].pavg[1] = pv[y/CELL][x/CELL]; + } + else + { + parts[i].pavg[0] = 0.0f; + parts[i].pavg[1] = 0.0f; + } + if (t!=PT_STKM&&t!=PT_STKM2&&t!=PT_FIGH)//set everything to default values first, except for stickman. + { + parts[i].x = (float)x; + parts[i].y = (float)y; + parts[i].type = t; + parts[i].vx = 0; + parts[i].vy = 0; + parts[i].life = 0; + parts[i].ctype = 0; + parts[i].temp = ptypes[t].heat; + parts[i].tmp = 0; + parts[i].tmp2 = 0; + } + if (t==PT_LIGH && p==-2) + { + switch (gravityMode) + { + default: + case 0: + parts[i].tmp= 270+rand()%40-20; + break; + case 1: + parts[i].tmp = rand()%360; + break; + case 2: + parts[i].tmp = atan2(x-XCNTR, y-YCNTR)*(180.0f/M_PI)+90; + break; + } + parts[i].tmp2 = 4; + } + if (t==PT_SOAP) + { + parts[i].tmp = -1; + parts[i].tmp2 = -1; + } + //now set various properties that we want at spawn. + if (t==PT_ACID || t==PT_CAUS) + { + parts[i].life = 75; + } + /*Testing + if(t==PT_WOOD){ + parts[i].life = 150; + } + End Testing*/ + if (t==PT_WARP) { + parts[i].life = rand()%95+70; + } + if (t==PT_FUSE) { + parts[i].life = 50; + parts[i].tmp = 50; + } + /*if (ptypes[t].properties&PROP_LIFE) { + int r; + for (r = 0; r255 ? 255 : (colr<0 ? 0 : colr); + colg = colg>255 ? 255 : (colg<0 ? 0 : colg); + colb = colb>255 ? 255 : (colb<0 ? 0 : colb); + parts[i].dcolour = 0xFF000000 | (colr<<16) | (colg<<8) | colb; + } + elementCount[t]++; + return i; +} + +void Simulation::create_gain_photon(int pp)//photons from PHOT going through GLOW +{ + float xx, yy; + int i, lr, temp_bin, nx, ny; + + if (pfree == -1) + return; + i = pfree; + + lr = rand() % 2; + + if (lr) { + xx = parts[pp].x - 0.3*parts[pp].vy; + yy = parts[pp].y + 0.3*parts[pp].vx; + } else { + xx = parts[pp].x + 0.3*parts[pp].vy; + yy = parts[pp].y - 0.3*parts[pp].vx; + } + + nx = (int)(xx + 0.5f); + ny = (int)(yy + 0.5f); + + if (nx<0 || ny<0 || nx>=XRES || ny>=YRES) + return; + + if ((pmap[ny][nx] & 0xFF) != PT_GLOW) + return; + + pfree = parts[i].life; + if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; + + parts[i].type = PT_PHOT; + parts[i].life = 680; + parts[i].x = xx; + parts[i].y = yy; + parts[i].vx = parts[pp].vx; + parts[i].vy = parts[pp].vy; + parts[i].temp = parts[pmap[ny][nx] >> 8].temp; + parts[i].tmp = 0; + parts[i].pavg[0] = parts[i].pavg[1] = 0.0f; + photons[ny][nx] = PT_PHOT|(i<<8); + + temp_bin = (int)((parts[i].temp-273.0f)*0.25f); + if (temp_bin < 0) temp_bin = 0; + if (temp_bin > 25) temp_bin = 25; + parts[i].ctype = 0x1F << temp_bin; +} + +void Simulation::create_cherenkov_photon(int pp)//photons from NEUT going through GLAS +{ + int i, lr, nx, ny; + float r, eff_ior; + + if (pfree == -1) + return; + i = pfree; + + nx = (int)(parts[pp].x + 0.5f); + ny = (int)(parts[pp].y + 0.5f); + if ((pmap[ny][nx] & 0xFF) != PT_GLAS) + return; + + if (hypotf(parts[pp].vx, parts[pp].vy) < 1.44f) + return; + + pfree = parts[i].life; + if (i>parts_lastActiveIndex) parts_lastActiveIndex = i; + + lr = rand() % 2; + + parts[i].type = PT_PHOT; + parts[i].ctype = 0x00000F80; + parts[i].life = 680; + parts[i].x = parts[pp].x; + parts[i].y = parts[pp].y; + parts[i].temp = parts[pmap[ny][nx] >> 8].temp; + parts[i].tmp = 0; + parts[i].pavg[0] = parts[i].pavg[1] = 0.0f; + photons[ny][nx] = PT_PHOT|(i<<8); + + if (lr) { + parts[i].vx = parts[pp].vx - 2.5f*parts[pp].vy; + parts[i].vy = parts[pp].vy + 2.5f*parts[pp].vx; + } else { + parts[i].vx = parts[pp].vx + 2.5f*parts[pp].vy; + parts[i].vy = parts[pp].vy - 2.5f*parts[pp].vx; + } + + /* photons have speed of light. no discussion. */ + r = 1.269 / hypotf(parts[i].vx, parts[i].vy); + parts[i].vx *= r; + parts[i].vy *= r; +} + +void Simulation::delete_part(int x, int y, int flags)//calls kill_part with the particle located at x,y +{ + unsigned i; + + if (x<0 || y<0 || x>=XRES || y>=YRES) + return; + if (photons[y][x]) { + i = photons[y][x]; + } else { + i = pmap[y][x]; + } + + if (!i) + return; + kill_part(i>>8); +} + +void Simulation::update_particles_i(int start, int inc) +{ + int i, j, x, y, t, nx, ny, r, surround_space, s, lt, rt, nt, nnx, nny, q, golnum, goldelete, z, neighbors, createdsomething; + float mv, dx, dy, ix, iy, lx, ly, nrx, nry, dp, ctemph, ctempl, gravtot; + int fin_x, fin_y, clear_x, clear_y, stagnant; + float fin_xf, fin_yf, clear_xf, clear_yf; + float nn, ct1, ct2, swappage; + float pt = R_TEMP; + float c_heat = 0.0f; + int h_count = 0; + int starti = (start*-1); + int surround[8]; + int surround_hconduct[8]; + int lighting_ok=1; + float pGravX, pGravY, pGravD; + + if (sys_pause&&lighting_recreate>0) + { + for (i=0; i<=parts_lastActiveIndex; i++) + { + if (parts[i].type==PT_LIGH && parts[i].tmp2>0) + { + lighting_ok=0; + break; + } + } + } + + if (lighting_ok) + lighting_recreate--; + + if (lighting_recreate<0) + lighting_recreate=1; + + if (lighting_recreate>21) + lighting_recreate=21; + + if (sys_pause&&!framerender)//do nothing if paused + return; + + //wire! + if(elementCount[PT_WIRE] > 0) + { + for (nx=0; nx>8].type==PT_WIRE) + parts[r>>8].tmp=parts[r>>8].ctype; + } + } + } + //game of life! + if (elementCount[PT_LIFE]>0&&++CGOL>=GSPEED)//GSPEED is frames per generation + { + int createdsomething = 0; + CGOL=0; + ISGOL=0; + for (nx=CELL; nx>8].type==PT_LIFE/* && parts[r>>8].ctype==golnum-1*/) + { + golnum = parts[r>>8].ctype+1; + if (golnum<=0 || golnum>NGOLALT) { + parts[r>>8].type = PT_NONE; + continue; + } + if (parts[r>>8].tmp == grule[golnum][9]-1) { + gol[nx][ny] = golnum; + for ( nnx=-1; nnx<2; nnx++) + { + for ( nny=-1; nny<2; nny++)//it will count itself as its own neighbor, which is needed, but will have 1 extra for delete check + { + rt = pmap[((ny+nny+YRES-3*CELL)%(YRES-2*CELL))+CELL][((nx+nnx+XRES-3*CELL)%(XRES-2*CELL))+CELL]; + if (!rt || (rt&0xFF)==PT_LIFE) + { + gol2[((nx+nnx+XRES-3*CELL)%(XRES-2*CELL))+CELL][((ny+nny+YRES-3*CELL)%(YRES-2*CELL))+CELL][golnum] ++; + gol2[((nx+nnx+XRES-3*CELL)%(XRES-2*CELL))+CELL][((ny+nny+YRES-3*CELL)%(YRES-2*CELL))+CELL][0] ++; + } + } + } + } else { + parts[r>>8].tmp --; + if (parts[r>>8].tmp<=0) + parts[r>>8].type = PT_NONE;//using kill_part makes it not work + } + } + //} + } + } + } + for (nx=CELL; nx=2&&gol2[nx][ny][golnum]>=(goldelete%2)+goldelete/2) + { + if (create_part(-1, nx, ny, PT_LIFE|((golnum-1)<<8))) + createdsomething = 1; + } + else if (gol[nx][ny]==golnum&&(grule[golnum][goldelete-1]==0||grule[golnum][goldelete-1]==2))//subtract 1 because it counted itself + { + if (parts[r>>8].tmp==grule[golnum][9]-1) + parts[r>>8].tmp --; + } + if (r && parts[r>>8].tmp<=0) + parts[r>>8].type = PT_NONE;//using kill_part makes it not work + } + for ( z = 0; z<=NGOL; z++) + gol2[nx][ny][z] = 0;//this improves performance A LOT compared to the memset, i was getting ~23 more fps with this. + } + } + //memset(gol2, 0, sizeof(gol2)); + } + if (ISWIRE==1)//wifi channel reseting + { + for ( q = 0; q<(int)(MAX_TEMP-73.15f)/100+2; q++) + if (!wireless[q][1]) + { + wireless[q][0] = 0; + } + else + wireless[q][1] = 0; + } + //the main particle loop function, goes over all particles. + for (i=0; i<=parts_lastActiveIndex; i++) + if (parts[i].type) + { + lx = parts[i].x; + ly = parts[i].y; + t = parts[i].type; + if (t<0 || t>=PT_NUM) + { + kill_part(i); + continue; + } + //printf("parts[%d].type: %d\n", i, parts[i].type); + + if (parts[i].life>0 && (ptypes[t].properties&PROP_LIFE_DEC)) + { + // automatically decrease life + parts[i].life--; + if (parts[i].life<=0 && (ptypes[t].properties&(PROP_LIFE_KILL_DEC|PROP_LIFE_KILL))) + { + // kill on change to no life + kill_part(i); + continue; + } + } + else if (parts[i].life<=0 && (ptypes[t].properties&PROP_LIFE_KILL)) + { + // kill if no life + kill_part(i); + continue; + } + + x = (int)(parts[i].x+0.5f); + y = (int)(parts[i].y+0.5f); + + //this kills any particle out of the screen, or in a wall where it isn't supposed to go + if (x=XRES-CELL || y>=YRES-CELL || + (bmap[y/CELL][x/CELL] && + (bmap[y/CELL][x/CELL]==WL_WALL || + bmap[y/CELL][x/CELL]==WL_WALLELEC || + bmap[y/CELL][x/CELL]==WL_ALLOWAIR || + (bmap[y/CELL][x/CELL]==WL_DESTROYALL) || + (bmap[y/CELL][x/CELL]==WL_ALLOWLIQUID && ptypes[t].falldown!=2) || + (bmap[y/CELL][x/CELL]==WL_ALLOWSOLID && ptypes[t].falldown!=1) || + (bmap[y/CELL][x/CELL]==WL_ALLOWGAS && !(ptypes[t].properties&TYPE_GAS)) || //&& ptypes[t].falldown!=0 && parts[i].type!=PT_FIRE && parts[i].type!=PT_SMKE && parts[i].type!=PT_HFLM) || + (bmap[y/CELL][x/CELL]==WL_ALLOWENERGY && !(ptypes[t].properties&TYPE_ENERGY)) || + (bmap[y/CELL][x/CELL]==WL_DETECT && (t==PT_METL || t==PT_SPRK)) || + (bmap[y/CELL][x/CELL]==WL_EWALL && !emap[y/CELL][x/CELL])) && (t!=PT_STKM) && (t!=PT_STKM2) && (t!=PT_FIGH))) + { + kill_part(i); + continue; + } + if (bmap[y/CELL][x/CELL]==WL_DETECT && emap[y/CELL][x/CELL]<8) + set_emap(x/CELL, y/CELL); + + //adding to velocity from the particle's velocity + vx[y/CELL][x/CELL] = vx[y/CELL][x/CELL]*ptypes[t].airloss + ptypes[t].airdrag*parts[i].vx; + vy[y/CELL][x/CELL] = vy[y/CELL][x/CELL]*ptypes[t].airloss + ptypes[t].airdrag*parts[i].vy; + + if (t==PT_GAS||t==PT_NBLE) + { + if (pv[y/CELL][x/CELL]<3.5f) + pv[y/CELL][x/CELL] += ptypes[t].hotair*(3.5f-pv[y/CELL][x/CELL]); + if (y+CELL= 0 && y-2 < YRES && (ptypes[t].properties&TYPE_LIQUID)) {//some heat convection for liquids + r = pmap[y-2][x]; + if (!(!r || parts[i].type != (r&0xFF))) { + if (parts[i].temp>parts[r>>8].temp) { + swappage = parts[i].temp; + parts[i].temp = parts[r>>8].temp; + parts[r>>8].temp = swappage; + } + } + } + + //heat transfer code + h_count = 0; +#ifdef REALHEAT + if (t&&(t!=PT_HSWC||parts[i].life==10)) + { + float c_Cm = 0.0f; +#else + if (t&&(t!=PT_HSWC||parts[i].life==10)&&ptypes[t].hconduct>(rand()%250)) + { + float c_Cm = 0.0f; +#endif + if (aheat_enable) + { + c_heat = (hv[y/CELL][x/CELL]-parts[i].temp)*0.04; + c_heat = restrict_flt(c_heat, -MAX_TEMP+MIN_TEMP, MAX_TEMP-MIN_TEMP); + parts[i].temp += c_heat; + hv[y/CELL][x/CELL] -= c_heat; + } + c_heat = 0.0f; + for (j=0; j<8; j++) + { + surround_hconduct[j] = i; + r = surround[j]; + if (!r) + continue; + rt = r&0xFF; + if (rt&&ptypes[rt].hconduct&&(rt!=PT_HSWC||parts[r>>8].life==10) + &&(t!=PT_FILT||(rt!=PT_BRAY&&rt!=PT_BIZR&&rt!=PT_BIZRG)) + &&(rt!=PT_FILT||(t!=PT_BRAY&&t!=PT_PHOT&&t!=PT_BIZR&&t!=PT_BIZRG))) + { + surround_hconduct[j] = r>>8; +#ifdef REALHEAT + c_heat += parts[r>>8].temp*96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight); + c_Cm += 96.645/ptypes[rt].hconduct*fabs(ptypes[rt].weight); +#else + c_heat += parts[r>>8].temp; +#endif + h_count++; + } + } +#ifdef REALHEAT + if (t == PT_PHOT) + pt = (c_heat+parts[i].temp*96.645)/(c_Cm+96.645); + else + pt = (c_heat+parts[i].temp*96.645/ptypes[t].hconduct*fabs(ptypes[t].weight))/(c_Cm+96.645/ptypes[t].hconduct*fabs(ptypes[t].weight)); + +#else + pt = (c_heat+parts[i].temp)/(h_count+1); +#endif + pt = parts[i].temp = restrict_flt(pt, MIN_TEMP, MAX_TEMP); + for (j=0; j<8; j++) + { + parts[surround_hconduct[j]].temp = pt; + } + + ctemph = ctempl = pt; + // change boiling point with pressure + if ((ptypes[t].state==ST_LIQUID && ptransitions[t].tht>-1 && ptransitions[t].tht-1 && ptransitions[t].tltptransitions[t].thv&&ptransitions[t].tht>-1) { + // particle type change due to high temperature + if (ptransitions[t].tht!=PT_NUM) + t = ptransitions[t].tht; + else if (t==PT_ICEI) { + if (parts[i].ctype>0&&parts[i].ctype274.0f) t = PT_WATR; + else s = 0; + } + else if (t==PT_SLTW) { + if (1>rand()%6) t = PT_SALT; + else t = PT_WTRV; + } + else s = 0; + } else if (ctempl-1) { + // particle type change due to low temperature + if (ptransitions[t].tlt!=PT_NUM) + t = ptransitions[t].tlt; + else if (t==PT_WTRV) { + if (pt<273.0f) t = PT_RIME; + else t = PT_DSTW; + } + else if (t==PT_LAVA) { + if (parts[i].ctype>0 && parts[i].ctype=ptransitions[PT_BMTL].thv) s = 0; + else if (ptransitions[parts[i].ctype].tht==PT_LAVA) { + if (pt>=ptransitions[parts[i].ctype].thv) s = 0; + } + else if (pt>=973.0f) s = 0; // freezing point for lava with any other (not listed in ptransitions as turning into lava) ctype + if (s) { + t = parts[i].ctype; + parts[i].ctype = PT_NONE; + if (t==PT_THRM) { + parts[i].tmp = 0; + t = PT_BMTL; + } + if (t==PT_PLUT) + { + parts[i].tmp = 0; + t = PT_LAVA; + } + } + } + else if (pt<973.0f) t = PT_STNE; + else s = 0; + } + else s = 0; + } + else s = 0; + if (s) { // particle type change occurred + if (t==PT_ICEI||t==PT_LAVA) + parts[i].ctype = parts[i].type; + if (!(t==PT_ICEI&&parts[i].ctype==PT_FRZW)) parts[i].life = 0; + if (ptypes[t].state==ST_GAS&&ptypes[parts[i].type].state!=ST_GAS) + pv[y/CELL][x/CELL] += 0.50f; + part_change_type(i,x,y,t); + if (t==PT_FIRE||t==PT_PLSM||t==PT_HFLM) + parts[i].life = rand()%50+120; + if (t==PT_LAVA) { + if (parts[i].ctype==PT_BRMT) parts[i].ctype = PT_BMTL; + else if (parts[i].ctype==PT_SAND) parts[i].ctype = PT_GLAS; + else if (parts[i].ctype==PT_BGLA) parts[i].ctype = PT_GLAS; + else if (parts[i].ctype==PT_PQRT) parts[i].ctype = PT_QRTZ; + parts[i].life = rand()%120+240; + } + if (t==PT_NONE) { + kill_part(i); + goto killed; + } + } + + pt = parts[i].temp = restrict_flt(parts[i].temp, MIN_TEMP, MAX_TEMP); + if (t==PT_LAVA) { + parts[i].life = restrict_flt((parts[i].temp-700)/7, 0.0f, 400.0f); + if (parts[i].ctype==PT_THRM&&parts[i].tmp>0) + { + parts[i].tmp--; + parts[i].temp = 3500; + } + if (parts[i].ctype==PT_PLUT&&parts[i].tmp>0) + { + parts[i].tmp--; + parts[i].temp = MAX_TEMP; + } + } + } + } + + if (t==PT_LIFE) + { + parts[i].temp = restrict_flt(parts[i].temp-50.0f, MIN_TEMP, MAX_TEMP); + //ISGOL=1;//means there is a life particle on screen + } + if (t==PT_WIRE) + { + //wire_placed = 1; + } + //spark updates from walls + if ((ptypes[t].properties&PROP_CONDUCTS) || t==PT_SPRK) + { + nx = x % CELL; + if (nx == 0) + nx = x/CELL - 1; + else if (nx == CELL-1) + nx = x/CELL + 1; + else + nx = x/CELL; + ny = y % CELL; + if (ny == 0) + ny = y/CELL - 1; + else if (ny == CELL-1) + ny = y/CELL + 1; + else + ny = y/CELL; + if (nx>=0 && ny>=0 && nx2.5f) + { + parts[i].life = rand()%80+180; + parts[i].temp = restrict_flt(ptypes[PT_FIRE].heat + (ptypes[t].flammable/2), MIN_TEMP, MAX_TEMP); + t = PT_FIRE; + part_change_type(i,x,y,t); + pv[y/CELL][x/CELL] += 0.25f * CFDS; + } + + + s = 1; + gravtot = fabs(gravy[(y/CELL)*(XRES/CELL)+(x/CELL)])+fabs(gravx[(y/CELL)*(XRES/CELL)+(x/CELL)]); + if (pv[y/CELL][x/CELL]>ptransitions[t].phv&&ptransitions[t].pht>-1) { + // particle type change due to high pressure + if (ptransitions[t].pht!=PT_NUM) + t = ptransitions[t].pht; + else if (t==PT_BMTL) { + if (pv[y/CELL][x/CELL]>2.5f) + t = PT_BRMT; + else if (pv[y/CELL][x/CELL]>1.0f && parts[i].tmp==1) + t = PT_BRMT; + else s = 0; + } + else s = 0; + } else if (pv[y/CELL][x/CELL]-1) { + // particle type change due to low pressure + if (ptransitions[t].plt!=PT_NUM) + t = ptransitions[t].plt; + else s = 0; + } else if (gravtot>(ptransitions[t].phv/4.0f)&&ptransitions[t].pht>-1) { + // particle type change due to high gravity + if (ptransitions[t].pht!=PT_NUM) + t = ptransitions[t].pht; + else if (t==PT_BMTL) { + if (gravtot>0.625f) + t = PT_BRMT; + else if (gravtot>0.25f && parts[i].tmp==1) + t = PT_BRMT; + else s = 0; + } + else s = 0; + } else s = 0; + if (s) { // particle type change occurred + parts[i].life = 0; + part_change_type(i,x,y,t); + if (t==PT_FIRE) + parts[i].life = rand()%50+120; + if (t==PT_NONE) { + kill_part(i); + goto killed; + } + } + + //call the particle update function, if there is one +#ifdef LUACONSOLE + if (ptypes[t].update_func && lua_el_mode[t] != 2) +#else + if (ptypes[t].update_func) +#endif + { + if ((*(ptypes[t].update_func))(this, i,x,y,surround_space,nt, parts, pmap)) + continue; + } +#ifdef LUACONSOLE + if(lua_el_mode[t]) + { + if(luacon_part_update(t,i,x,y,surround_space,nt)) + continue; + } +#endif + if (legacy_enable)//if heat sim is off + update_legacy_all(this, i,x,y,surround_space,nt, parts, pmap); + +killed: + if (parts[i].type == PT_NONE)//if its dead, skip to next particle + continue; + + if (!parts[i].vx&&!parts[i].vy)//if its not moving, skip to next particle, movement code it next + continue; + +#if defined(WIN32) && !defined(__GNUC__) + mv = max(fabsf(parts[i].vx), fabsf(parts[i].vy)); +#else + mv = fmaxf(fabsf(parts[i].vx), fabsf(parts[i].vy)); +#endif + if (mv < ISTP) + { + clear_x = x; + clear_y = y; + clear_xf = parts[i].x; + clear_yf = parts[i].y; + fin_xf = clear_xf + parts[i].vx; + fin_yf = clear_yf + parts[i].vy; + fin_x = (int)(fin_xf+0.5f); + fin_y = (int)(fin_yf+0.5f); + } + else + { + // interpolate to see if there is anything in the way + dx = parts[i].vx*ISTP/mv; + dy = parts[i].vy*ISTP/mv; + fin_xf = parts[i].x; + fin_yf = parts[i].y; + while (1) + { + mv -= ISTP; + fin_xf += dx; + fin_yf += dy; + fin_x = (int)(fin_xf+0.5f); + fin_y = (int)(fin_yf+0.5f); + if (mv <= 0.0f) + { + // nothing found + fin_xf = parts[i].x + parts[i].vx; + fin_yf = parts[i].y + parts[i].vy; + fin_x = (int)(fin_xf+0.5f); + fin_y = (int)(fin_yf+0.5f); + clear_xf = fin_xf-dx; + clear_yf = fin_yf-dy; + clear_x = (int)(clear_xf+0.5f); + clear_y = (int)(clear_yf+0.5f); + break; + } + if (fin_x=XRES-CELL || fin_y>=YRES-CELL || pmap[fin_y][fin_x] || (bmap[fin_y/CELL][fin_x/CELL] && (bmap[fin_y/CELL][fin_x/CELL]==WL_DESTROYALL || bmap[fin_y/CELL][fin_x/CELL]==WL_DETECT || !eval_move(t,fin_x,fin_y,NULL)))) + { + // found an obstacle + clear_xf = fin_xf-dx; + clear_yf = fin_yf-dy; + clear_x = (int)(clear_xf+0.5f); + clear_y = (int)(clear_yf+0.5f); + break; + } + + } + } + + stagnant = parts[i].flags & FLAG_STAGNANT; + parts[i].flags &= ~FLAG_STAGNANT; + + if ((t==PT_PHOT||t==PT_NEUT||t==PT_ELEC)) { + if (t == PT_PHOT) { + rt = pmap[fin_y][fin_x] & 0xFF; + lt = pmap[y][x] & 0xFF; + + r = eval_move(PT_PHOT, fin_x, fin_y, NULL); + if (((rt==PT_GLAS && lt!=PT_GLAS) || (rt!=PT_GLAS && lt==PT_GLAS)) && r) { + if (!get_normal_interp(REFRACT|t, parts[i].x, parts[i].y, parts[i].vx, parts[i].vy, &nrx, &nry)) { + kill_part(i); + continue; + } + + r = get_wavelength_bin(&parts[i].ctype); + if (r == -1) { + kill_part(i); + continue; + } + nn = GLASS_IOR - GLASS_DISP*(r-15)/15.0f; + nn *= nn; + nrx = -nrx; + nry = -nry; + if (rt==PT_GLAS && lt!=PT_GLAS) + nn = 1.0f/nn; + ct1 = parts[i].vx*nrx + parts[i].vy*nry; + ct2 = 1.0f - (nn*nn)*(1.0f-(ct1*ct1)); + if (ct2 < 0.0f) { + // total internal reflection + parts[i].vx -= 2.0f*ct1*nrx; + parts[i].vy -= 2.0f*ct1*nry; + fin_xf = parts[i].x; + fin_yf = parts[i].y; + fin_x = x; + fin_y = y; + } else { + // refraction + ct2 = sqrtf(ct2); + ct2 = ct2 - nn*ct1; + parts[i].vx = nn*parts[i].vx + ct2*nrx; + parts[i].vy = nn*parts[i].vy + ct2*nry; + } + } + } + if (stagnant)//FLAG_STAGNANT set, was reflected on previous frame + { + // cast coords as int then back to float for compatibility with existing saves + if (!do_move(i, x, y, (float)fin_x, (float)fin_y)) { + kill_part(i); + continue; + } + } + else if (!do_move(i, x, y, fin_xf, fin_yf)) + { + // reflection + parts[i].flags |= FLAG_STAGNANT; + if (t==PT_NEUT && 100>(rand()%1000)) + { + kill_part(i); + continue; + } + r = pmap[fin_y][fin_x]; + + if ((r & 0xFF) == PT_PIPE && !(parts[r>>8].tmp&0xFF)) + { + parts[r>>8].tmp = (parts[r>>8].tmp&~0xFF) | parts[i].type; + parts[r>>8].temp = parts[i].temp; + parts[r>>8].flags = parts[i].life; + parts[r>>8].pavg[0] = parts[i].tmp; + parts[r>>8].pavg[1] = parts[i].ctype; + kill_part(i); + continue; + } + + // this should be replaced with a particle type attribute ("photwl" or something) + if ((r & 0xFF) == PT_PSCN) parts[i].ctype = 0x00000000; + if ((r & 0xFF) == PT_NSCN) parts[i].ctype = 0x00000000; + if ((r & 0xFF) == PT_SPRK) parts[i].ctype = 0x00000000; + if ((r & 0xFF) == PT_COAL) parts[i].ctype = 0x00000000; + if ((r & 0xFF) == PT_BCOL) parts[i].ctype = 0x00000000; + if ((r & 0xFF) == PT_PLEX) parts[i].ctype &= 0x1F00003E; + if ((r & 0xFF) == PT_NITR) parts[i].ctype &= 0x0007C000; + if ((r & 0xFF) == PT_NBLE) parts[i].ctype &= 0x3FFF8000; + if ((r & 0xFF) == PT_LAVA) parts[i].ctype &= 0x3FF00000; + if ((r & 0xFF) == PT_ACID) parts[i].ctype &= 0x1FE001FE; + if ((r & 0xFF) == PT_DUST) parts[i].ctype &= 0x3FFFFFC0; + if ((r & 0xFF) == PT_SNOW) parts[i].ctype &= 0x03FFFFFF; + if ((r & 0xFF) == PT_GOO) parts[i].ctype &= 0x3FFAAA00; + if ((r & 0xFF) == PT_PLNT) parts[i].ctype &= 0x0007C000; + if ((r & 0xFF) == PT_PLUT) parts[i].ctype &= 0x001FCE00; + if ((r & 0xFF) == PT_URAN) parts[i].ctype &= 0x003FC000; + + if (get_normal_interp(t, parts[i].x, parts[i].y, parts[i].vx, parts[i].vy, &nrx, &nry)) { + dp = nrx*parts[i].vx + nry*parts[i].vy; + parts[i].vx -= 2.0f*dp*nrx; + parts[i].vy -= 2.0f*dp*nry; + // leave the actual movement until next frame so that reflection of fast particles and refraction happen correctly + } else { + if (t!=PT_NEUT) + kill_part(i); + continue; + } + if (!parts[i].ctype&&t!=PT_NEUT&&t!=PT_ELEC) { + kill_part(i); + continue; + } + } + } + else if (ptypes[t].falldown==0) + { + // gasses and solids (but not powders) + if (!do_move(i, x, y, fin_xf, fin_yf)) + { + // can't move there, so bounce off + // TODO + if (fin_x>x+ISTP) fin_x=x+ISTP; + if (fin_xy+ISTP) fin_y=y+ISTP; + if (fin_y= rand()%400)//checking stagnant is cool, but then it doesn't update when you change it later. + { + if (!flood_water(x,y,i,y, parts[i].tmp2)) + goto movedone; + } + // liquids and powders + if (!do_move(i, x, y, fin_xf, fin_yf)) + { + if (fin_x!=x && do_move(i, x, y, fin_xf, clear_yf)) + { + parts[i].vx *= ptypes[t].collision; + parts[i].vy *= ptypes[t].collision; + } + else if (fin_y!=y && do_move(i, x, y, clear_xf, fin_yf)) + { + parts[i].vx *= ptypes[t].collision; + parts[i].vy *= ptypes[t].collision; + } + else + { + s = 1; + r = (rand()%2)*2-1; + if ((clear_x!=x || clear_y!=y || nt || surround_space) && + (fabsf(parts[i].vx)>0.01f || fabsf(parts[i].vy)>0.01f)) + { + // allow diagonal movement if target position is blocked + // but no point trying this if particle is stuck in a block of identical particles + dx = parts[i].vx - parts[i].vy*r; + dy = parts[i].vy + parts[i].vx*r; + if (fabsf(dy)>fabsf(dx)) + mv = fabsf(dy); + else + mv = fabsf(dx); + dx /= mv; + dy /= mv; + if (do_move(i, x, y, clear_xf+dx, clear_yf+dy)) + { + parts[i].vx *= ptypes[t].collision; + parts[i].vy *= ptypes[t].collision; + goto movedone; + } + swappage = dx; + dx = dy*r; + dy = -swappage*r; + if (do_move(i, x, y, clear_xf+dx, clear_yf+dy)) + { + parts[i].vx *= ptypes[t].collision; + parts[i].vy *= ptypes[t].collision; + goto movedone; + } + } + if (ptypes[t].falldown>1 && !ngrav_enable && gravityMode==0 && parts[i].vy>fabsf(parts[i].vx)) + { + s = 0; + // stagnant is true if FLAG_STAGNANT was set for this particle in previous frame + if (!stagnant || nt) //nt is if there is an something else besides the current particle type, around the particle + rt = 30;//slight less water lag, although it changes how it moves a lot + else + rt = 10; + for (j=clear_x+r; j>=0 && j>=clear_x-rt && j0) + r = 1; + else + r = -1; + if (s==1) + for (j=ny+r; j>=0 && j=ny-rt && j1 && fabsf(pGravX*parts[i].vx+pGravY*parts[i].vy)>fabsf(pGravY*parts[i].vx-pGravX*parts[i].vy)) + { + float nxf, nyf, prev_pGravX, prev_pGravY, ptGrav = ptypes[t].gravity; + s = 0; + // stagnant is true if FLAG_STAGNANT was set for this particle in previous frame + if (!stagnant || nt) //nt is if there is an something else besides the current particle type, around the particle + rt = 30;//slight less water lag, although it changes how it moves a lot + else + rt = 10; + nxf = clear_xf; + nyf = clear_yf; + for (j=0;jfabsf(pGravX)) + mv = fabsf(pGravY); + else + mv = fabsf(pGravX); + if (mv<0.0001f) break; + pGravX /= mv; + pGravY /= mv; + if (j) + { + nxf += r*(pGravY*2.0f-prev_pGravY); + nyf += -r*(pGravX*2.0f-prev_pGravX); + } + else + { + nxf += r*pGravY; + nyf += -r*pGravX; + } + prev_pGravX = pGravX; + prev_pGravY = pGravY; + nx = (int)(nxf+0.5f); + ny = (int)(nyf+0.5f); + if (nx<0 || ny<0 || nx>=XRES || ny >=YRES) + break; + if ((pmap[ny][nx]&0xFF)!=t || bmap[ny/CELL][nx/CELL]) + { + s = do_move(i, x, y, nxf, nyf); + if (s) + { + nx = (int)(parts[i].x+0.5f); + ny = (int)(parts[i].y+0.5f); + break; + } + if (bmap[ny/CELL][nx/CELL]!=WL_STREAM) + break; + } + } + if (s==1) + { + clear_x = nx; + clear_y = ny; + for (j=0;jfabsf(pGravX)) + mv = fabsf(pGravY); + else + mv = fabsf(pGravX); + if (mv<0.0001f) break; + pGravX /= mv; + pGravY /= mv; + nxf += pGravX; + nyf += pGravY; + nx = (int)(nxf+0.5f); + ny = (int)(nyf+0.5f); + if (nx<0 || ny<0 || nx>=XRES || ny>=YRES) + break; + if ((pmap[ny][nx]&0xFF)!=t || bmap[ny/CELL][nx/CELL]) + { + s = do_move(i, clear_x, clear_y, nxf, nyf); + if (s || bmap[ny/CELL][nx/CELL]!=WL_STREAM) + break; + } + } + } + else if (s==-1) {} // particle is out of bounds + else if ((clear_x!=x||clear_y!=y) && do_move(i, x, y, clear_xf, clear_yf)) {} + else parts[i].flags |= FLAG_STAGNANT; + parts[i].vx *= ptypes[t].collision; + parts[i].vy *= ptypes[t].collision; + } + else + { + // if interpolation was done, try moving to last clear position + if ((clear_x!=x||clear_y!=y) && do_move(i, x, y, clear_xf, clear_yf)) {} + else parts[i].flags |= FLAG_STAGNANT; + parts[i].vx *= ptypes[t].collision; + parts[i].vy *= ptypes[t].collision; + } + } + } + } +movedone: + continue; + } +} + +void Simulation::update_particles()//doesn't update the particles themselves, but some other things +{ + int i, j, x, y, t, nx, ny, r, cr,cg,cb, l = -1; + float lx, ly; + int lastPartUsed = 0; + int lastPartUnused = -1; +#ifdef MT + int pt = 0, pc = 0; + pthread_t *InterThreads; +#endif + + air->update_air(); + + memset(pmap, 0, sizeof(pmap)); + memset(photons, 0, sizeof(photons)); + NUM_PARTS = 0; + for (i=0; i<=parts_lastActiveIndex; i++)//the particle loop that resets the pmap/photon maps every frame, to update them. + { + if (parts[i].type) + { + t = parts[i].type; + x = (int)(parts[i].x+0.5f); + y = (int)(parts[i].y+0.5f); + if (x>=0 && y>=0 && x=NPART-1) pfree = -1; + else pfree = parts_lastActiveIndex+1; + } + else + { + if (parts_lastActiveIndex>=NPART-1) parts[lastPartUnused].life = -1; + else parts[lastPartUnused].life = parts_lastActiveIndex+1; + } + parts_lastActiveIndex = lastPartUsed; + if (!sys_pause||framerender) + { + for (y=0; y=XRES || ny<0 || ny>=YRES) + break; + addpixel(vid, nx, ny, 255, 255, 255, 64); + i = nx/CELL; + j = ny/CELL; + lx += vx[j][i]*0.125f; + ly += vy[j][i]*0.125f; + if (bmap[j][i]==WL_STREAM && i!=x && j!=y) + break; + } + drawtext(vid, x*CELL, y*CELL-2, "\x8D", 255, 255, 255, 128); + } +*/ +} + +Simulation::Simulation() +{ + //Create and attach gravity simulation + grav = new Gravity(); + //Give air sim references to our data + grav->bmap = bmap; + //Gravity sim gives us maps to use + gravx = grav->gravx; + gravy = grav->gravy; + gravp = grav->gravp; + gravmap = grav->gravmap; + + //Create and attach air simulation + air = new Air(); + //Give air sim references to our data + air->bmap = bmap; + air->emap = emap; + air->fvx = fvx; + air->fvy = fvy; + //Air sim gives us maps to use + vx = air->vx; + vy = air->vy; + pv = air->pv; + hv = air->hv; + + //ptypes[0] = {"", PIXPACK(0x000000), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, 0, R_TEMP+0.0f +273.15f, 251, "Erases particles.", ST_NONE, 0, NULL, NULL}; + //ptypes[1] = {"DUST", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 1, 85, 0, R_TEMP+0.0f +273.15f, 70, "Very light dust. Flammable.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, NULL, &graphics_DUST}; + //ptypes[2] = {"WATR", PIXPACK(0x2030D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, 0, R_TEMP-2.0f +273.15f, 29, "Liquid. Conducts electricity. Freezes. Extinguishes fires.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_WATR, NULL}; + +#define SC_WALL 0 +#define SC_ELEC 1 +#define SC_POWERED 2 +#define SC_EXPLOSIVE 3 +#define SC_GAS 4 +#define SC_LIQUID 5 +#define SC_POWDERS 6 +#define SC_SOLIDS 7 +#define SC_NUCLEAR 8 +#define SC_SPECIAL 9 +#define SC_LIFE 10 +#define SC_TOOL 11 +#define SC_CRACKER 13 +#define SC_CRACKER2 14 +#define SC_TOTAL 12 + + part_type ptypest[PT_NUM] = + { + //Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description + {"", PIXPACK(0x000000), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Erases particles.", ST_NONE, 0, NULL, NULL}, + {"DUST", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 1, 85, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Very light dust. Flammable.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, NULL, &graphics_DUST}, + {"WATR", PIXPACK(0x2030D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Liquid. Conducts electricity. Freezes. Extinguishes fires.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_WATR, NULL}, + {"OIL", PIXPACK(0x404010), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 20, 0, 0, 5, 1, 1, 20, SC_LIQUID, R_TEMP+0.0f +273.15f, 42, "Liquid. Flammable.", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, + {"FIRE", PIXPACK(0xFF1000), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.001f * CFDS, 1, 0, 0, 0, 1, 1, 1, 2, SC_EXPLOSIVE, R_TEMP+400.0f+273.15f, 88, "Ignites flammable materials. Heats air.", ST_GAS, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, &update_PYRO, &graphics_FIRE}, + {"STNE", PIXPACK(0xA0A0A0), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 1, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Heavy particles. Meltable.", ST_SOLID, TYPE_PART, NULL, NULL}, + {"LAVA", PIXPACK(0xE05010), 0.3f, 0.02f * CFDS, 0.95f, 0.80f, 0.0f, 0.15f, 0.00f, 0.0003f * CFDS, 2, 0, 0, 0, 2, 1, 1, 45, SC_LIQUID, R_TEMP+1500.0f+273.15f, 60, "Heavy liquid. Ignites flammable materials. Solidifies when cold.", ST_LIQUID, TYPE_LIQUID|PROP_LIFE_DEC, &update_PYRO, &graphics_LAVA}, + {"GUN", PIXPACK(0xC0C0D0), 0.7f, 0.02f * CFDS, 0.94f, 0.80f, -0.1f, 0.1f, 0.00f, 0.000f * CFDS, 1, 600, 1, 0, 10, 1, 1, 85, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 97, "Light dust. Explosive.", ST_SOLID, TYPE_PART, NULL, NULL}, + {"NITR", PIXPACK(0x20E010), 0.5f, 0.02f * CFDS, 0.92f, 0.97f, 0.0f, 0.2f, 0.00f, 0.000f * CFDS, 2, 1000, 2, 0, 3, 1, 1, 23, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 50, "Liquid. Pressure sensitive explosive.", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, + {"CLNE", PIXPACK(0xFFD010), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Solid. Duplicates any particles it touches.", ST_SOLID, TYPE_SOLID, &update_CLNE, NULL}, + {"GAS", PIXPACK(0xE0FF20), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 0.75f, 0.001f * CFDS, 0, 600, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+2.0f +273.15f, 42, "Gas. Diffuses. Flammable. Liquefies under pressure.", ST_GAS, TYPE_GAS, NULL, NULL}, + {"C-4", PIXPACK(0xD080E0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 1000, 2, 50, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Solid. Pressure sensitive explosive.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, NULL, NULL}, + {"GOO", PIXPACK(0x804000), 0.0f, 0.00f * CFDS, 0.97f, 0.50f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 12, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 75, "Solid. Deforms and disappears under pressure.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_GOO, NULL}, + {"ICE", PIXPACK(0xA0C0FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0003f* CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP-50.0f+273.15f, 46, "Solid. Freezes water. Crushes under pressure. Cools down air.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_ICEI, NULL}, + {"METL", PIXPACK(0x404060), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Solid. Conducts electricity. Meltable.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, NULL, NULL}, + {"SPRK", PIXPACK(0xFFFF80), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.001f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Electricity. Conducted by metal and water.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SPRK, &graphics_SPRK}, + {"SNOW", PIXPACK(0xC0E0FF), 0.7f, 0.01f * CFDS, 0.96f, 0.90f, -0.1f, 0.05f, 0.01f, -0.00005f* CFDS,1, 0, 0, 0, 20, 1, 1, 50, SC_POWDERS, R_TEMP-30.0f+273.15f, 46, "Light particles.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_ICEI, NULL}, + {"WOOD", PIXPACK(0xC0A040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 0, 15, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 164, "Solid. Flammable.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, NULL, NULL}, + {"NEUT", PIXPACK(0x20E0FF), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.01f, 0.002f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_NUCLEAR, R_TEMP+4.0f +273.15f, 60, "Neutrons. Interact with matter in odd ways.", ST_GAS, TYPE_ENERGY|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_NEUT, &graphics_NEUT}, + {"PLUT", PIXPACK(0x407020), 0.4f, 0.01f * CFDS, 0.99f, 0.95f, 0.0f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 90, SC_NUCLEAR, R_TEMP+4.0f +273.15f, 251, "Heavy particles. Fissile. Generates neutrons under pressure.", ST_SOLID, TYPE_PART|PROP_NEUTPENETRATE|PROP_RADIOACTIVE, &update_PLUT, NULL}, + {"PLNT", PIXPACK(0x0CAC00), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 0, 10, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 65, "Plant, drinks water and grows.", ST_SOLID, TYPE_SOLID|PROP_NEUTPENETRATE|PROP_LIFE_DEC, &update_PLNT, NULL}, + {"ACID", PIXPACK(0xED55FF), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 40, 0, 0, 1, 1, 1, 10, SC_LIQUID, R_TEMP+0.0f +273.15f, 34, "Dissolves almost everything.", ST_LIQUID, TYPE_LIQUID|PROP_DEADLY, &update_ACID, &graphics_ACID}, + {"VOID", PIXPACK(0x790B0B), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0003f* CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Hole, will drain away any particles.", ST_SOLID, TYPE_SOLID, NULL, NULL}, + {"WTRV", PIXPACK(0xA0A0FF), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, -0.1f, 0.75f, 0.0003f * CFDS, 0, 0, 0, 0, 4, 1, 1, 1, SC_GAS, R_TEMP+100.0f+273.15f, 48, "Steam, heats up air, produced from hot water.", ST_GAS, TYPE_GAS, &update_WTRV, NULL}, + {"CNCT", PIXPACK(0xC0C0C0), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 55, SC_POWDERS, R_TEMP+0.0f +273.15f, 100, "Concrete, stronger than stone.", ST_SOLID, TYPE_PART|PROP_HOT_GLOW, NULL, NULL}, + {"DSTW", PIXPACK(0x1020C0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP-2.0f +273.15f, 23, "Distilled water, does not conduct electricity.", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE, &update_DSTW, NULL}, + {"SALT", PIXPACK(0xFFFFFF), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 1, 1, 1, 75, SC_POWDERS, R_TEMP+0.0f +273.15f, 110, "Salt, dissolves in water.", ST_SOLID, TYPE_PART, NULL, NULL}, + {"SLTW", PIXPACK(0x4050F0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 35, SC_LIQUID, R_TEMP+0.0f +273.15f, 75, "Saltwater, conducts electricity, difficult to freeze.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_SLTW, NULL}, + {"DMND", PIXPACK(0xCCFFFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 186, "Diamond. Indestructible.", ST_SOLID, TYPE_SOLID, NULL, NULL}, + {"BMTL", PIXPACK(0x505070), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Breakable metal.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, &update_BMTL, NULL}, + {"BRMT", PIXPACK(0x705060), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 211, "Broken metal.", ST_SOLID, TYPE_PART|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, &update_BRMT, NULL}, + {"PHOT", PIXPACK(0xFFFFFF), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_NUCLEAR, R_TEMP+900.0f+273.15f, 251, "Photons. Travel in straight lines.", ST_GAS, TYPE_ENERGY|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_PHOT, &graphics_PHOT}, + {"URAN", PIXPACK(0x707020), 0.4f, 0.01f * CFDS, 0.99f, 0.95f, 0.0f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 90, SC_NUCLEAR, R_TEMP+30.0f+273.15f, 251, "Heavy particles. Generates heat under pressure.", ST_SOLID, TYPE_PART | PROP_RADIOACTIVE, &update_URAN, NULL}, + {"WAX", PIXPACK(0xF0F0BB), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 10, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 44, "Wax. Melts at moderately high temperatures.", ST_SOLID, TYPE_SOLID, NULL, NULL}, + {"MWAX", PIXPACK(0xE0E0AA), 0.3f, 0.02f * CFDS, 0.95f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000001f* CFDS,2, 5, 0, 0, 2, 1, 1, 25, SC_LIQUID, R_TEMP+28.0f+273.15f, 44, "Liquid Wax.", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, + {"PSCN", PIXPACK(0x805050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "P-Type Silicon, Will transfer current to any conductor.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, + {"NSCN", PIXPACK(0x505080), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "N-Type Silicon, Will not transfer current to P-Type Silicon.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, + {"LN2", PIXPACK(0x80A0DF), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 0, 1, 1, 30, SC_LIQUID, 70.15f, 70, "Liquid Nitrogen. Very cold.", ST_SOLID, TYPE_LIQUID, NULL, NULL}, + {"INSL", PIXPACK(0x9EA3B6), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 7, 0, 0, 10, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 0, "Insulator, does not conduct heat or electricity.", ST_SOLID, TYPE_SOLID, NULL, NULL}, + {"VACU", PIXPACK(0x303030), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, -0.01f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+70.0f+273.15f, 255, "Vacuum, sucks in other particles and heats up.", ST_NONE, TYPE_SOLID, NULL, NULL}, + {"VENT", PIXPACK(0xEFEFEF), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.010f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP-16.0f+273.15f, 255, "Air vent, creates pressure and pushes other particles away.", ST_NONE, TYPE_SOLID, NULL, NULL}, + {"RBDM", PIXPACK(0xCCCCCC), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 1000, 1, 50, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 240, "Rubidium, explosive, especially on contact with water, low melting point", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, + {"LRBD", PIXPACK(0xAAAAAA), 0.3f, 0.02f * CFDS, 0.95f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000001f* CFDS,2, 1000, 1, 0, 2, 1, 1, 45, SC_EXPLOSIVE, R_TEMP+45.0f+273.15f, 170, "Liquid Rubidium.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, + {"NTCT", PIXPACK(0x505040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Semi-conductor. Only conducts electricity when hot (More than 100C)", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, &update_NPTCT, NULL}, + {"SAND", PIXPACK(0xFFD090), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 1, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Sand, Heavy particles. Meltable.", ST_SOLID, TYPE_PART, NULL, NULL}, + {"GLAS", PIXPACK(0x404040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 150, "Solid. Meltable. Shatters under pressure", ST_SOLID, TYPE_SOLID | PROP_NEUTPASS | PROP_HOT_GLOW | PROP_SPARKSETTLE, &update_GLAS, NULL}, + {"PTCT", PIXPACK(0x405050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Semi-conductor. Only conducts electricity when cold (Less than 100C)", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, &update_NPTCT, NULL}, + {"BGLA", PIXPACK(0x606060), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Broken Glass, Heavy particles. Meltable. Bagels.", ST_SOLID, TYPE_PART | PROP_HOT_GLOW, NULL, NULL}, + {"THDR", PIXPACK(0xFFFFA0), 0.0f, 0.00f * CFDS, 1.0f, 0.30f, -0.99f, 0.6f, 0.62f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_EXPLOSIVE, 9000.0f +273.15f, 1, "Lightning! Very hot, inflicts damage upon most materials, transfers current to metals.", ST_NONE, TYPE_ENERGY, &update_THDR, &graphics_THDR}, + {"PLSM", PIXPACK(0xBB99FF), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.30f, 0.001f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, 10000.0f +273.15f, 5, "Plasma, extremely hot.", ST_NONE, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, &update_PYRO, &graphics_PLSM}, + {"ETRD", PIXPACK(0x404040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Electrode. Creates a surface that allows Plasma arcs. (Use sparingly)", ST_NONE, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, + {"NICE", PIXPACK(0xC0E0FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0005f* CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, 35.0f, 46, "Nitrogen Ice.", ST_SOLID, TYPE_SOLID, NULL, NULL}, + {"NBLE", PIXPACK(0xEB4917), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 0.75f, 0.001f * CFDS, 0, 0, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+2.0f +273.15f, 106, "Noble Gas. Diffuses. Conductive. Ionizes into plasma when introduced to electricity", ST_GAS, TYPE_GAS|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, + {"BTRY", PIXPACK(0x858505), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Solid. Generates Electricity.", ST_SOLID, TYPE_SOLID, &update_BTRY, NULL}, + {"LCRY", PIXPACK(0x505050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Liquid Crystal. Changes colour when charged. (PSCN Charges, NSCN Discharges)", ST_SOLID, TYPE_SOLID, &update_LCRY, &graphics_LCRY}, + {"STKM", PIXPACK(0x000000), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Stickman. Don't kill him!", ST_NONE, 0, &update_STKM, &graphics_STKM}, + {"SWCH", PIXPACK(0x103B11), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Solid. Only conducts when switched on. (PSCN switches on, NSCN switches off)", ST_SOLID, TYPE_SOLID, &update_SWCH, &graphics_SWCH}, + {"SMKE", PIXPACK(0x222222), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.001f * CFDS, 1, 0, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+320.0f+273.15f, 88, "Smoke", ST_SOLID, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, NULL, &graphics_SMKE}, + {"DESL", PIXPACK(0x440000), 1.0f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.0f, 0.0f * CFDS, 2, 2, 0, 0, 5, 1, 1, 15, SC_LIQUID, R_TEMP+0.0f +273.15f, 42, "Liquid. Explodes under high pressure and temperatures", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, + {"COAL", PIXPACK(0x222222), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 200, "Solid. Burns slowly.", ST_SOLID, TYPE_SOLID, &update_COAL, &graphics_COAL}, + {"LOXY", PIXPACK(0x80A0EF), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 5000, 0, 0, 0, 1, 1, 30, SC_LIQUID, 80.0f, 70, "Liquid Oxygen. Very cold. Reacts with fire", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, + {"OXYG", PIXPACK(0x80A0FF), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 3.0f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+0.0f +273.15f, 70, "Gas. Ignites easily.", ST_GAS, TYPE_GAS, &update_O2, NULL}, + {"INWR", PIXPACK(0x544141), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Insulated Wire. Doesn't conduct to metal or semiconductors.", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC, NULL, NULL}, + {"YEST", PIXPACK(0xEEE0C0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 15, 0, 0, 30, 1, 1, 80, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Yeast, grows when warm (~37C).", ST_SOLID, TYPE_PART, &update_YEST, NULL}, + {"DYST", PIXPACK(0xBBB0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 20, 0, 0, 30, 0, 1, 80, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Dead Yeast.", ST_SOLID, TYPE_PART, NULL, NULL}, + {"THRM", PIXPACK(0xA08090), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 211, "Thermite. Burns at extremely high temperature.", ST_SOLID, TYPE_PART, &update_THRM, NULL}, + {"GLOW", PIXPACK(0x445464), 0.3f, 0.02f * CFDS, 0.98f, 0.80f, 0.0f, 0.15f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 2, 1, 1, 40, SC_LIQUID, R_TEMP+20.0f+273.15f, 44, "Glow, Glows under pressure", ST_LIQUID, TYPE_LIQUID|PROP_LIFE_DEC, &update_GLOW, &graphics_GLOW}, + {"BRCK", PIXPACK(0x808080), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Brick, breakable building material.", ST_SOLID, TYPE_SOLID|PROP_HOT_GLOW, NULL, NULL}, + {"CFLM", PIXPACK(0x8080FF), 0.9f, 0.04f * CFDS, 0.97f, 0.20f, 0.0f, -0.1f, 0.00f, 0.0005f * CFDS, 1, 0, 0, 0, 1, 1, 1, 2, SC_EXPLOSIVE, 0.0f, 88, "Sub-zero flame.", ST_LIQUID, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, NULL, &graphics_HFLM}, + {"FIRW", PIXPACK(0xFFA040), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, -0.99f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 55, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 70, "Fireworks!", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_FIRW, &graphics_FIRW}, + {"FUSE", PIXPACK(0x0A5706), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 200, "Solid. Burns slowly. Ignites at somewhat high temperatures and electricity.", ST_SOLID, TYPE_SOLID, &update_FUSE, NULL}, + {"FSEP", PIXPACK(0x63AD5F), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 70, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Fuse Powder. See FUSE.", ST_SOLID, TYPE_PART, &update_FSEP, NULL}, + {"AMTR", PIXPACK(0x808080), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.00f, 0.10f, 1.00f, 0.0000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_NUCLEAR, R_TEMP+0.0f +273.15f, 70, "Anti-Matter, Destroys a majority of particles", ST_NONE, TYPE_PART, &update_AMTR, NULL}, //Maybe TYPE_ENERGY? + {"BCOL", PIXPACK(0x333333), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.3f, 0.00f, 0.000f * CFDS, 1, 0, 0, 5, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 150, "Broken Coal. Heavy particles. See COAL", ST_SOLID, TYPE_PART, &update_BCOL, NULL}, + {"PCLN", PIXPACK(0x3B3B0A), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Solid. When activated, duplicates any particles it touches.", ST_NONE, TYPE_SOLID, &update_PCLN, &graphics_PCLN}, + {"HSWC", PIXPACK(0x3B0A0A), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Heat switch. Conducts Heat only when activated", ST_NONE, TYPE_SOLID, &update_HSWC, &graphics_HSWC}, + {"IRON", PIXPACK(0x707070), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 50, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Rusts with salt, can be used for electrolysis of WATR", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, &update_IRON, NULL}, + {"MORT", PIXPACK(0xE0E0E0), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.01f, 0.002f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_CRACKER2, R_TEMP+4.0f +273.15f, 60, "Steam Train.", ST_NONE, TYPE_PART, &update_MORT, NULL}, + {"LIFE", PIXPACK(0x0CAC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 1, 100, SC_LIFE, 9000.0f, 40, "Game Of Life! B3/S23", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, &graphics_LIFE}, + {"DLAY", PIXPACK(0x753590), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, 4.0f+273.15f, 0, "Conducts with temperature-dependent delay. (use HEAT/COOL).", ST_SOLID, TYPE_SOLID, &update_DLAY, &graphics_DLAY}, + {"CO2", PIXPACK(0x666666), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.1f, 0.1f, 1.0f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+273.15f, 88, "Carbon Dioxide", ST_GAS, TYPE_GAS, &update_CO2, NULL}, + {"DRIC", PIXPACK(0xE0E0E0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0005f* CFDS, 0, 0, 0, 0, 20, 1, 1, 100, SC_SOLIDS, 172.65f, 2, "Dry Ice.", ST_SOLID, TYPE_SOLID, NULL, NULL}, + {"BUBW", PIXPACK(0x2030D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Carbonated water. Conducts electricity. Freezes. Extinguishes fires.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_NEUTPENETRATE, &update_CBNW, &graphics_CBNW}, + {"STOR", PIXPACK(0x50DFDF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Solid. Stores a single particle, releases when charged with PSCN, also passes to PIPE", ST_NONE, TYPE_SOLID, &update_STOR, &graphics_STOR}, + {"PVOD", PIXPACK(0x792020), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Solid. When activated, destroys entering particles", ST_NONE, TYPE_SOLID, &update_PVOD, &graphics_PVOD}, + {"CONV", PIXPACK(0x0AAB0A), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Solid. Converts whatever touches it into its ctype.", ST_NONE, TYPE_SOLID, &update_CONV, NULL}, + {"CAUS", PIXPACK(0x80FFA0), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 1.50f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+0.0f +273.15f, 70, "Caustic Gas, acts like Acid", ST_GAS, TYPE_GAS|PROP_DEADLY, &update_CAUS, NULL}, + {"LIGH", PIXPACK(0xFFFFC0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 0, "More realistic lightning. Set pen size to set the size of the lightning.", ST_SOLID, TYPE_SOLID, &update_LIGH, &graphics_LIGH}, + {"TESC", PIXPACK(0x707040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Tesla coil!", ST_SOLID, TYPE_SOLID|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, NULL, NULL}, + {"DEST", PIXPACK(0xFF3311), -0.05f, 0.00f * CFDS, 0.95f, 0.95f, -0.1f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 101, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 150, "More destructive Bomb.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_DEST, &graphics_DEST}, + {"SPNG", PIXPACK(0xFFBE30), 0.00f, 0.00f * CFDS, 0.00f, 1.00f, 0.00f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 1, 30, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "A sponge, absorbs water.", ST_SOLID, TYPE_SOLID, &update_SPNG, &graphics_SPNG}, + {"RIME", PIXPACK(0xCCCCCC), 0.00f, 0.00f * CFDS, 0.00f, 1.00f, 0.00f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 30, 1, 1, 100, SC_CRACKER2, 243.15f, 100, "Not quite Ice", ST_SOLID, TYPE_SOLID, &update_RIME, NULL}, + {"FOG", PIXPACK(0xAAAAAA), 0.8f, 0.00f * CFDS, 0.4f, 0.70f, -0.1f, 0.0f, 0.99f, 0.000f * CFDS, 0, 0, 0, 0, 30, 1, 1, 1, SC_CRACKER2, 243.15f, 100, "Not quite Steam", ST_GAS, TYPE_GAS|PROP_LIFE_DEC, &update_FOG, NULL}, + {"BCLN", PIXPACK(0xFFD040), 0.0f, 0.00f * CFDS, 0.97f, 0.50f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 12, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Breakable Clone.", ST_NONE, TYPE_SOLID|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_BCLN, NULL}, + {"LOVE", PIXPACK(0xFF30FF), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.0f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_CRACKER2, 373.0f, 40, "Love...", ST_GAS, TYPE_SOLID, &update_MISC, NULL}, + {"DEUT", PIXPACK(0x00153F), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 31, SC_NUCLEAR, R_TEMP-2.0f +273.15f, 251, "Deuterium oxide. Volume changes with temp, radioactive with neutrons.", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE, &update_DEUT, &graphics_DEUT}, + {"WARP", PIXPACK(0x000000), 0.8f, 0.00f * CFDS, 0.9f, 0.70f, -0.1f, 0.0f, 3.00f, 0.000f * CFDS, 0, 0, 0, 0, 30, 1, 1, 1, SC_NUCLEAR, R_TEMP +273.15f, 100, "Displaces other elements.", ST_GAS, TYPE_GAS|PROP_LIFE_DEC|PROP_LIFE_KILL, &update_WARP, NULL}, + {"PUMP", PIXPACK(0x0A0A3B), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 10, 1, 1, 100, SC_POWERED, 273.15f, 0, "Changes pressure to its temp when activated. (use HEAT/COOL).", ST_SOLID, TYPE_SOLID, &update_PUMP, &graphics_PUMP}, + {"FWRK", PIXPACK(0x666666), 0.4f, 0.01f * CFDS, 0.99f, 0.95f, 0.0f, 0.4f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 1, 1, 1, 97, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 100, "First fireworks made, activated by heat/neutrons.", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_FWRK, NULL}, + {"PIPE", PIXPACK(0x444444), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, 273.15f, 0, "Moves elements around, read FAQ on website for help.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_PIPE, &graphics_PIPE}, + {"FRZZ", PIXPACK(0xC0E0FF), 0.7f, 0.01f * CFDS, 0.96f, 0.90f, -0.1f, 0.05f, 0.01f, -0.00005f* CFDS,1, 0, 0, 0, 20, 1, 1, 50, SC_POWDERS, 90.0f, 46, "FREEZE", ST_SOLID, TYPE_PART, &update_FRZZ, NULL}, + {"FRZW", PIXPACK(0x1020C0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_CRACKER2, 120.0f, 29, "FREEZE WATER", ST_LIQUID, TYPE_LIQUID||PROP_LIFE_DEC, &update_FRZW, NULL}, + {"GRAV", PIXPACK(0xFFE0A0), 0.7f, 0.00f * CFDS, 1.00f, 1.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 1, 85, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Very light dust. Changes colour based on velocity.", ST_SOLID, TYPE_PART, &update_MISC, &graphics_GRAV}, + {"BIZR", PIXPACK(0x00FF77), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 30, SC_LIQUID, R_TEMP+0.0f +273.15f, 29, "Bizarre... contradicts the normal state changes.", ST_LIQUID, TYPE_LIQUID, &update_BIZR, &graphics_BIZR}, + {"BIZG", PIXPACK(0x00FFBB), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 2.75f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 1, SC_CRACKER2, R_TEMP-200.0f+273.15f, 42, "Bizarre gas", ST_GAS, TYPE_GAS, &update_BIZR, &graphics_BIZR}, + {"BIZS", PIXPACK(0x00E455), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_CRACKER2, R_TEMP+300.0f+273.15f, 251, "Bizarre solid", ST_SOLID, TYPE_SOLID, &update_BIZR, &graphics_BIZR}, + {"INST", PIXPACK(0x404039), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Instantly conducts, PSCN to charge, NSCN to take.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, NULL, NULL}, + {"ISOZ", PIXPACK(0xAA30D0), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 0, 1, 1, 24, SC_NUCLEAR, R_TEMP-2.0f +273.15f, 29, "Radioactive liquid", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE, &update_ISZ, NULL}, + {"ISZS", PIXPACK(0x662089), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0007f* CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_NUCLEAR, 140.00f, 251, "Solid form of ISOZ, slowly decays.", ST_SOLID, TYPE_SOLID, &update_ISZ, NULL}, + {"PRTI", PIXPACK(0xEB5917), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.005f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 0, "Portal IN. Things go in here, now with channels (same as WIFI)", ST_SOLID, TYPE_SOLID, &update_PRTI, &graphics_PRTI}, + {"PRTO", PIXPACK(0x0020EB), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.005f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 0, "Portal OUT. Things come out here, now with channels (same as WIFI)", ST_SOLID, TYPE_SOLID, &update_PRTO, &graphics_PRTO}, + {"PSTE", PIXPACK(0xAA99AA), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 31, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Colloid, Hardens under pressure", ST_LIQUID, TYPE_LIQUID, NULL, NULL}, + {"PSTS", PIXPACK(0x776677), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 20, 0, 1, 100, SC_CRACKER, R_TEMP-2.0f +273.15f, 29, "Solid form of PSTE, temporary", ST_SOLID, TYPE_SOLID, NULL, NULL}, + {"ANAR", PIXPACK(0xFFFFEE), -0.7f, -0.02f * CFDS, 0.96f, 0.80f, 0.1f, -0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 1, 1, 85, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Very light dust. Behaves opposite gravity", ST_SOLID, TYPE_PART, &update_ANAR, NULL}, + {"VINE", PIXPACK(0x079A00), 0.0f, 0.00f * CFDS, 0.95f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 20, 0, 0, 10, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 65, "Vine, grows", ST_SOLID, TYPE_SOLID, &update_VINE, NULL}, + {"INVS", PIXPACK(0x00CCCC), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 15, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 164, "Invisible to everything while under pressure.", ST_SOLID, TYPE_SOLID | PROP_NEUTPASS, NULL, &graphics_INVS}, + {"EQVE", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 30, 0, 1, 85, SC_CRACKER2, R_TEMP+0.0f +273.15f, 70, "Shared velocity test", ST_SOLID, TYPE_PART, NULL, NULL}, + {"SPWN2", PIXPACK(0xAAAAAA), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 0, "STK2 spawn point", ST_SOLID, TYPE_SOLID, &update_SPAWN2, NULL}, + {"SPWN", PIXPACK(0xAAAAAA), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 0, "STKM spawn point", ST_SOLID, TYPE_SOLID, &update_SPAWN, NULL}, + {"SHLD", PIXPACK(0xAAAAAA), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 0, "Shield, spark it to grow", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD1, NULL}, + {"SHD2", PIXPACK(0x777777), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_CRACKER2, R_TEMP+0.0f +273.15f, 0, "Shield lvl 2", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD2, NULL}, + {"SHD3", PIXPACK(0x444444), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_CRACKER2, R_TEMP+0.0f +273.15f, 0, "Shield lvl 3", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD3, NULL}, + {"SHD4", PIXPACK(0x212121), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 0, 1, 100, SC_CRACKER2, R_TEMP+0.0f +273.15f, 0, "Shield lvl 4", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_SHLD4, NULL}, + {"LOLZ", PIXPACK(0x569212), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.0f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_CRACKER2, 373.0f, 40, "Lolz", ST_GAS, TYPE_SOLID, &update_MISC, NULL}, + {"WIFI", PIXPACK(0x40A060), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 2, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 0, "Wireless transmitter, color coded.", ST_SOLID, TYPE_SOLID, &update_WIFI, &graphics_WIFI}, + {"FILT", PIXPACK(0x000056), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 251, "Filter for photons, changes the color.", ST_SOLID, TYPE_SOLID, NULL, &graphics_FILT}, + {"ARAY", PIXPACK(0xFFBB00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 0, "Ray Emitter. Rays create points when they collide", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_ARAY, NULL}, + {"BRAY", PIXPACK(0xFFFFFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 0, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Ray Point. Rays create points when they collide", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC|PROP_LIFE_KILL, NULL, &graphics_BRAY}, + {"STK2", PIXPACK(0x000000), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Stickman. Don't kill him!", ST_NONE, 0, &update_STKM2, &graphics_STKM2}, + {"BOMB", PIXPACK(0xFFF288), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 20, 1, 1, 30, SC_EXPLOSIVE, R_TEMP-2.0f +273.15f, 29, "Bomb.", ST_NONE, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC|PROP_SPARKSETTLE, &update_BOMB, &graphics_BOMB}, + {"C-5", PIXPACK(0x2050E0), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Cold explosive", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, &update_C5, NULL}, + {"SING", PIXPACK(0x242424), 0.7f, 0.36f * CFDS, 0.96f, 0.80f, 0.1f, 0.12f, 0.00f, -0.001f * CFDS, 1, 0, 0, 0, 0, 1, 1, 86, SC_NUCLEAR, R_TEMP+0.0f +273.15f, 70, "Singularity", ST_SOLID, TYPE_PART|PROP_LIFE_DEC, &update_SING, NULL}, + {"QRTZ", PIXPACK(0xAADDDD), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SOLIDS, R_TEMP+0.0f +273.15f, 3, "Quartz, breakable mineral. Conducts but becomes brittle at lower temperatures.", ST_SOLID, TYPE_SOLID|PROP_HOT_GLOW|PROP_LIFE_DEC, &update_QRTZ, &graphics_QRTZ}, + {"PQRT", PIXPACK(0x88BBBB), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.27f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 0, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 3, "Broken quartz.", ST_SOLID, TYPE_PART| PROP_HOT_GLOW, &update_QRTZ, &graphics_QRTZ}, + {"EMP", PIXPACK(0x66AAFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.0f, 0.0f * CFDS, 0, 0, 0, 0, 3, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 121, "Breaks activated electronics.", ST_SOLID, TYPE_SOLID|PROP_LIFE_DEC, &update_EMP, &graphics_EMP}, + {"BREL", PIXPACK(0x707060), 0.4f, 0.04f * CFDS, 0.94f, 0.95f, -0.1f, 0.18f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 90, SC_POWDERS, R_TEMP+0.0f +273.15f, 211, "Broken electronics", ST_SOLID, TYPE_PART|PROP_CONDUCTS|PROP_LIFE_DEC|PROP_HOT_GLOW, NULL, NULL}, + {"ELEC", PIXPACK(0xDFEFFF), 0.0f, 0.00f * CFDS, 1.00f, 1.00f, -0.99f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, -1, SC_NUCLEAR, R_TEMP+200.0f+273.15f, 251, "Electrons", ST_GAS, TYPE_ENERGY|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_ELEC, &graphics_ELEC}, + {"ACEL", PIXPACK(0x0099CC), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Accelerator", ST_NONE, TYPE_SOLID, &update_ACEL, &graphics_ACEL}, + {"DCEL", PIXPACK(0x99CC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Decelerator", ST_NONE, TYPE_SOLID, &update_DCEL, &graphics_DCEL}, + {"TNT", PIXPACK(0xC05050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Explosive.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE, &update_BANG, NULL}, + {"IGNC", PIXPACK(0xC0B050), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 100, SC_EXPLOSIVE, R_TEMP+0.0f +273.15f, 88, "Ignition cord.", ST_SOLID, TYPE_SOLID | PROP_NEUTPENETRATE | PROP_SPARKSETTLE | PROP_LIFE_KILL, &update_IGNT, NULL}, + {"BOYL", PIXPACK(0x0A3200), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 0.18f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 1, 1, SC_GAS, R_TEMP+2.0f +273.15f, 42, "Boyle, variable pressure gas. Expands when heated.", ST_GAS, TYPE_GAS, &update_BOYL, NULL}, + /*FREE*/{"LOTE", PIXPACK(0xFF0000), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Behaves kinda like Living on the Edge S3458/B37/4", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, + /*FREE*/{"FRG2", PIXPACK(0x00FF00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Like Frogs rule S124/B3/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, + /*FREE*/{"STAR", PIXPACK(0x0000FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Like Star Wars rule S3456/B278/6", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, + /*FREE*/{"FROG", PIXPACK(0x00AA00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Frogs S12/B34/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, + /*FREE*/{"BRAN", PIXPACK(0xCCCC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_LIFE, 9000.0f, 40, "Brian 6 S6/B246/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL, NULL}, + /*FREE*/{"WIND", PIXPACK(0x101010), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 0, 0, 100, SC_SPECIAL, 0.0f, 40, "", ST_NONE, ST_NONE, NULL, NULL}, + {"HYGN", PIXPACK(0x5070FF), 2.0f, 0.00f * CFDS, 0.99f, 0.30f, -0.10f, 0.00f, 3.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 1, SC_GAS, R_TEMP+0.0f +273.15f, 251, "Combines with O2 to make WATR", ST_GAS, TYPE_GAS, &update_H2, NULL}, + {"SOAP", PIXPACK(0xF5F5DC), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 35, SC_LIQUID, R_TEMP-2.0f +273.15f, 29, "Soap. Creates bubbles.", ST_LIQUID, TYPE_LIQUID|PROP_NEUTPENETRATE|PROP_LIFE_DEC, &update_SOAP, NULL}, + {"BHOL", PIXPACK(0x202020), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 186, "Black hole (Requires newtonian gravity)", ST_SOLID, TYPE_SOLID, &update_NBHL, NULL}, + {"WHOL", PIXPACK(0xFFFFFF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 186, "White hole (Requires newtonian gravity)", ST_SOLID, TYPE_SOLID, &update_NWHL, NULL}, + {"MERC", PIXPACK(0x736B6D), 0.4f, 0.04f * CFDS, 0.94f, 0.80f, 0.0f, 0.3f, 0.00f, 0.000f * CFDS, 2, 0, 0, 0, 20, 1, 1, 91, SC_ELEC, R_TEMP+0.0f +273.15f, 251, "Mercury. Volume changes with temperature, Conductive.", ST_LIQUID, TYPE_LIQUID|PROP_CONDUCTS|PROP_NEUTABSORB|PROP_LIFE_DEC, &update_MERC, NULL}, + {"PBCN", PIXPACK(0x3B1D0A), 0.0f, 0.00f * CFDS, 0.97f, 0.50f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 12, 1, 1, 100, SC_POWERED, R_TEMP+0.0f +273.15f, 251, "Powered breakable clone", ST_NONE, TYPE_SOLID, &update_PBCN, &graphics_PBCN}, + {"GPMP", PIXPACK(0x0A3B3B), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, 1, 100, SC_POWERED, 0.0f +273.15f, 0, "Changes gravity to its temp when activated. (use HEAT/COOL).", ST_NONE, TYPE_SOLID, &update_GPMP, &graphics_GPMP}, + {"CLST", PIXPACK(0xE4A4A4), 0.7f, 0.02f * CFDS, 0.94f, 0.95f, 0.0f, 0.2f, 0.00f, 0.000f * CFDS, 1, 0, 0, 2, 2, 1, 1, 55, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Clay dust. Produces paste when mixed with water.", ST_SOLID, TYPE_PART, &update_CLST, &graphics_CLST}, + {"WIRE", PIXPACK(0xFFCC00), 0.0f, 0.00f * CFDS, 0.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 1, 100, SC_ELEC, R_TEMP+0.0f +273.15f, 250, "WireWorld wires.",ST_SOLID,TYPE_SOLID,&update_WIRE, &graphics_WIRE}, + {"GBMB", PIXPACK(0x1144BB), 0.6f, 0.01f * CFDS, 0.98f, 0.95f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 0, 0, 0, 20, 1, 1, 30, SC_EXPLOSIVE, R_TEMP-2.0f +273.15f, 29, "Sticks to first object it touches then produces strong gravity push.", ST_NONE, TYPE_PART|PROP_LIFE_DEC|PROP_LIFE_KILL_DEC, &update_GBMB, &graphics_GBMB}, + {"FIGH", PIXPACK(0x000000), 0.5f, 0.00f * CFDS, 0.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.00f * CFDS, 0, 0, 0, 0, 0, 1, 1, 50, SC_SPECIAL, R_TEMP+14.6f+273.15f, 0, "Fighter. Tries to kill stickmen.", ST_NONE, 0, &update_FIGH, &graphics_FIGH}, + //Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Use Weight Section H Ins Description + }; + memcpy(ptypes, ptypest, sizeof(part_type)*PT_NUM); + +#define IPL -257.0f +#define IPH 257.0f +#define ITL MIN_TEMP-1 +#define ITH MAX_TEMP+1 +// no transition (PT_NONE means kill part) +#define NT -1 +// special transition - lava ctypes etc need extra code, which is only found and run if ST is given +#define ST PT_NUM +part_transition ptransitionst[PT_NUM] = +{ // if low pressure if high pressure if low temperature if high temperature + // Name plv plt phv pht tlv tlt thv tht + /* NONE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* DUST */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* WATR */ {IPL, NT, IPH, NT, 273.15f,PT_ICEI, 373.0f, PT_WTRV}, + /* OIL */ {IPL, NT, IPH, NT, ITL, NT, 333.0f, PT_GAS}, + /* FIRE */ {IPL, NT, IPH, NT, ITL, NT, 2773.0f,PT_PLSM}, + /* STNE */ {IPL, NT, IPH, NT, ITL, NT, 983.0f, PT_LAVA}, + /* LAVA */ {IPL, NT, IPH, NT, 2573.15f,ST, ITH, NT}, // 2573.15f is highest melt pt of possible ctypes + /* GUN */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, + /* NITR */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, + /* CLNE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* GAS */ {IPL, NT, 6.0f, PT_OIL, ITL, NT, 573.0f, PT_FIRE}, + /* C-4 */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, + /* GOO */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* ICE */ {IPL, NT, 0.8f, PT_SNOW, ITL, NT, 233.0f, ST}, + /* METL */ {IPL, NT, IPH, NT, ITL, NT, 1273.0f,PT_LAVA}, + /* SPRK */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SNOW */ {IPL, NT, IPH, NT, ITL, NT, 273.0f, PT_WATR}, + /* WOOD */ {IPL, NT, IPH, NT, ITL, NT, 873.0f, PT_FIRE}, + /* NEUT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PLUT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PLNT */ {IPL, NT, IPH, NT, ITL, NT, 573.0f, PT_FIRE}, + /* ACID */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* VOID */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* WTRV */ {IPL, NT, IPH, NT, 371.0f, ST, ITH, NT}, + /* CNCT */ {IPL, NT, IPH, NT, ITL, NT, 1123.0f,PT_LAVA}, + /* DSTW */ {IPL, NT, IPH, NT, 273.15f,PT_ICEI, 373.0f, PT_WTRV}, + /* SALT */ {IPL, NT, IPH, NT, ITL, NT, 1173.0f,PT_LAVA}, + /* SLTW */ {IPL, NT, IPH, NT, 233.0f, PT_ICEI, 483.0f, ST}, + /* DMND */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* BMTL */ {IPL, NT, 1.0f, ST, ITL, NT, 1273.0f,PT_LAVA}, + /* BRMT */ {IPL, NT, IPH, NT, ITL, NT, 1273.0f,PT_LAVA}, + /* PHOT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* URAN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* WAX */ {IPL, NT, IPH, NT, ITL, NT, 319.0f, PT_MWAX}, + /* MWAX */ {IPL, NT, IPH, NT, 318.0f, PT_WAX, 673.0f, PT_FIRE}, + /* PSCN */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, + /* NSCN */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, + /* LN2 */ {IPL, NT, IPH, NT, 63.0f, PT_NICE, 77.0f, PT_NONE}, + /* INSL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* VACU */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* VENT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* RBDM */ {IPL, NT, IPH, NT, ITL, NT, 312.0f, PT_LRBD}, + /* LRBD */ {IPL, NT, IPH, NT, 311.0f, PT_RBDM, 961.0f, PT_FIRE}, + /* NTCT */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, + /* SAND */ {IPL, NT, IPH, NT, ITL, NT, 1973.0f,PT_LAVA}, + /* GLAS */ {IPL, NT, IPH, NT, ITL, NT, 1973.0f,PT_LAVA}, + /* PTCT */ {IPL, NT, IPH, NT, ITL, NT, 1414.0f,PT_LAVA}, + /* BGLA */ {IPL, NT, IPH, NT, ITL, NT, 1973.0f,PT_LAVA}, + /* THDR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PLSM */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* ETRD */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* NICE */ {IPL, NT, IPH, NT, ITL, NT, 63.1f, PT_LNTG}, + /* NBLE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* BTRY */ {IPL, NT, IPH, NT, ITL, NT, 2273.0f,PT_PLSM}, + /* LCRY */ {IPL, NT, IPH, NT, ITL, NT, 1273.0f,PT_BGLA}, + /* STKM */ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE}, + /* SWCH */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SMKE */ {IPL, NT, IPH, NT, ITL, NT, 625.0f, PT_FIRE}, + /* DESL */ {IPL, NT, 5.0f, PT_FIRE, ITL, NT, 335.0f, PT_FIRE}, + /* COAL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* LO2 */ {IPL, NT, IPH, NT, ITL, NT, 90.1f, PT_O2}, + /* O2 */ {IPL, NT, IPH, NT, 90.0f, PT_LO2, ITH, NT}, + /* INWR */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, + /* YEST */ {IPL, NT, IPH, NT, ITL, NT, 373.0f, PT_DYST}, + /* DYST */ {IPL, NT, IPH, NT, ITL, NT, 473.0f, PT_DUST}, + /* THRM */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* GLOW */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* BRCK */ {IPL, NT, 8.8f, PT_STNE, ITL, NT, 1223.0f,PT_LAVA}, + /* CFLM */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* FIRW */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* FUSE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* FSEP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* AMTR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* BCOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PCLN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* HSWC */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* IRON */ {IPL, NT, IPH, NT, ITL, NT, 1687.0f,PT_LAVA}, + /* MORT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* LIFE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* DLAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* CO2 */ {IPL, NT, IPH, NT, 194.65f,PT_DRIC, ITH, NT}, + /* DRIC */ {IPL, NT, IPH, NT, ITL, NT, 195.65f,PT_CO2}, + /* CBNW */ {IPL, NT, IPH, NT, 273.15f,PT_ICEI, 373.0f, PT_WTRV}, + /* STOR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* STOR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SPNG */ {IPL, NT, IPH, NT, ITL, NT, 2730.0f,PT_FIRE}, + /* RIME */ {IPL, NT, IPH, NT, ITL, NT, 273.15f,PT_WATR}, + /* FOG */ {IPL, NT, IPH, NT, ITL, NT, 373.15f,PT_WTRV}, + /* BCLN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* LOVE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* DEUT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* WARP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PUMP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* FWRK */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PIPE */ {IPL, NT, 10.0f, PT_BRMT, ITL, NT, ITH, NT}, + /* FRZZ */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* FRZW */ {IPL, NT, IPH, NT, ITL, NT, 53.0f, PT_ICEI}, + /* GRAV */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* BIZR */ {IPL, NT, IPH, NT, 100.0f, PT_BIZRG, 400.0f, PT_BIZRS}, + /* BIZRG*/ {IPL, NT, IPH, NT, ITL, NT, 100.0f, PT_BIZR},//, 400.0f, PT_BIZRS}, + /* BIZRS*/ {IPL, NT, IPH, NT, 400.0f, PT_BIZR, ITH, NT},// 100.0f, PT_BIZRG}, + /* INST */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* ISOZ */ {IPL, NT, IPH, NT, 160.0f, PT_ISZS, ITH, NT}, + /* ISZS */ {IPL, NT, IPH, NT, ITL, NT, 300.0f, PT_ISOZ}, + /* PRTI */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PRTO */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PSTE */ {IPL, NT, 0.5f, PT_PSTS, ITL, NT, 747.0f, PT_BRCK}, + /* PSTS */ {0.5f, PT_PSTE, IPH, NT, ITL, NT, ITH, NT}, + /* ANAR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* VINE */ {IPL, NT, IPH, NT, ITL, NT, 573.0f, PT_FIRE}, + /* INVS */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* EQVE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SPWN2*/ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SPAWN*/ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SHLD1*/ {IPL, NT, 7.0f, PT_NONE, ITL, NT, ITH, NT}, + /* SHLD2*/ {IPL, NT, 15.0f, PT_NONE, ITL, NT, ITH, NT}, + /* SHLD3*/ {IPL, NT, 25.0f, PT_NONE, ITL, NT, ITH, NT}, + /* SHLD4*/ {IPL, NT, 40.0f, PT_NONE, ITL, NT, ITH, NT}, + /* LOlZ */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* WIFI */ {IPL, NT, 15.0f, PT_BRMT, ITL, NT, ITH, NT}, + /* FILT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* ARAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* BRAY */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* STKM2*/ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE}, + /* BOMB */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* C-5 */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SING */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* QRTZ */ {IPL, NT, IPH, NT, ITL, NT, 2573.15f,PT_LAVA}, + /* PQRT */ {IPL, NT, IPH, NT, ITL, NT, 2573.15f,PT_LAVA}, + /* EMP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* BREL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* ELEC */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* ACEL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* DCEL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* TNT */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* IGNP */ {IPL, NT, IPH, NT, ITL, NT, 673.0f, PT_FIRE}, + /* BOYL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /*FREE*//* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* WIND */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* H2 */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* SOAP */ {IPL, NT, IPH, NT, ITL, NT, ITL, NT}, + /* NBHL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* NWHL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* MERC */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* PBCN */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* GPMP */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* CLST */ {IPL, NT, IPH, NT, ITL, NT, 1256.0f, PT_LAVA}, + /* WIRE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* GBMB */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT}, + /* FIGH */ {IPL, NT, IPH, NT, ITL, NT, 620.0f, PT_FIRE}, +}; +#undef IPL +#undef IPH +#undef ITL +#undef ITH +#undef NT +#undef ST*/ + memcpy(ptransitions, ptransitionst, sizeof(part_transition) * PT_NUM); + init_can_move(); + clear_sim(); +} diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h new file mode 100644 index 0000000..b3c51af --- /dev/null +++ b/src/simulation/Simulation.h @@ -0,0 +1,241 @@ +/* + * Simulation.h + * + * Created on: Jan 2, 2012 + * Author: Simon + */ + +#ifndef SIMULATION_H_ +#define SIMULATION_H_ +#include +#include "Config.h" +#include "Renderer.h" +#include "Graphics.h" +#include "Elements.h" +#include "misc.h" + +#define CHANNELS ((int)(MAX_TEMP-73)/100+2) + +class Simulation; +class Renderer; +class Gravity; +class Air; + +struct Particle +{ + int type; + int life, ctype; + float x, y, vx, vy; + float temp; + float pavg[2]; + int flags; + int tmp; + int tmp2; + unsigned int dcolour; +}; +typedef struct Particle Particle; + +struct sign +{ + int x,y,ju; + char text[256]; +}; +typedef struct sign sign; + +struct part_type +{ + char *name; + pixel pcolors; + float advection; + float airdrag; + float airloss; + float loss; + float collision; + float gravity; + float diffusion; + float hotair; + int falldown; + int flammable; + int explosive; + int meltable; + int hardness; + int menu; + int enabled; + int weight; + int menusection; + float heat; + unsigned char hconduct; + char *descs; + char state; + unsigned int properties; + int (*update_func) (UPDATE_FUNC_ARGS); + int (*graphics_func) (GRAPHICS_FUNC_ARGS); +}; +typedef struct part_type part_type; + +struct part_transition +{ + float plv; // transition occurs if pv is lower than this + int plt; + float phv; // transition occurs if pv is higher than this + int pht; + float tlv; // transition occurs if t is lower than this + int tlt; + float thv; // transition occurs if t is higher than this + int tht; +}; +typedef struct part_transition part_transition; + +struct playerst +{ + char comm; //command cell + char pcomm; //previous command + int elem; //element power + float legs[16]; //legs' positions + float accs[8]; //accelerations + char spwn; //if stick man was spawned + unsigned int frames; //frames since last particle spawn - used when spawning LIGH +}; +typedef struct playerst playerst; + +struct wall_type +{ + pixel colour; + pixel eglow; // if emap set, add this to fire glow + int drawstyle; + const char *descs; +}; +typedef struct wall_type wall_type; + +struct gol_menu +{ + const char *name; + pixel colour; + int goltype; + const char *description; +}; +typedef struct gol_menu gol_menu; + +//#ifdef _cplusplus +class Simulation +{ +private: +public: + + Gravity * grav; + Air * air; + part_type ptypes[PT_NUM]; + part_transition ptransitions[PT_NUM]; + wall_type wtypes[UI_WALLCOUNT]; + gol_menu gmenu[NGOL]; + int goltype[NGOL]; + int grule[NGOL+1][10]; + playerst player; + playerst player2; + playerst fighters[256]; //255 is the maximum number of fighters + unsigned char fighcount; //Contains the number of fighters + int lighting_recreate; + int gravwl_timeout; + Particle portalp[CHANNELS][8][80]; + Particle emptyparticle; + int portal_rx[8]; + int portal_ry[8]; + int wireless[CHANNELS][2]; + char can_move[PT_NUM][PT_NUM]; + int parts_lastActiveIndex;// = NPART-1; + int pfree; + int NUM_PARTS; + int elementCount[PT_NUM]; + int ISWIRE; + sign * signs; + //Gol sim + int CGOL; + int ISGOL; + int GSPEED; + unsigned char gol[XRES][YRES]; + unsigned char gol2[XRES][YRES][NGOL+1]; + //Air sim + float (*vx)[XRES/CELL]; + float (*vy)[XRES/CELL]; + float (*pv)[XRES/CELL]; + float (*hv)[XRES/CELL]; + //Gravity sim + float *gravx;//gravx[(YRES/CELL) * (XRES/CELL)]; + float *gravy;//gravy[(YRES/CELL) * (XRES/CELL)]; + float *gravp;//gravp[(YRES/CELL) * (XRES/CELL)]; + float *gravmap;//gravmap[(YRES/CELL) * (XRES/CELL)]; + //Walls + unsigned char bmap[YRES/CELL][XRES/CELL]; + unsigned char emap[YRES/CELL][XRES/CELL]; + float fvx[YRES/CELL][XRES/CELL]; + float fvy[YRES/CELL][XRES/CELL]; + //Particles + Particle parts[NPART]; + int pmap[YRES][XRES]; + int photons[YRES][XRES]; + // + int gravityMode; + int airMode; + int ngrav_enable; + int legacy_enable; + int aheat_enable; + int VINE_MODE; + int water_equal_test; + int sys_pause; + int framerender; + int pretty_powder; + // + int sandcolour_r; + int sandcolour_g; + int sandcolour_b; //TODO: Make a single variable + //Stuff + int is_blocking(int t, int x, int y); + int is_boundary(int pt, int x, int y); + int find_next_boundary(int pt, int *x, int *y, int dm, int *em); + int pn_junction_sprk(int x, int y, int pt); + void photoelectric_effect(int nx, int ny); + unsigned direction_to_map(float dx, float dy, int t); + int do_move(int i, int x, int y, float nxf, float nyf); + int try_move(int i, int x, int y, int nx, int ny); + int eval_move(int pt, int nx, int ny, unsigned *rr); + void init_can_move(); + void create_cherenkov_photon(int pp); + void create_gain_photon(int pp); + void kill_part(int i); + int flood_prop(int x, int y, size_t propoffset, void * propvalue, int proptype); + int flood_prop_2(int x, int y, size_t propoffset, void * propvalue, int proptype, int parttype, char * bitmap); + int flood_water(int x, int y, int i, int originaly, int check); + void detach(int i); + void part_change_type(int i, int x, int y, int t); + int create_part_add_props(int p, int x, int y, int tv, int rx, int ry); + //int InCurrentBrush(int i, int j, int rx, int ry); + //int get_brush_flags(); + int create_part(int p, int x, int y, int t); + void delete_part(int x, int y, int flags); + int is_wire(int x, int y); + int is_wire_off(int x, int y); + void set_emap(int x, int y); + int parts_avg(int ci, int ni, int t); + void create_arc(int sx, int sy, int dx, int dy, int midpoints, int variance, int type, int flags); + int nearest_part(int ci, int t, int max_d); + void update_particles_i(int start, int inc); + void update_particles(); + 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 create_box(int x1, int y1, int x2, int y2, int c, int flags); + int flood_parts(int x, int y, int c, int cm, int bm, int flags); + int create_parts(int x, int y, int rx, int ry, int c, int flags); + void create_line(int x1, int y1, int x2, int y2, int rx, int ry, int c, int flags); + void *transform_save(void *odata, int *size, matrix2d transform, vector2d translate); + 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); + int get_normal(int pt, int x, int y, float dx, float dy, float *nx, float *ny); + int get_normal_interp(int pt, float x0, float y0, float dx, float dy, float *nx, float *ny); + void clear_sim(); + void UpdateParticles(); + Simulation(); +}; +//#endif + +#endif /* SIMULATION_H_ */ -- cgit v0.9.2-21-gd62e