diff options
28 files changed, 808 insertions, 174 deletions
diff --git a/src/cat/LegacyLuaAPI.cpp b/src/cat/LegacyLuaAPI.cpp index 293d45e..9c32ad5 100644 --- a/src/cat/LegacyLuaAPI.cpp +++ b/src/cat/LegacyLuaAPI.cpp @@ -1100,7 +1100,7 @@ int luatpt_reset_spark(lua_State* l) if (luacon_sim->parts[i].ctype >= 0 && luacon_sim->parts[i].ctype < PT_NUM) { luacon_sim->parts[i].type = luacon_sim->parts[i].ctype; - luacon_sim->parts[i].life = 0; + luacon_sim->parts[i].life = luacon_sim->parts[i].ctype = 0; } else luacon_sim->kill_part(i); diff --git a/src/cat/TPTScriptInterface.cpp b/src/cat/TPTScriptInterface.cpp index 21e93ab..e821559 100644 --- a/src/cat/TPTScriptInterface.cpp +++ b/src/cat/TPTScriptInterface.cpp @@ -255,16 +255,29 @@ AnyType TPTScriptInterface::tptS_set(std::deque<std::string> * words) //Selector int newValue; if(value.GetType() == TypeNumber) + { newValue = ((NumberType)value).Value(); + } else if(value.GetType() == TypeString) { - newValue = GetParticleType(((StringType)value).Value()); - if (newValue < 0 || newValue >= PT_NUM) + if (property.Value() == "temp") { - // TODO: add element CAKE to invalidate this - if (!strcasecmp(((StringType)value).Value().c_str(),"cake")) - throw GeneralException("Cake is a lie, not an element"); - throw GeneralException("Invalid element"); + std::string newString = ((StringType)value).Value(); + if (newString.at(newString.length()-1) == 'C') + newValue = atoi(newString.substr(0, newString.length()-1).c_str())+273; + else if (newString.at(newString.length()-1) == 'F') + newValue = (int)((atoi(newString.substr(0, newString.length()-1).c_str())-32.0f)*5/9+273.15f); + } + else + { + newValue = GetParticleType(((StringType)value).Value()); + if (newValue < 0 || newValue >= PT_NUM) + { + // TODO: add element CAKE to invalidate this + if (!strcasecmp(((StringType)value).Value().c_str(),"cake")) + throw GeneralException("Cake is a lie, not an element"); + throw GeneralException("Invalid element"); + } } } else diff --git a/src/client/GameSave.cpp b/src/client/GameSave.cpp index 52ad64b..ddb4ef4 100644 --- a/src/client/GameSave.cpp +++ b/src/client/GameSave.cpp @@ -960,12 +960,32 @@ void GameSave::readOPS(char * data, int dataLength) case PT_PSTN: if (savedVersion < 87 && particles[newIndex].ctype) particles[newIndex].life = 1; + break; case PT_STKM: case PT_STKM2: case PT_FIGH: if (savedVersion < 88 && particles[newIndex].ctype == OLD_SPC_AIR) particles[newIndex].ctype = SPC_AIR; + break; + case PT_FILT: + if (savedVersion < 89) + { + if (particles[newIndex].tmp<0 || particles[newIndex].tmp>3) + particles[newIndex].tmp = 6; + particles[newIndex].ctype = 0; + } + break; + case PT_QRTZ: + case PT_PQRT: + if (savedVersion < 89) + { + particles[newIndex].tmp2 = particles[newIndex].tmp; + particles[newIndex].tmp = particles[newIndex].ctype; + particles[newIndex].ctype = 0; + } + break; } + //note: PSv was used in version 77.0 and every version before, add something in PSv too if the element is that old newIndex++; } } @@ -1587,6 +1607,21 @@ void GameSave::readPSv(char * data, int dataLength) if (ver < 88) //fix air blowing stickmen if ((particles[i-1].type == PT_STKM || particles[i-1].type == PT_STKM2 || particles[i-1].type == PT_FIGH) && particles[i-1].ctype == OLD_SPC_AIR) particles[i-1].ctype == SPC_AIR; + if (ver < 89) + { + if (particles[i-1].type == PT_FILT) + { + if (particles[i-1].tmp<0 || particles[i-1].tmp>3) + particles[i-1].tmp = 6; + particles[i-1].ctype = 0; + } + else if (particles[i-1].type == PT_QRTZ || particles[i-1].type == PT_PQRT) + { + particles[i-1].tmp2 = particles[i-1].tmp; + particles[i-1].tmp = particles[i-1].ctype; + particles[i-1].ctype = 0; + } + } } } diff --git a/src/graphics/Graphics.cpp b/src/graphics/Graphics.cpp index d4e2956..c70344b 100644 --- a/src/graphics/Graphics.cpp +++ b/src/graphics/Graphics.cpp @@ -67,13 +67,10 @@ void VideoBuffer::Resize(int width, int height, bool resample, bool fixedRatio) else if(fixedRatio) { //Force proportions - float scaleFactor = 1.0f; - if(Height > newHeight) - scaleFactor = ((float)newHeight)/((float)Height); - if(Width > newWidth) - scaleFactor = ((float)newWidth)/((float)Width); - newWidth = ((float)Width)*scaleFactor; - newHeight = ((float)Height)*scaleFactor; + if(newWidth*Height > newHeight*Width) // same as nW/W > nH/H + newWidth = (int)(Width * (newHeight/(float)Height)); + else + newHeight = (int)(Height * (newWidth/(float)Width)); } if(resample) newBuffer = Graphics::resample_img(Buffer, Width, Height, newWidth, newHeight); @@ -589,7 +586,7 @@ int Graphics::textwidth(const char *s) return x-1; } -int Graphics::CharWidth(char c) +int Graphics::CharWidth(unsigned char c) { return font_data[font_ptrs[(int)c]]; } diff --git a/src/graphics/Graphics.h b/src/graphics/Graphics.h index 580f2c0..de1c2e8 100644 --- a/src/graphics/Graphics.h +++ b/src/graphics/Graphics.h @@ -203,7 +203,7 @@ public: //Font/text metrics static int CharIndexAtPosition(char *s, int positionX, int positionY); static int PositionAtCharIndex(char *s, int charIndex, int & positionX, int & positionY); - static int CharWidth(char c); + static int CharWidth(unsigned char c); static int textnwidth(char *s, int n); static void textnpos(char *s, int n, int w, int *cx, int *cy); static int textwidthx(char *s, int w); diff --git a/src/gui/game/GameController.cpp b/src/gui/game/GameController.cpp index b6d0560..a114b82 100644 --- a/src/gui/game/GameController.cpp +++ b/src/gui/game/GameController.cpp @@ -749,7 +749,7 @@ void GameController::ResetSpark() if (sim->parts[i].ctype >= 0 && sim->parts[i].ctype < PT_NUM && sim->elements[sim->parts[i].ctype].Enabled) { sim->parts[i].type = sim->parts[i].ctype; - sim->parts[i].life = 0; + sim->parts[i].ctype = sim->parts[i].life = 0; } else sim->kill_part(i); @@ -1389,6 +1389,16 @@ std::string GameController::ElementResolve(int type, int ctype) return ""; } +bool GameController::IsValidElement(int type) +{ + if(gameModel && gameModel->GetSimulation()) + { + return (type > 0 && type < PT_NUM && gameModel->GetSimulation()->elements[type].Enabled); + } + else + return false; +} + std::string GameController::WallName(int type) { if(gameModel && gameModel->GetSimulation() && gameModel->GetSimulation()->wtypes && type >= 0 && type < UI_WALLCOUNT) diff --git a/src/gui/game/GameController.h b/src/gui/game/GameController.h index d723ccb..b2a7d99 100644 --- a/src/gui/game/GameController.h +++ b/src/gui/game/GameController.h @@ -137,6 +137,7 @@ public: ui::Point PointTranslate(ui::Point point); ui::Point NormaliseBlockCoord(ui::Point point); std::string ElementResolve(int type, int ctype); + bool IsValidElement(int type); std::string WallName(int type); void ResetAir(); diff --git a/src/gui/game/GameView.cpp b/src/gui/game/GameView.cpp index f7fa6f5..1dad1f8 100644 --- a/src/gui/game/GameView.cpp +++ b/src/gui/game/GameView.cpp @@ -1473,6 +1473,13 @@ void GameView::OnKeyPress(int key, Uint16 character, bool shift, bool ctrl, bool else c->InvertAirSim(); break; + case ';': + if (ctrl) + { + c->SetReplaceModeFlags(c->GetReplaceModeFlags()^SPECIFIC_DELETE); + break; + } + //fancy case switch without break case SDLK_INSERT: c->SetReplaceModeFlags(c->GetReplaceModeFlags()^REPLACE_MODE); break; @@ -2062,16 +2069,25 @@ void GameView::OnDraw() ctype = sample.particle.tmp&0xFF; if(showDebug) { - if (sample.particle.type == PT_LAVA && ctype > 0 && ctype < PT_NUM) + if (sample.particle.type == PT_LAVA && c->IsValidElement(ctype)) sampleInfo << "Molten " << c->ElementResolve(ctype, -1); - else if ((sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) && ctype > 0 && ctype < PT_NUM) + else if ((sample.particle.type == PT_PIPE || sample.particle.type == PT_PPIP) && c->IsValidElement(ctype)) sampleInfo << c->ElementResolve(sample.particle.type, -1) << " with " << c->ElementResolve(ctype, (int)sample.particle.pavg[1]); else if (sample.particle.type == PT_LIFE) sampleInfo << c->ElementResolve(sample.particle.type, sample.particle.ctype); + else if (sample.particle.type == PT_FILT) + { + sampleInfo << c->ElementResolve(sample.particle.type, sample.particle.ctype); + const char* filtModes[] = {"set colour", "AND", "OR", "subtract colour", "red shift", "blue shift", "no effect", "XOR", "NOT"}; + if (sample.particle.tmp>=0 && sample.particle.tmp<=8) + sampleInfo << " (" << filtModes[sample.particle.tmp] << ")"; + else + sampleInfo << " (unknown mode)"; + } else { sampleInfo << c->ElementResolve(sample.particle.type, sample.particle.ctype); - if(ctype > 0 && ctype < PT_NUM) + if (c->IsValidElement(ctype)) sampleInfo << " (" << c->ElementResolve(ctype, -1) << ")"; else sampleInfo << " ()"; @@ -2094,7 +2110,9 @@ void GameView::OnDraw() sampleInfo << ", Temp: " << std::fixed << sample.particle.temp -273.15f; sampleInfo << ", Pressure: " << std::fixed << sample.AirPressure; } - if(sample.particle.type == PT_PHOT) + if (sample.particle.type == PT_PHOT || sample.particle.type == PT_BIZR || sample.particle.type == PT_BIZRG || sample.particle.type == PT_BIZRS) + wavelengthGfx = sample.particle.ctype; + if (sample.particle.type == PT_FILT && sample.particle.ctype) wavelengthGfx = sample.particle.ctype; } else if (sample.WallType) diff --git a/src/simulation/Simulation.cpp b/src/simulation/Simulation.cpp index c1cf22e..b090841 100644 --- a/src/simulation/Simulation.cpp +++ b/src/simulation/Simulation.cpp @@ -388,23 +388,23 @@ int Simulation::flood_prop_2(int x, int y, size_t propoffset, void * propvalue, } for (x=x1; x<=x2; x++) { - i = pmap[y][x]>>8; + i = pmap[y][x]; if (!i) - i = photons[y][x]>>8; + i = photons[y][x]; if (!i) continue; switch (proptype) { case StructProperty::Float: - *((float*)(((char*)&parts[i])+propoffset)) = *((float*)propvalue); + *((float*)(((char*)&parts[i>>8])+propoffset)) = *((float*)propvalue); break; case StructProperty::ParticleType: case StructProperty::Integer: - *((int*)(((char*)&parts[i])+propoffset)) = *((int*)propvalue); + *((int*)(((char*)&parts[i>>8])+propoffset)) = *((int*)propvalue); break; case StructProperty::UInteger: - *((unsigned int*)(((char*)&parts[i])+propoffset)) = *((unsigned int*)propvalue); + *((unsigned int*)(((char*)&parts[i>>8])+propoffset)) = *((unsigned int*)propvalue); break; default: @@ -2019,13 +2019,16 @@ void Simulation::init_can_move() } //a list of lots of things PHOT can move through // TODO: replace with property - for (movingType = 0; movingType < PT_NUM; movingType++) + for (destinationType = 0; destinationType < PT_NUM; destinationType++) { - if (movingType == PT_GLAS || movingType == PT_PHOT || movingType == PT_FILT || movingType == PT_INVIS - || movingType == PT_CLNE || movingType == PT_PCLN || movingType == PT_BCLN || movingType == PT_PBCN - || movingType == PT_WATR || movingType == PT_DSTW || movingType == PT_SLTW || movingType == PT_GLOW - || movingType == PT_ISOZ || movingType == PT_ISZS || movingType == PT_QRTZ || movingType == PT_PQRT) - can_move[PT_PHOT][movingType] = 2; + if (destinationType == PT_GLAS || destinationType == PT_PHOT || destinationType == PT_FILT || destinationType == PT_INVIS + || destinationType == PT_CLNE || destinationType == PT_PCLN || destinationType == PT_BCLN || destinationType == PT_PBCN + || destinationType == PT_WATR || destinationType == PT_DSTW || destinationType == PT_SLTW || destinationType == PT_GLOW + || destinationType == PT_ISOZ || destinationType == PT_ISZS || destinationType == PT_QRTZ || destinationType == PT_PQRT + || destinationType == PT_H2) + can_move[PT_PHOT][destinationType] = 2; + if (destinationType != PT_DMND && destinationType != PT_INSL && destinationType != PT_VOID && destinationType != PT_PVOD) + can_move[PT_PROT][destinationType] = 2; } //other special cases that weren't covered above @@ -2163,7 +2166,7 @@ int Simulation::try_move(int i, int x, int y, int nx, int ny) if ((r & 0xFF) < PT_NUM && elements[r&0xFF].HeatConduct && ((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)) { + else 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; } @@ -2192,63 +2195,64 @@ int Simulation::try_move(int i, int x, int y, int nx, int ny) 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) + if (parts[i].type == PT_PHOT) + { + if ((r&0xFF) == PT_GLOW) { - parts[r>>8].life = 120; - create_gain_photon(i); + if (!parts[r>>8].life && 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 + else if ((r&0xFF) == PT_FILT) + parts[i].ctype = Element_FILT::interactWavelengths(&parts[r>>8], parts[i].ctype); + else if ((r&0xFF) == PT_INVIS) + { + if (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; + } + } + else if ((r&0xFF)==PT_BIZR || (r&0xFF)==PT_BIZRG || (r&0xFF)==PT_BIZRS) + { + part_change_type(i, x, y, PT_ELEC); + parts[i].ctype = 0; + } + else if ((r&0xFF) == PT_H2) + { + part_change_type(i, x, y, PT_PROT); + parts[i].ctype = 0; } } - 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; + else if (parts[i].type == PT_NEUT) + { + if ((r&0xFF) == PT_GLAS) + if (rand() < RAND_MAX/10) + create_cherenkov_photon(i); } - if ((parts[i].type==PT_BIZR||parts[i].type==PT_BIZRG) && (r&0xFF)==PT_FILT) + else if (parts[i].type == PT_PROT) { - 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; + if ((r&0xFF) == PT_INVIS) + part_change_type(i, x, y, PT_NEUT); } - if (((r&0xFF)==PT_BIZR || (r&0xFF)==PT_BIZRG || (r&0xFF)==PT_BIZRS) && parts[i].type==PT_PHOT) + else if ((parts[i].type==PT_BIZR || parts[i].type==PT_BIZRG)) { - part_change_type(i, x, y, PT_ELEC); - parts[i].ctype = 0; + if ((r&0xFF) == PT_FILT) + parts[i].ctype = Element_FILT::interactWavelengths(&parts[r>>8], parts[i].ctype); } 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 (parts[i].type == PT_NEUT && (elements[r & 0xFF].Properties & PROP_NEUTABSORB)) - { - kill_part(i); - return 0; - } if ((r&0xFF)==PT_VOID || (r&0xFF)==PT_PVOD) //this is where void eats particles { //void ctype already checked in eval_move kill_part(i); return 0; } - if ((r&0xFF)==PT_BHOL || (r&0xFF)==PT_NBHL) //this is where blackhole eats particles + else if ((r&0xFF)==PT_BHOL || (r&0xFF)==PT_NBHL) //this is where blackhole eats particles { if (!legacy_enable) { @@ -2257,39 +2261,61 @@ int Simulation::try_move(int i, int x, int y, int nx, int ny) kill_part(i); return 0; } - if (((r&0xFF)==PT_WHOL||(r&0xFF)==PT_NWHL) && parts[i].type==PT_ANAR) //whitehole eats anar + else if (((r&0xFF)==PT_WHOL || (r&0xFF)==PT_NWHL)) //whitehole eats anar { - if (!legacy_enable) + if (parts[i].type == PT_ANAR) { - parts[r>>8].temp = restrict_flt(parts[r>>8].temp- (MAX_TEMP-parts[i].temp)/2, MIN_TEMP, MAX_TEMP); + if (!legacy_enable) + { + parts[r>>8].temp = restrict_flt(parts[r>>8].temp- (MAX_TEMP-parts[i].temp)/2, MIN_TEMP, MAX_TEMP); + } + kill_part(i); + return 0; } - kill_part(i); - return 0; } - if ((r&0xFF)==PT_DEUT && parts[i].type==PT_ELEC) + else if ((r&0xFF)==PT_DEUT) { - if(parts[r>>8].life < 6000) - parts[r>>8].life += 1; - parts[r>>8].temp = 0; - kill_part(i); - return 0; + if (parts[i].type == PT_ELEC) + { + if(parts[r>>8].life < 6000) + parts[r>>8].life += 1; + parts[r>>8].temp = 0; + kill_part(i); + return 0; + } } - if (((r&0xFF)==PT_VIBR || (r&0xFF)==PT_BVBR) && (elements[parts[i].type].Properties & TYPE_ENERGY)) + else if (((r&0xFF)==PT_VIBR || (r&0xFF)==PT_BVBR)) { - parts[r>>8].tmp += 20; - kill_part(i); - return 0; + if ((elements[parts[i].type].Properties & TYPE_ENERGY)) + { + parts[r>>8].tmp += 20; + kill_part(i); + return 0; + } } - if (parts[i].type==PT_CNCT && y<ny && (pmap[y+1][x]&0xFF)==PT_CNCT)//check below CNCT for another CNCT - return 0; + if (parts[i].type == PT_NEUT) + { + if (elements[r & 0xFF].Properties & PROP_NEUTABSORB) + { + kill_part(i); + return 0; + } + } + else if (parts[i].type == PT_CNCT) + { + if (y<ny && (pmap[y+1][x]&0xFF) == PT_CNCT) //check below CNCT for another CNCT + return 0; + } + else if(parts[i].type == PT_GBMB) + { + if (parts[i].life>0) + return 0; + } if ((bmap[y/CELL][x/CELL]==WL_EHOLE && !emap[y/CELL][x/CELL]) && !(bmap[ny/CELL][nx/CELL]==WL_EHOLE && !emap[ny/CELL][nx/CELL])) return 0; - if(parts[i].type==PT_GBMB&&parts[i].life>0) - 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 { @@ -2663,6 +2689,11 @@ int Simulation::create_part(int p, int x, int y, int tv) parts[index].ctype = PT_DUST; return index; } + if (p==-2 && ((elements[type].Properties & PROP_DRAWONCTYPE) || type==PT_CRAY)) + { + parts[index].ctype = PT_SPRK; + return index; + } if (!(type == PT_INST || (elements[type].Properties&PROP_CONDUCTS)) || parts[index].life!=0) return -1; if (p == -2 && type == PT_INST) @@ -2849,7 +2880,7 @@ int Simulation::create_part(int p, int x, int y, int tv) break; case PT_QRTZ: case PT_PQRT: - parts[i].tmp = (rand()%11); + parts[i].tmp2 = (rand()%11); break; case PT_CLST: parts[i].tmp = (rand()%7); @@ -2941,12 +2972,16 @@ int Simulation::create_part(int p, int x, int y, int tv) parts[i].ctype = 0x47FFFF; break; case PT_DTEC: - parts[i].tmp2 = 2; - break; case PT_TSNS: parts[i].tmp2 = 2; break; - case PT_FIGH:{ + case PT_VIRS: + case PT_VRSS: + case PT_VRSG: + parts[i].pavg[1] = 250; + break; + case PT_FIGH: + { unsigned char fcount = 0; while (fcount < 100 && fcount < (fighcount+1) && fighters[fcount].spwn==1) fcount++; if (fcount < 100 && fighters[fcount].spwn==0) @@ -2961,35 +2996,53 @@ int Simulation::create_part(int p, int x, int y, int tv) return i; } parts[i].type=0; - return -1;} - case PT_PHOT:{ + return -1; + } + case PT_PHOT: + { float a = (rand()%8) * 0.78540f; parts[i].life = 680; parts[i].ctype = 0x3FFFFFFF; parts[i].vx = 3.0f*cosf(a); parts[i].vy = 3.0f*sinf(a); - break;} - case PT_ELEC:{ + break; + } + case PT_ELEC: + { float a = (rand()%360)*3.14159f/180.0f; parts[i].life = 680; parts[i].vx = 2.0f*cosf(a); parts[i].vy = 2.0f*sinf(a); - break;} - case PT_NEUT:{ + break; + } + case PT_NEUT: + { float r = (rand()%128+128)/127.0f; float a = (rand()%360)*3.14159f/180.0f; parts[i].life = rand()%480+480; parts[i].vx = r*cosf(a); parts[i].vy = r*sinf(a); - break;} - case PT_TRON:{ + break; + } + case PT_PROT: + { + float a = (rand()%36)* 0.17453f; + parts[i].life = 680; + parts[i].vx = 2.0f*cosf(a); + parts[i].vy = 2.0f*sinf(a); + break; + } + case PT_TRON: + { int randhue = rand()%360; int randomdir = rand()%4; parts[i].tmp = 1|(randomdir<<5)|(randhue<<7);//set as a head and a direction parts[i].tmp2 = 4;//tail parts[i].life = 5; - break;} - case PT_LIGH:{ + break; + } + case PT_LIGH: + { float gx, gy, gsize; if (p!=-2) { @@ -3008,7 +3061,8 @@ int Simulation::create_part(int p, int x, int y, int tv) } parts[i].tmp = (((int)(atan2f(-gy, gx)*(180.0f/M_PI)))+rand()%40-20+360)%360; parts[i].tmp2 = 4; - break;} + break; + } default: break; } @@ -3762,7 +3816,7 @@ void Simulation::update_particles_i(int start, int inc) s = 1; //A fix for ice with ctype = 0 - if ((t==PT_ICEI || t==PT_SNOW) && (parts[i].ctype==0 || parts[i].ctype>=PT_NUM || parts[i].ctype==PT_ICEI || parts[i].ctype==PT_SNOW)) + if ((t==PT_ICEI || t==PT_SNOW) && (parts[i].ctype<=0 || parts[i].ctype>=PT_NUM || parts[i].ctype==PT_ICEI || parts[i].ctype==PT_SNOW || !elements[parts[i].ctype].Enabled)) parts[i].ctype = PT_WATR; if (ctemph>elements[t].HighTemperature && elements[t].HighTemperatureTransition>-1) @@ -3789,7 +3843,7 @@ void Simulation::update_particles_i(int start, int inc) #endif else if (t == PT_ICEI || t == PT_SNOW) { - if (parts[i].ctype < PT_NUM && parts[i].ctype != t) + if (parts[i].ctype > 0 && parts[i].ctype < PT_NUM && parts[i].ctype != t) { if (elements[parts[i].ctype].LowTemperatureTransition==t && pt<=elements[parts[i].ctype].LowTemperature) s = 0; @@ -3892,7 +3946,7 @@ void Simulation::update_particles_i(int start, int inc) } else if (t == PT_LAVA) { - if (parts[i].ctype>0 && parts[i].ctype<PT_NUM && parts[i].ctype!=PT_LAVA) + if (parts[i].ctype>0 && parts[i].ctype<PT_NUM && parts[i].ctype!=PT_LAVA && parts[i].ctype!=PT_LAVA && elements[parts[i].ctype].Enabled) { if (parts[i].ctype==PT_THRM&&pt>=elements[PT_BMTL].HighTemperature) s = 0; diff --git a/src/simulation/Simulation.h b/src/simulation/Simulation.h index 9c900ab..4c4ee95 100644 --- a/src/simulation/Simulation.h +++ b/src/simulation/Simulation.h @@ -70,7 +70,6 @@ public: bool gravWallChanged; //Portals and Wifi Particle portalp[CHANNELS][8][80]; - Particle emptyparticle; int portal_rx[8]; int portal_ry[8]; int wireless[CHANNELS][2]; diff --git a/src/simulation/elements/ACID.cpp b/src/simulation/elements/ACID.cpp index e078551..4ea94ff 100644 --- a/src/simulation/elements/ACID.cpp +++ b/src/simulation/elements/ACID.cpp @@ -48,7 +48,7 @@ Element_ACID::Element_ACID() //#TPT-Directive ElementHeader Element_ACID static int update(UPDATE_FUNC_ARGS) int Element_ACID::update(UPDATE_FUNC_ARGS) - { +{ int r, rx, ry, trade, np; for (rx=-2; rx<3; rx++) for (ry=-2; ry<3; ry++) @@ -95,7 +95,7 @@ int Element_ACID::update(UPDATE_FUNC_ARGS) } } } - for ( trade = 0; trade<2; trade ++) + for (trade = 0; trade<2; trade++) { rx = rand()%5-2; ry = rand()%5-2; @@ -109,8 +109,8 @@ int Element_ACID::update(UPDATE_FUNC_ARGS) int temp = parts[i].life - parts[r>>8].life; if (temp==1) { - parts[r>>8].life ++; - parts[i].life --; + parts[r>>8].life++; + parts[i].life--; } else if (temp>0) { @@ -126,7 +126,6 @@ int Element_ACID::update(UPDATE_FUNC_ARGS) //#TPT-Directive ElementHeader Element_ACID static int graphics(GRAPHICS_FUNC_ARGS) int Element_ACID::graphics(GRAPHICS_FUNC_ARGS) - { int s = cpart->life; if (s>75) s = 75; //These two should not be here. @@ -140,5 +139,4 @@ int Element_ACID::graphics(GRAPHICS_FUNC_ARGS) return 0; } - Element_ACID::~Element_ACID() {} diff --git a/src/simulation/elements/ARAY.cpp b/src/simulation/elements/ARAY.cpp index ac28834..16bff2d 100644 --- a/src/simulation/elements/ARAY.cpp +++ b/src/simulation/elements/ARAY.cpp @@ -98,7 +98,7 @@ int Element_ARAY::update(UPDATE_FUNC_ARGS) break; } } else if ((r&0xFF)==PT_FILT) {//get color if passed through FILT - colored = parts[r>>8].ctype; + colored = Element_FILT::interactWavelengths(&parts[r>>8], colored); //this if prevents BRAY from stopping on certain materials } else if ((r&0xFF)!=PT_STOR && (r&0xFF)!=PT_INWR && ((r&0xFF)!=PT_SPRK || parts[r>>8].ctype!=PT_INWR) && (r&0xFF)!=PT_ARAY && (r&0xFF)!=PT_WIFI && !((r&0xFF)==PT_SWCH && parts[r>>8].life>=10)) { if (nyy!=0 || nxx!=0) { diff --git a/src/simulation/elements/BCOL.cpp b/src/simulation/elements/BCOL.cpp index 3fb85af..cb53f6c 100644 --- a/src/simulation/elements/BCOL.cpp +++ b/src/simulation/elements/BCOL.cpp @@ -21,7 +21,7 @@ Element_BCOL::Element_BCOL() Flammable = 0; Explosive = 0; - Meltable = 5; + Meltable = 0; Hardness = 2; Weight = 90; diff --git a/src/simulation/elements/CRAY.cpp b/src/simulation/elements/CRAY.cpp index 2933dcf..002ed28 100644 --- a/src/simulation/elements/CRAY.cpp +++ b/src/simulation/elements/CRAY.cpp @@ -96,13 +96,14 @@ int Element_CRAY::update(UPDATE_FUNC_ARGS) else nr = sim->create_part(-1, x+nxi+nxx, y+nyi+nyy, parts[i].ctype); if (nr!=-1) { - parts[nr].dcolour = colored; + if (colored) + parts[nr].dcolour = colored; parts[nr].temp = parts[i].temp; if(!--partsRemaining) docontinue = 0; } } else if ((r&0xFF)==PT_FILT) { // get color if passed through FILT - colored = wavelengthToDecoColour(parts[r>>8].ctype); + colored = wavelengthToDecoColour(Element_FILT::getWavelengths(&parts[r>>8])); } else if ((r&0xFF) == PT_CRAY || nostop) { docontinue = 1; } else if(destroy && r && ((r&0xFF) != PT_DMND)) { diff --git a/src/simulation/elements/DTEC.cpp b/src/simulation/elements/DTEC.cpp index 8ecaf2e..ed894a2 100644 --- a/src/simulation/elements/DTEC.cpp +++ b/src/simulation/elements/DTEC.cpp @@ -73,6 +73,7 @@ int Element_DTEC::update(UPDATE_FUNC_ARGS) } } } + int photonWl = 0; for (rx=-rd; rx<rd+1; rx++) for (ry=-rd; ry<rd+1; ry++) if (x+rx>=0 && y+ry>=0 && x+rx<XRES && y+ry<YRES && (rx || ry)) @@ -84,7 +85,32 @@ int Element_DTEC::update(UPDATE_FUNC_ARGS) continue; if (parts[r>>8].type == parts[i].ctype && (parts[i].ctype != PT_LIFE || parts[i].tmp == parts[r>>8].ctype || !parts[i].tmp)) parts[i].life = 1; + if (parts[r>>8].type == PT_PHOT) + photonWl = parts[r>>8].ctype; } + if (photonWl) + { + int nx, ny; + for (rx=-1; rx<2; rx++) + for (ry=-1; ry<2; ry++) + if (BOUNDS_CHECK && (rx || ry)) + { + r = pmap[y+ry][x+rx]; + if (!r) + continue; + nx = x+rx; + ny = y+ry; + while ((r&0xFF)==PT_FILT) + { + parts[r>>8].ctype = photonWl; + nx += rx; + ny += ry; + if (nx<0 || ny<0 || nx>=XRES || ny>=YRES) + break; + r = pmap[ny][nx]; + } + } + } return 0; } diff --git a/src/simulation/elements/ELEC.cpp b/src/simulation/elements/ELEC.cpp index 8ab4af1..56e90b3 100644 --- a/src/simulation/elements/ELEC.cpp +++ b/src/simulation/elements/ELEC.cpp @@ -91,6 +91,7 @@ int Element_ELEC::update(UPDATE_FUNC_ARGS) sim->create_part(r>>8, x+rx, y+ry, PT_H2); return 1; case PT_NEUT: + case PT_PROT: // this is the correct reaction, not NEUT, but leaving NEUT in anyway sim->part_change_type(r>>8, x+rx, y+ry, PT_H2); parts[r>>8].life = 0; parts[r>>8].ctype = 0; @@ -124,8 +125,6 @@ int Element_ELEC::update(UPDATE_FUNC_ARGS) return 0; } - - //#TPT-Directive ElementHeader Element_ELEC static int graphics(GRAPHICS_FUNC_ARGS) int Element_ELEC::graphics(GRAPHICS_FUNC_ARGS) diff --git a/src/simulation/elements/EXOT.cpp b/src/simulation/elements/EXOT.cpp index df075e0..e2f6e41 100644 --- a/src/simulation/elements/EXOT.cpp +++ b/src/simulation/elements/EXOT.cpp @@ -47,11 +47,13 @@ Element_EXOT::Element_EXOT() } //#TPT-Directive ElementHeader Element_EXOT static int update(UPDATE_FUNC_ARGS) -int Element_EXOT::update(UPDATE_FUNC_ARGS) { +int Element_EXOT::update(UPDATE_FUNC_ARGS) +{ int r, rt, rx, ry, nb, rrx, rry, trade, tym; for (rx=-2; rx<=2; rx++) for (ry=-2; ry<=2; ry++) - if (BOUNDS_CHECK && (rx || ry)) { + if (BOUNDS_CHECK && (rx || ry)) + { r = pmap[y+ry][x+rx]; if (!r) continue; @@ -65,11 +67,14 @@ int Element_EXOT::update(UPDATE_FUNC_ARGS) { } else if (rt == PT_EXOT) { + if (parts[r>>8].ctype == PT_PROT) + parts[i].ctype = PT_PROT; if (parts[r>>8].life == 1500 && !(rand()%1000)) parts[i].life = 1500; } else if (rt == PT_LAVA) { + //turn molten TTAN or molten GOLD to molten VIBR if (parts[r>>8].ctype == PT_TTAN || parts[r>>8].ctype == PT_GOLD) { if (!(rand()%10)) @@ -79,66 +84,71 @@ int Element_EXOT::update(UPDATE_FUNC_ARGS) { return 1; } } + //molten VIBR will kill the leftover EXOT though, so the VIBR isn't killed later else if (parts[r>>8].ctype == PT_VIBR) { - if (1>rand()%1000) + if (!(rand()%1000)) { sim->kill_part(i); return 1; } } } - if ((parts[i].tmp>245) && (parts[i].life>1000)) + if (parts[i].tmp > 245 && parts[i].life > 1000) if (rt!=PT_EXOT && rt!=PT_BREC && rt!=PT_DMND && rt!=PT_CLNE && rt!=PT_PRTI && rt!=PT_PRTO && rt!=PT_PCLN && rt!=PT_VOID && rt!=PT_NBHL && rt!=PT_WARP) { sim->create_part(i, x, y, rt); - return 0; + return 1; } } + parts[i].tmp--; parts[i].tmp2--; - if (parts[i].tmp<1 || parts[i].tmp>250) + //reset tmp every 250 frames, gives EXOT it's slow flashing effect + if (parts[i].tmp < 1 || parts[i].tmp > 250) parts[i].tmp = 250; - if (parts[i].tmp2<1) + + if (parts[i].tmp2 < 1) parts[i].tmp2 = 1; - else if (parts[i].tmp2>6000) + else if (parts[i].tmp2 > 6000) { parts[i].tmp2 = 10000; - if (parts[i].life<1001) + if (parts[i].life < 1001) { sim->part_change_type(i, x, y, PT_WARP); return 0; } } - else if(parts[i].life<1001) + else if(parts[i].life < 1001) sim->pv[y/CELL][x/CELL] += (parts[i].tmp2*CFDS)/160000; + if (sim->pv[y/CELL][x/CELL]>200 && parts[i].temp>9000 && parts[i].tmp2>200) { parts[i].tmp2 = 6000; sim->part_change_type(i, x, y, PT_WARP); return 0; } - if (parts[i].tmp2>100) + if (parts[i].tmp2 > 100) { - for ( trade = 0; trade<9; trade ++) + for (trade = 0; trade < 9; trade++) { rx = rand()%5-2; ry = rand()%5-2; - if (x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES && (rx || ry)) + if (BOUNDS_CHECK && (rx || ry)) { r = pmap[y+ry][x+rx]; if (!r) continue; - if ((r&0xFF)==PT_EXOT && (parts[i].tmp2>parts[r>>8].tmp2) && parts[r>>8].tmp2>=0 )//diffusion + if ((r&0xFF)==PT_EXOT && (parts[i].tmp2 > parts[r>>8].tmp2) && parts[r>>8].tmp2 >= 0) //diffusion { tym = parts[i].tmp2 - parts[r>>8].tmp2; - if (tym ==1) + if (tym == 1) { - parts[r>>8].tmp2 ++; - parts[i].tmp2 --; + parts[r>>8].tmp2++; + parts[i].tmp2--; break; } - if (tym>0) + if (tym > 0) { parts[r>>8].tmp2 += tym/2; parts[i].tmp2 -= tym/2; @@ -148,7 +158,17 @@ int Element_EXOT::update(UPDATE_FUNC_ARGS) { } } } - if (parts[i].temp<273.15f) + if (parts[i].ctype == PT_PROT) + { + if (parts[i].temp < 50.0f) + { + sim->create_part(i, x, y, PT_CFLM); + return 1; + } + else + parts[i].temp -= 1.0f; + } + else if (parts[i].temp < 273.15f) { parts[i].vx = 0; parts[i].vy = 0; diff --git a/src/simulation/elements/FILT.cpp b/src/simulation/elements/FILT.cpp index d6b82f2..8ece142 100644 --- a/src/simulation/elements/FILT.cpp +++ b/src/simulation/elements/FILT.cpp @@ -48,21 +48,17 @@ Element_FILT::Element_FILT() //#TPT-Directive ElementHeader Element_FILT static int graphics(GRAPHICS_FUNC_ARGS) int Element_FILT::graphics(GRAPHICS_FUNC_ARGS) - { - int x, temp_bin = (int)((cpart->temp-273.0f)*0.025f); - if (temp_bin < 0) temp_bin = 0; - if (temp_bin > 25) temp_bin = 25; - cpart->ctype = 0x1F << temp_bin; + int x, wl = Element_FILT::getWavelengths(cpart); *colg = 0; *colb = 0; *colr = 0; for (x=0; x<12; x++) { - *colr += (cpart->ctype >> (x+18)) & 1; - *colb += (cpart->ctype >> x) & 1; + *colr += (wl >> (x+18)) & 1; + *colb += (wl >> x) & 1; } for (x=0; x<12; x++) - *colg += (cpart->ctype >> (x+9)) & 1; + *colg += (wl >> (x+9)) & 1; x = 624/(*colr+*colg+*colb+1); *cola = 127; *colr *= x; @@ -73,5 +69,68 @@ int Element_FILT::graphics(GRAPHICS_FUNC_ARGS) return 0; } +//#TPT-Directive ElementHeader Element_FILT static int interactWavelengths(Particle* cpart, int origWl) +// Returns the wavelengths in a particle after FILT interacts with it (e.g. a photon) +// cpart is the FILT particle, origWl the original wavelengths in the interacting particle +int Element_FILT::interactWavelengths(Particle* cpart, int origWl) +{ + const int mask = 0x3FFFFFFF; + int filtWl = getWavelengths(cpart); + switch (cpart->tmp) + { + case 0: + return filtWl; //Assign Colour + case 1: + return origWl & filtWl; //Filter Colour + case 2: + return origWl | filtWl; //Add Colour + case 3: + return origWl & (~filtWl); //Subtract colour of filt from colour of photon + case 4: + { + int shift = int((cpart->temp-273.0f)*0.025f); + if (shift<=0) shift = 1; + return (origWl << shift) & mask; // red shift + } + case 5: + { + int shift = int((cpart->temp-273.0f)*0.025f); + if (shift<=0) shift = 1; + return (origWl >> shift) & mask; // blue shift + } + case 6: + return origWl; // No change + case 7: + return origWl ^ filtWl; // XOR colours + case 8: + return (~origWl) & mask; // Invert colours + case 9: + { + int t1, t2, t3, r; + t1 = (origWl & 0x0000FF)+(rand()%5)-2; + t1 = ((origWl & 0x00FF00)>>8)+(rand()%5)-2; + t3 = ((origWl & 0xFF0000)>>16)+(rand()%5)-2; + return (origWl & 0xFF000000) | (t3<<16) | (t2<<8) | t1; + } + default: + return filtWl; + } +} + +//#TPT-Directive ElementHeader Element_FILT static int getWavelengths(Particle* cpart) +int Element_FILT::getWavelengths(Particle* cpart) +{ + if (cpart->ctype) + { + return cpart->ctype; + } + else + { + int temp_bin = (int)((cpart->temp-273.0f)*0.025f); + if (temp_bin < 0) temp_bin = 0; + if (temp_bin > 25) temp_bin = 25; + return (0x1F << temp_bin); + } +} Element_FILT::~Element_FILT() {} diff --git a/src/simulation/elements/PHOT.cpp b/src/simulation/elements/PHOT.cpp index e132d3d..4fe5bbe 100644 --- a/src/simulation/elements/PHOT.cpp +++ b/src/simulation/elements/PHOT.cpp @@ -88,6 +88,11 @@ int Element_PHOT::update(UPDATE_FUNC_ARGS) parts[i].ctype = 0x1F<<(rand()%26); parts[i].life++; //Delay death } + else if ((r&0xFF) == PT_FILT && parts[r>>8].tmp==9) + { + parts[i].vx += ((float)(rand()%1000-500))/1000.0f; + parts[i].vy += ((float)(rand()%1000-500))/1000.0f; + } } return 0; } diff --git a/src/simulation/elements/PIPE.cpp b/src/simulation/elements/PIPE.cpp index 14dbee0..ee1a21a 100644 --- a/src/simulation/elements/PIPE.cpp +++ b/src/simulation/elements/PIPE.cpp @@ -71,6 +71,8 @@ int Element_PIPE::update(UPDATE_FUNC_ARGS) { int r, rx, ry, np; int rnd, rndstore; + if ((parts[i].tmp&0xFF)>=PT_NUM || !sim->elements[parts[i].tmp&0xFF].Enabled) + parts[i].tmp &= ~0xFF; if (parts[i].tmp & PPIP_TMPFLAG_TRIGGERS) { int pause_changed = 0; @@ -285,7 +287,7 @@ int Element_PIPE::update(UPDATE_FUNC_ARGS) //#TPT-Directive ElementHeader Element_PIPE static int graphics(GRAPHICS_FUNC_ARGS) int Element_PIPE::graphics(GRAPHICS_FUNC_ARGS) { - if ((cpart->tmp&0xFF)>0 && (cpart->tmp&0xFF)<PT_NUM) + if ((cpart->tmp&0xFF)>0 && (cpart->tmp&0xFF)<PT_NUM && ren->sim->elements[(cpart->tmp&0xFF)].Enabled) { //Create a temp. particle and do a subcall. Particle tpart; diff --git a/src/simulation/elements/PROT.cpp b/src/simulation/elements/PROT.cpp new file mode 100644 index 0000000..4302244 --- /dev/null +++ b/src/simulation/elements/PROT.cpp @@ -0,0 +1,153 @@ +#include "simulation/Elements.h" +//#TPT-Directive ElementClass Element_PROT PT_PROT 173 +Element_PROT::Element_PROT() +{ + Identifier = "DEFAULT_PT_PROT"; + Name = "PROT"; + Colour = PIXPACK(0x990000); + MenuVisible = 1; + MenuSection = SC_NUCLEAR; + Enabled = 1; + + Advection = 0.0f; + AirDrag = 0.00f * CFDS; + AirLoss = 1.00f; + Loss = 1.00f; + Collision = -.99f; + Gravity = 0.0f; + Diffusion = 0.00f; + HotAir = 0.000f * CFDS; + Falldown = 0; + + Flammable = 0; + Explosive = 0; + Meltable = 0; + Hardness = 0; + + Weight = -1; + + Temperature = R_TEMP+273.15f; + HeatConduct = 61; + Description = "Protons. Transfer heat to materials, and removes sparks."; + + State = ST_GAS; + Properties = TYPE_ENERGY|PROP_LIFE_KILL; + + LowPressure = IPL; + LowPressureTransition = NT; + HighPressure = IPH; + HighPressureTransition = NT; + LowTemperature = ITL; + LowTemperatureTransition = NT; + HighTemperature = ITH; + HighTemperatureTransition = NT; + + Update = &Element_PROT::update; + Graphics = &Element_PROT::graphics; +} + +//#TPT-Directive ElementHeader Element_PROT static int update(UPDATE_FUNC_ARGS) +int Element_PROT::update(UPDATE_FUNC_ARGS) +{ + sim->pv[y/CELL][x/CELL] -= .003f; + int under = pmap[y][x]; + //set off explosives (only when hot because it wasn't as fun when it made an entire save explode) + if (parts[i].temp > 273.15f+500.0f && (sim->elements[under&0xFF].Flammable || sim->elements[under&0xFF].Explosive || (under&0xFF) == PT_BANG)) + { + sim->create_part(under>>8, x, y, PT_FIRE); + parts[under>>8].temp += restrict_flt(sim->elements[under&0xFF].Flammable*5, MIN_TEMP, MAX_TEMP); + sim->pv[y/CELL][x/CELL] += 1.00f; + } + //remove active sparks + else if ((under&0xFF) == PT_SPRK) + { + sim->part_change_type(under>>8, x, y, parts[under>>8].ctype); + parts[under>>8].life = 44+parts[under>>8].life; + parts[under>>8].ctype = 0; + } + //prevent inactive sparkable elements from being sparked + else if ((sim->elements[under&0xFF].Properties&PROP_CONDUCTS) && parts[under>>8].life <= 4) + { + parts[under>>8].life = 40+parts[under>>8].life; + } + else if ((under&0xFF) == PT_EXOT) + parts[under>>8].ctype = PT_PROT; + + //make temp of other things closer to it's own temperature. This will change temp of things that don't conduct, and won't change the PROT's temperature + if (under) + { + if ((under&0xFF) == PT_WIFI || (under&0xFF) == PT_PRTI || (under&0xFF) == PT_PRTO) + { + float change; + if (parts[i].temp<173.15f) change = -1000.0f; + else if (parts[i].temp<273.15f) change = -100.0f; + else if (parts[i].temp>473.15f) change = 1000.0f; + else if (parts[i].temp>373.15f) change = 100.0f; + else change = 0.0f; + parts[under>>8].temp = restrict_flt(parts[under>>8].temp+change, MIN_TEMP, MAX_TEMP); + } + else + { + parts[under>>8].temp = restrict_flt(parts[under>>8].temp-(parts[under>>8].temp-parts[i].temp)/4.0f, MIN_TEMP, MAX_TEMP); + } + } + //else, slowly kill it if it's not inside an element + else + parts[i].life--; + + //if this proton has collided with another last frame, change it into a heavier element + if (parts[i].tmp) + { + int newID, element; + if (parts[i].tmp > 4250) + element = PT_SING; //particle accelerators are known to create earth-destroying black holes + else if (parts[i].tmp > 275) + element = PT_PLUT; + else if (parts[i].tmp > 170) + element = PT_URAN; + else if (parts[i].tmp > 100) + element = PT_PLSM; + else if (parts[i].tmp > 40) + element = PT_O2; + else if (parts[i].tmp > 20) + element = PT_CO2; + else + element = PT_NBLE; + newID = sim->create_part(-1, x+rand()%3-1, y+rand()%3-1, element); + parts[newID].temp = restrict_flt(100.0f*parts[i].tmp, MIN_TEMP, MAX_TEMP); + sim->kill_part(i); + return 1; + } + //collide with other protons to make heavier materials + int ahead = sim->photons[y][x]; + if ((ahead>>8) != i && (ahead&0xFF) == PT_PROT) + { + float velocity1 = powf(parts[i].vx, 2.0f)+powf(parts[i].vy, 2.0f); + float velocity2 = powf(parts[ahead>>8].vx, 2.0f)+powf(parts[ahead>>8].vy, 2.0f); + float direction1 = atan2f(-parts[i].vy, parts[i].vx); + float direction2 = atan2f(-parts[ahead>>8].vy, parts[ahead>>8].vx); + float difference = direction1 - direction2; if (difference < 0) difference += 6.28319f; + + if (difference > 3.12659f && difference < 3.15659f && velocity1 + velocity2 > 10.0f) + { + parts[ahead>>8].tmp += (int)(velocity1 + velocity2); + sim->kill_part(i); + return 1; + } + } + return 0; +} + +//#TPT-Directive ElementHeader Element_PROT static int graphics(GRAPHICS_FUNC_ARGS) +int Element_PROT::graphics(GRAPHICS_FUNC_ARGS) +{ + *firea = 20; + *firer = 250; + *fireg = 128; + *fireb = 128; + + *pixel_mode |= FIRE_ADD; + return 1; +} + +Element_PROT::~Element_PROT() {} diff --git a/src/simulation/elements/PRTO.cpp b/src/simulation/elements/PRTO.cpp index 6ec11b4..1eae7ce 100644 --- a/src/simulation/elements/PRTO.cpp +++ b/src/simulation/elements/PRTO.cpp @@ -85,7 +85,7 @@ int Element_PRTO::update(UPDATE_FUNC_ARGS) sim->create_part(-1,x-1,y+1,PT_SPRK); sim->create_part(-1,x-1,y,PT_SPRK); sim->create_part(-1,x-1,y-1,PT_SPRK); - sim->portalp[parts[i].tmp][randomness][nnx] = sim->emptyparticle; + memset(&sim->portalp[parts[i].tmp][randomness][nnx], 0, sizeof(Particle)); break; } else if (sim->portalp[parts[i].tmp][randomness][nnx].type) @@ -132,7 +132,7 @@ int Element_PRTO::update(UPDATE_FUNC_ARGS) parts[np] = sim->portalp[parts[i].tmp][randomness][nnx]; parts[np].x = x+rx; parts[np].y = y+ry; - sim->portalp[parts[i].tmp][randomness][nnx] = sim->emptyparticle; + memset(&sim->portalp[parts[i].tmp][randomness][nnx], 0, sizeof(Particle)); break; } } diff --git a/src/simulation/elements/PSTN.cpp b/src/simulation/elements/PSTN.cpp index 6dda77f..998f7a2 100644 --- a/src/simulation/elements/PSTN.cpp +++ b/src/simulation/elements/PSTN.cpp @@ -167,7 +167,7 @@ int Element_PSTN::update(UPDATE_FUNC_ARGS) //#TPT-Directive ElementHeader Element_PSTN static int CanMoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int maxSize, int amount, bool retract, int block) int Element_PSTN::CanMoveStack(Simulation * sim, int stackX, int stackY, int directionX, int directionY, int maxSize, int amount, bool retract, int block) { - int posX, posY, r, spaces = 0, currentPos = 0; + int posX, posY, r, spaces = 0, currentPos = 0, num = 0; if (amount <= 0) return 0; for(posX = stackX, posY = stackY; currentPos < maxSize + amount && currentPos < XRES-1; posX += directionX, posY += directionY) { @@ -176,7 +176,7 @@ int Element_PSTN::CanMoveStack(Simulation * sim, int stackX, int stackY, int dir } r = sim->pmap[posY][posX]; if (sim->IsWallBlocking(posX, posY, 0) || (block && (r&0xFF) == block)) - return spaces; + return num; if(!r) { spaces++; tempParts[currentPos++] = -1; @@ -186,8 +186,9 @@ int Element_PSTN::CanMoveStack(Simulation * sim, int stackX, int stackY, int dir if(spaces < maxSize && currentPos < maxSize && (!retract || ((r&0xFF) == PT_FRME) && posX == stackX && posY == stackY)) tempParts[currentPos++] = r>>8; else - return spaces; + return num; } + num++; } if (spaces) return currentPos; diff --git a/src/simulation/elements/QRTZ.cpp b/src/simulation/elements/QRTZ.cpp index 5eec6d6..b399662 100644 --- a/src/simulation/elements/QRTZ.cpp +++ b/src/simulation/elements/QRTZ.cpp @@ -60,7 +60,7 @@ int Element_QRTZ::update(UPDATE_FUNC_ARGS) } } // absorb SLTW - if (parts[i].ctype!=-1) + if (parts[i].tmp != -1) for (rx=-1; rx<2; rx++) for (ry=-1; ry<2; ry++) if (BOUNDS_CHECK && (rx || ry)) @@ -71,15 +71,15 @@ int Element_QRTZ::update(UPDATE_FUNC_ARGS) else if ((r&0xFF)==PT_SLTW && !(rand()%500)) { sim->kill_part(r>>8); - parts[i].ctype ++; + parts[i].tmp++; } } // grow and diffuse - if (parts[i].ctype>0) + if (parts[i].tmp > 0) { - bool stopgrow=false; + bool stopgrow = false; int rnd, sry, srx; - for ( trade = 0; trade<9; trade ++) + for (trade = 0; trade < 9; trade++) { rnd = rand()%0x3FF; rx = (rnd%5)-2; @@ -91,20 +91,20 @@ int Element_QRTZ::update(UPDATE_FUNC_ARGS) { if (!stopgrow)//try to grow { - if (!pmap[y+sry][x+srx] && parts[i].ctype!=0) + if (!pmap[y+sry][x+srx] && parts[i].tmp!=0) { np = sim->create_part(-1,x+srx,y+sry,PT_QRTZ); if (np>-1) { - parts[np].tmp = parts[i].tmp; - parts[i].ctype--; + parts[np].tmp2 = parts[i].tmp2; + parts[i].tmp--; if (rand()%2) { - parts[np].ctype=-1;//dead qrtz + parts[np].tmp=-1;//dead qrtz } - else if (!parts[i].ctype && !(rand()%15)) + else if (!parts[i].tmp && !(rand()%15)) { - parts[i].ctype=-1; + parts[i].tmp=-1; } stopgrow=true; } @@ -114,19 +114,19 @@ int Element_QRTZ::update(UPDATE_FUNC_ARGS) r = pmap[y+ry][x+rx]; if (!r) continue; - else if ((r&0xFF)==PT_QRTZ && (parts[i].ctype>parts[r>>8].ctype) && parts[r>>8].ctype>=0) + else if ((r&0xFF)==PT_QRTZ && (parts[i].tmp>parts[r>>8].tmp) && parts[r>>8].tmp>=0) { - tmp = parts[i].ctype - parts[r>>8].ctype; + tmp = parts[i].tmp - parts[r>>8].tmp; if (tmp ==1) { - parts[r>>8].ctype ++; - parts[i].ctype --; + parts[r>>8].tmp++; + parts[i].tmp--; break; } if (tmp>0) { - parts[r>>8].ctype += tmp/2; - parts[i].ctype -= tmp/2; + parts[r>>8].tmp += tmp/2; + parts[i].tmp -= tmp/2; break; } } @@ -141,7 +141,7 @@ int Element_QRTZ::update(UPDATE_FUNC_ARGS) int Element_QRTZ::graphics(GRAPHICS_FUNC_ARGS) //QRTZ and PQRT { - int t = cpart->type, z = cpart->tmp - 5;//speckles! + int t = cpart->type, z = cpart->tmp2 - 5;//speckles! /*if (cpart->temp>(ptransitions[t].thv-800.0f))//hotglow for quartz { float frequency = 3.1415/(2*ptransitions[t].thv-(ptransitions[t].thv-800.0f)); diff --git a/src/simulation/elements/SOAP.cpp b/src/simulation/elements/SOAP.cpp index de7055d..fb88287 100644 --- a/src/simulation/elements/SOAP.cpp +++ b/src/simulation/elements/SOAP.cpp @@ -28,7 +28,7 @@ Element_SOAP::Element_SOAP() Temperature = R_TEMP-2.0f +273.15f; HeatConduct = 29; - Description = "Soap. Creates bubbles. Washes off deco color."; + Description = "Soap. Creates bubbles, washes off deco color, and cures virus."; State = ST_LIQUID; Properties = TYPE_LIQUID|PROP_NEUTPENETRATE|PROP_LIFE_DEC; diff --git a/src/simulation/elements/VIRS.cpp b/src/simulation/elements/VIRS.cpp new file mode 100644 index 0000000..a4a8800 --- /dev/null +++ b/src/simulation/elements/VIRS.cpp @@ -0,0 +1,145 @@ +#include "simulation/Elements.h" +//#TPT-Directive ElementClass Element_VIRS PT_VIRS 174 +Element_VIRS::Element_VIRS() +{ + Identifier = "DEFAULT_PT_VIRS"; + Name = "VIRS"; + Colour = PIXPACK(0xFE11F6); + MenuVisible = 1; + MenuSection = SC_LIQUID; + Enabled = 1; + + Advection = 0.6f; + AirDrag = 0.01f * CFDS; + AirLoss = 0.98f; + Loss = 0.95f; + Collision = 0.0f; + Gravity = 0.1f; + Diffusion = 0.00f; + HotAir = 0.000f * CFDS; + Falldown = 2; + + Flammable = 100; + Explosive = 0; + Meltable = 0; + Hardness = 20; + + Weight = 31; + + Temperature = 72.0f + 273.15f; + HeatConduct = 251; + Description = "Virus. Turns everything it touches into virus."; + + State = ST_LIQUID; + Properties = TYPE_LIQUID|PROP_DEADLY; + + LowPressure = IPL; + LowPressureTransition = NT; + HighPressure = IPH; + HighPressureTransition = NT; + LowTemperature = 305.0f; + LowTemperatureTransition = PT_VRSS; + HighTemperature = 673.0f; + HighTemperatureTransition = PT_VRSG; + + Update = &Element_VIRS::update; + +} + +//#TPT-Directive ElementHeader Element_VIRS static int update(UPDATE_FUNC_ARGS) +int Element_VIRS::update(UPDATE_FUNC_ARGS) +{ + //pavg[0] measures how many frames until it is cured (0 if still actively spreading and not being cured) + //pavg[1] measures how many frames until it dies + int r, rx, ry, rndstore = rand(); + if (parts[i].pavg[0]) + { + parts[i].pavg[0] -= (rndstore&0x1) ? 0:1; + //has been cured, so change back into the original element + if (!parts[i].pavg[0]) + { + sim->part_change_type(i,x,y,parts[i].tmp2); + parts[i].tmp2 = 0; + parts[i].pavg[0] = 0; + parts[i].pavg[1] = 0; + return 0; + } + } + //decrease pavg[1] so it slowly dies + if (parts[i].pavg[1] > 0) + { + if (((rndstore>>1)&0xD) < 1) + { + parts[i].pavg[1]--; + //if pavg[1] is now 0 and it's not in the process of being cured, kill it + if (!parts[i].pavg[1] && !parts[i].pavg[0]) + { + sim->kill_part(i); + return 1; + } + } + } + + //none of the things in the below loop happen while virus is being cured + if (parts[i].pavg[0]) + return 0; + + for (rx=-1; rx<2; rx++) + { + //reset rndstore, one random can last through 3 locations and reduce rand() calling by up to 6x as much + rndstore = rand(); + for (ry=-1; ry<2; ry++) + { + if (BOUNDS_CHECK && (rx || ry)) + { + r = pmap[y+ry][x+rx]; + if (!r) + continue; + + //spread "being cured" state + if (((r&0xFF) == PT_VIRS || (r&0xFF) == PT_VRSS || (r&0xFF) == PT_VRSG) && parts[r>>8].pavg[0]) + { + parts[i].pavg[0] = parts[r>>8].pavg[0] + (((rndstore&0x7)>>1) ? 2:1); + rndstore = rndstore >> 3; + return 0; + } + //soap cures virus + else if ((r&0xFF) == PT_SOAP) + { + parts[i].pavg[0] += 10; + if (!((rndstore&0x7)>>1)) + sim->kill_part(r>>8); + return 0; + } + //transforms things into virus here + else if ((r&0xFF) != PT_VIRS && (r&0xFF) != PT_VRSS && (r&0xFF) != PT_VRSG && (r&0xFF) != PT_DMND) + { + if (!((rndstore&0xF)>>1)) + { + parts[r>>8].tmp2 = (r&0xFF); + parts[r>>8].pavg[0] = 0; + if (parts[i].pavg[1]) + parts[r>>8].pavg[1] = parts[i].pavg[1] + ((rndstore>>4) ? 1:0); + else + parts[r>>8].pavg[1] = 0; + if (parts[r>>8].temp < 305.0f) + sim->part_change_type(r>>8,x,y,PT_VRSS); + else if (parts[r>>8].temp > 673.0f) + sim->part_change_type(r>>8,x,y,PT_VRSG); + else + sim->part_change_type(r>>8,x,y,PT_VIRS); + } + rndstore = rndstore >> 5; + } + //protons make VIRS last forever + else if ((sim->photons[y+ry][x+rx]&0xFF) == PT_PROT) + { + parts[i].pavg[1] = 0; + } + } + } + } + return 0; +} + +Element_VIRS::~Element_VIRS() {} diff --git a/src/simulation/elements/VRSG.cpp b/src/simulation/elements/VRSG.cpp new file mode 100644 index 0000000..8c699d7 --- /dev/null +++ b/src/simulation/elements/VRSG.cpp @@ -0,0 +1,49 @@ +#include "simulation/Elements.h" +//#TPT-Directive ElementClass Element_VRSG PT_VRSG 176 +Element_VRSG::Element_VRSG() +{ + Identifier = "DEFAULT_PT_VRSG"; + Name = "VRSG"; + Colour = PIXPACK(0xFE68FE); + MenuVisible = 0; + MenuSection = SC_GAS; + Enabled = 1; + + Advection = 1.0f; + AirDrag = 0.01f * CFDS; + AirLoss = 0.99f; + Loss = 0.30f; + Collision = -0.1f; + Gravity = 0.0f; + Diffusion = 0.75f; + HotAir = 0.000f * CFDS; + Falldown = 0; + + Flammable = 500; + Explosive = 0; + Meltable = 0; + Hardness = 0; + + Weight = 1; + + Temperature = 522.0f + 273.15f; + HeatConduct = 251; + Description = "Gas Virus. Turns everything it touches into virus."; + + State = ST_GAS; + Properties = TYPE_GAS|PROP_DEADLY; + + LowPressure = IPL; + LowPressureTransition = NT; + HighPressure = IPH; + HighPressureTransition = NT; + LowTemperature = 673.0f; + LowTemperatureTransition = PT_VIRS; + HighTemperature = ITH; + HighTemperatureTransition = NT; + + Update = &Element_VIRS::update; + +} + +Element_VRSG::~Element_VRSG() {} diff --git a/src/simulation/elements/VRSS.cpp b/src/simulation/elements/VRSS.cpp new file mode 100644 index 0000000..903a5f7 --- /dev/null +++ b/src/simulation/elements/VRSS.cpp @@ -0,0 +1,49 @@ +#include "simulation/Elements.h" +//#TPT-Directive ElementClass Element_VRSS PT_VRSS 175 +Element_VRSS::Element_VRSS() +{ + Identifier = "DEFAULT_PT_VRSS"; + Name = "VRSS"; + Colour = PIXPACK(0xD408CD); + MenuVisible = 0; + MenuSection = SC_SOLIDS; + Enabled = 1; + + Advection = 0.0f; + AirDrag = 0.00f * CFDS; + AirLoss = 0.90f; + Loss = 0.00f; + Collision = 0.0f; + Gravity = 0.0f; + Diffusion = 0.00f; + HotAir = 0.000f * CFDS; + Falldown = 0; + + Flammable = 5; + Explosive = 0; + Meltable = 0; + Hardness = 1; + + Weight = 100; + + Temperature = R_TEMP+ 273.15f; + HeatConduct = 251; + Description = "Solid Virus. Turns everything it touches into virus."; + + State = ST_SOLID; + Properties = TYPE_SOLID|PROP_DEADLY; + + LowPressure = IPL; + LowPressureTransition = NT; + HighPressure = IPH; + HighPressureTransition = NT; + LowTemperature = ITL; + LowTemperatureTransition = NT; + HighTemperature = 305.0f; + HighTemperatureTransition = PT_VIRS; + + Update = &Element_VIRS::update; + +} + +Element_VRSS::~Element_VRSS() {} |
