summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacob1 <jfu614@gmail.com>2012-12-06 16:01:46 (GMT)
committer jacob1 <jfu614@gmail.com>2012-12-06 16:01:46 (GMT)
commit122599763ef9827d7aadc0fe0295c2fbc96e82ab (patch)
treedcf0a21b20cd38a12dee93d9db6115da6c0fdb35 /src
parent2d7ac84c1dca8521f41cf023774b7a90e300b3bf (diff)
parent9bf5eeeef919260458637e84f3388b4d7d8204c5 (diff)
downloadpowder-122599763ef9827d7aadc0fe0295c2fbc96e82ab.zip
powder-122599763ef9827d7aadc0fe0295c2fbc96e82ab.tar.gz
Merge remote-tracking branch 'origin/master'
Diffstat (limited to 'src')
-rw-r--r--src/Config.h6
-rw-r--r--src/Misc.h7
-rw-r--r--src/client/Client.cpp8
-rw-r--r--src/client/ThumbnailBroker.cpp90
-rw-r--r--src/client/ThumbnailBroker.h3
-rw-r--r--src/game/BitmapBrush.h96
-rw-r--r--src/game/Brush.h2
-rw-r--r--src/game/GameController.cpp9
-rw-r--r--src/game/GameController.h1
-rw-r--r--src/game/GameModel.cpp21
-rw-r--r--src/game/GameView.cpp4
-rw-r--r--src/interface/Button.cpp44
-rw-r--r--src/interface/Button.h4
-rw-r--r--src/simulation/elements/CLST.cpp4
-rw-r--r--src/simulation/elements/SWCH.cpp2
-rw-r--r--src/simulation/elements/VIBR.cpp4
16 files changed, 260 insertions, 45 deletions
diff --git a/src/Config.h b/src/Config.h
index 44ca23f..8ed2075 100644
--- a/src/Config.h
+++ b/src/Config.h
@@ -11,8 +11,10 @@
#ifdef WIN
#define PATH_SEP "\\"
+#define PATH_SEP_CHAR '\\'
#else
#define PATH_SEP "/"
+#define PATH_SEP_CHAR '/'
#endif
//VersionInfoStart
@@ -25,7 +27,7 @@
#endif
#ifndef BUILD_NUM
-#define BUILD_NUM 249
+#define BUILD_NUM 250
#endif
#ifndef SNAPSHOT_ID
@@ -91,6 +93,8 @@
#define STAMPS_DIR "stamps"
+#define BRUSH_DIR "Brushes"
+
#define APPDATA_SUBDIR "\\HardWIRED"
//Number of unique thumbnails to have in cache at one time
diff --git a/src/Misc.h b/src/Misc.h
index cfac841..5ab6cf5 100644
--- a/src/Misc.h
+++ b/src/Misc.h
@@ -26,6 +26,13 @@ static char hex[] = "0123456789ABCDEF";
char *exe_name(void);
+//Linear interpolation
+template <typename T> inline T LinearInterpolate(T val1, T val2, T lowerCoord, T upperCoord, T coord)
+{
+ if(lowerCoord == upperCoord) return val1;
+ return (((val2 - val1) / (upperCoord - lowerCoord)) * (coord - lowerCoord)) + val1;
+}
+
//Signum function
int isign(float i);
diff --git a/src/client/Client.cpp b/src/client/Client.cpp
index 99c6b5b..fb14050 100644
--- a/src/client/Client.cpp
+++ b/src/client/Client.cpp
@@ -140,7 +140,7 @@ void Client::Initialise(std::string proxyString)
stampsLib.close();
//Begin version check
- versionCheckRequest = http_async_req_start(NULL, SERVER "/Startup.json", NULL, 0, 1);
+ versionCheckRequest = http_async_req_start(NULL, SERVER "/Startup.json", NULL, 0, 0);
if(authUser.ID)
{
@@ -367,6 +367,9 @@ std::vector<std::string> Client::DirectorySearch(std::string directory, std::str
std::vector<std::string> Client::DirectorySearch(std::string directory, std::string search, std::vector<std::string> extensions)
{
//Get full file listing
+ //Normalise directory string, ensure / or \ is present
+ if(*directory.rbegin() != '/' && *directory.rbegin() != '\\')
+ directory += PATH_SEP;
std::vector<std::string> directoryList;
#if defined(WIN) && !defined(__GNUC__)
//Windows
@@ -717,6 +720,7 @@ void Client::WritePrefs()
void Client::Shutdown()
{
+ ThumbnailBroker::Ref().Shutdown();
ClearThumbnailRequests();
http_done();
@@ -1824,7 +1828,7 @@ Thumbnail * Client::GetThumbnail(int saveID, int saveDate)
{
if(!activeThumbRequests[i])
{
- activeThumbRequests[i] = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 1);
+ activeThumbRequests[i] = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 0);
activeThumbRequestTimes[i] = currentTime;
activeThumbRequestCompleteTimes[i] = 0;
activeThumbRequestIDs[i] = idString;
diff --git a/src/client/ThumbnailBroker.cpp b/src/client/ThumbnailBroker.cpp
index e884a98..92ccfd8 100644
--- a/src/client/ThumbnailBroker.cpp
+++ b/src/client/ThumbnailBroker.cpp
@@ -19,6 +19,9 @@ ThumbnailBroker::ThumbnailBroker()
//listenersMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_init (&listenersMutex, NULL);
+
+
+ pthread_mutex_init (&runningMutex, NULL);
}
ThumbnailBroker::~ThumbnailBroker()
@@ -26,6 +29,45 @@ ThumbnailBroker::~ThumbnailBroker()
}
+void ThumbnailBroker::assureRunning()
+{
+ pthread_mutex_lock(&runningMutex);
+ bool running = thumbnailQueueRunning;
+ thumbnailQueueRunning = true;
+ pthread_mutex_unlock(&runningMutex);
+
+ if(!running)
+ {
+#ifdef DEBUG
+ std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl;
+#endif
+ pthread_create(&thumbnailQueueThread, 0, &ThumbnailBroker::thumbnailQueueProcessHelper, this);
+ }
+}
+
+void ThumbnailBroker::Shutdown()
+{
+ pthread_mutex_lock(&runningMutex);
+ if(thumbnailQueueRunning)
+ {
+ thumbnailQueueRunning = false;
+ pthread_mutex_unlock(&runningMutex);
+ pthread_join(thumbnailQueueThread, NULL);
+ }
+ else
+ pthread_mutex_unlock(&runningMutex);
+
+
+ for (std::list<ThumbnailRequest>::iterator iter = currentRequests.begin(), end = currentRequests.end(); iter != end; ++iter)
+ {
+ ThumbnailRequest req = *iter;
+ if(req.HTTPContext)
+ {
+ http_async_req_close(req.HTTPContext);
+ }
+ }
+}
+
void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, int width, int height, ThumbnailListener * tListener)
{
RenderThumbnail(gameSave, true, true, width, height, tListener);
@@ -35,36 +77,20 @@ void ThumbnailBroker::RenderThumbnail(GameSave * gameSave, bool decorations, boo
{
AttachThumbnailListener(tListener);
pthread_mutex_lock(&thumbnailQueueMutex);
- bool running = thumbnailQueueRunning;
- thumbnailQueueRunning = true;
renderRequests.push_back(ThumbRenderRequest(new GameSave(*gameSave), decorations, fire, width, height, ListenerHandle(tListener->ListenerRand, tListener)));
pthread_mutex_unlock(&thumbnailQueueMutex);
- if(!running)
- {
-#ifdef DEBUG
- std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl;
-#endif
- pthread_create(&thumbnailQueueThread, 0, &ThumbnailBroker::thumbnailQueueProcessHelper, this);
- }
+ assureRunning();
}
void ThumbnailBroker::RetrieveThumbnail(int saveID, int saveDate, int width, int height, ThumbnailListener * tListener)
{
AttachThumbnailListener(tListener);
pthread_mutex_lock(&thumbnailQueueMutex);
- bool running = thumbnailQueueRunning;
- thumbnailQueueRunning = true;
thumbnailRequests.push_back(ThumbnailRequest(saveID, saveDate, width, height, ListenerHandle(tListener->ListenerRand, tListener)));
pthread_mutex_unlock(&thumbnailQueueMutex);
- if(!running)
- {
-#ifdef DEBUG
- std::cout << typeid(*this).name() << " Starting background thread for new " << __FUNCTION__ << " request" << std::endl;
-#endif
- pthread_create(&thumbnailQueueThread, 0, &ThumbnailBroker::thumbnailQueueProcessHelper, this);
- }
+ assureRunning();
}
void * ThumbnailBroker::thumbnailQueueProcessHelper(void * ref)
@@ -97,17 +123,33 @@ void ThumbnailBroker::FlushThumbQueue()
void ThumbnailBroker::thumbnailQueueProcessTH()
{
time_t lastAction = time(NULL);
+ pthread_mutex_lock(&runningMutex);
+ thumbnailQueueRunning = true;
+ pthread_mutex_unlock(&runningMutex);
while(true)
{
//Shutdown after 2 seconds of idle
if(time(NULL) - lastAction > 2)
{
- pthread_mutex_lock(&thumbnailQueueMutex);
- thumbnailQueueRunning = false;
- pthread_mutex_unlock(&thumbnailQueueMutex);
+#ifdef DEBUG
+ std::cout << typeid(*this).name() << " Idle shutdown" << std::endl;
+#endif
+ break;
+ }
+
+
+ pthread_mutex_lock(&runningMutex);
+ bool running = thumbnailQueueRunning;
+ pthread_mutex_unlock(&runningMutex);
+ if(!running)
+ {
+#ifdef DEBUG
+ std::cout << typeid(*this).name() << " Requested shutdown" << std::endl;
+#endif
break;
}
+
//Renderer
pthread_mutex_lock(&thumbnailQueueMutex);
if(renderRequests.size())
@@ -220,7 +262,7 @@ void ThumbnailBroker::thumbnailQueueProcessTH()
std::cout << typeid(*this).name() << " Creating new request for " << req.ID.SaveID << ":" << req.ID.SaveDate << std::endl;
#endif
- req.HTTPContext = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 1);
+ req.HTTPContext = http_async_req_start(NULL, (char *)urlStream.str().c_str(), NULL, 0, 0);
req.RequestTime = time(NULL);
currentRequests.push_back(req);
}
@@ -252,7 +294,6 @@ void ThumbnailBroker::thumbnailQueueProcessTH()
char * data;
int status, data_size, imgw, imgh;
data = http_async_req_stop(req.HTTPContext, &status, &data_size);
- free(req.HTTPContext);
if (status == 200 && data)
{
@@ -307,6 +348,9 @@ void ThumbnailBroker::thumbnailQueueProcessTH()
}
}
+ pthread_mutex_lock(&runningMutex);
+ thumbnailQueueRunning = false;
+ pthread_mutex_unlock(&runningMutex);
}
void ThumbnailBroker::RetrieveThumbnail(int saveID, int width, int height, ThumbnailListener * tListener)
diff --git a/src/client/ThumbnailBroker.h b/src/client/ThumbnailBroker.h
index ba6d3ae..5160479 100644
--- a/src/client/ThumbnailBroker.h
+++ b/src/client/ThumbnailBroker.h
@@ -77,6 +77,7 @@ private:
pthread_mutex_t thumbnailQueueMutex;
pthread_mutex_t listenersMutex;
+ pthread_mutex_t runningMutex;
pthread_t thumbnailQueueThread;
bool thumbnailQueueRunning;
std::deque<ThumbnailRequest> thumbnailRequests;
@@ -91,10 +92,12 @@ private:
static void * thumbnailQueueProcessHelper(void * ref);
void thumbnailQueueProcessTH();
+ void assureRunning();
public:
ThumbnailBroker();
virtual ~ThumbnailBroker();
+ void Shutdown();
void FlushThumbQueue();
void RenderThumbnail(GameSave * gameSave, bool decorations, bool fire, int width, int height, ThumbnailListener * tListener);
diff --git a/src/game/BitmapBrush.h b/src/game/BitmapBrush.h
new file mode 100644
index 0000000..e1c0445
--- /dev/null
+++ b/src/game/BitmapBrush.h
@@ -0,0 +1,96 @@
+/*
+ * BitmapBrush.h
+ *
+ * Created on: Nov 18, 2012
+ * Author: Simon Robertshaw
+ */
+
+#ifndef BTIMAPBRUSH_H_
+#define BTIMAPBRUSH_H_
+
+#include <vector>
+#include <cmath>
+#include "Brush.h"
+
+class BitmapBrush: public Brush
+{
+protected:
+ ui::Point origSize;
+ unsigned char * origBitmap;
+public:
+ BitmapBrush(std::vector<unsigned char> newBitmap, ui::Point rectSize_):
+ Brush(ui::Point(0, 0)),
+ origSize(0, 0)
+ {
+ ui::Point newSize = rectSize_;
+
+ //Ensure the rect has odd dimentions so we can pull an integer radius with a 1x1 centre
+ if(!(newSize.X % 2))
+ newSize.X += 1;
+ if(!(newSize.Y % 2))
+ newSize.Y += 1;
+
+ radius = (newSize-ui::Point(1, 1))/2;
+ size = newSize;
+ origSize = size;
+
+ origBitmap = new unsigned char[size.X*size.Y];
+ std::fill(origBitmap, origBitmap+(size.X*size.Y), 0);
+ for(int y = 0; y < rectSize_.Y; y++)
+ {
+ for(int x = 0; x < rectSize_.X; x++)
+ {
+ if(newBitmap[(y*rectSize_.X)+x] >= 128)
+ origBitmap[(y*size.X)+x] = newBitmap[(y*rectSize_.X)+x];
+ }
+ }
+
+ SetRadius(radius);
+ };
+ virtual void GenerateBitmap()
+ {
+ if(origBitmap)
+ {
+ if(bitmap)
+ delete[] bitmap;
+ bitmap = new unsigned char[size.X*size.Y];
+ if(size == origSize)
+ std::copy(origBitmap, origBitmap+(origSize.X*origSize.Y), bitmap);
+ else
+ {
+ //Bilinear interpolation
+ float factorX = ((float)origSize.X)/((float)size.X);
+ float factorY = ((float)origSize.Y)/((float)size.Y);
+ for(int y = 0; y < size.Y; y++)
+ {
+ for(int x = 0; x < size.X; x++)
+ {
+ float originalY = ((float)y)*factorY;
+ float originalX = ((float)x)*factorX;
+
+ int lowerX = std::floor(originalX);
+ int upperX = std::min((float)(origSize.X-1), std::floor(originalX+1.0f));
+ int lowerY = std::floor(originalY);
+ int upperY = std::min((float)(origSize.Y-1), std::floor(originalY+1.0f));
+
+ unsigned char topRight = origBitmap[(lowerY*origSize.X)+upperX];
+ unsigned char topLeft = origBitmap[(lowerY*origSize.X)+lowerX];
+ unsigned char bottomRight = origBitmap[(upperY*origSize.X)+upperX];
+ unsigned char bottomLeft = origBitmap[(upperY*origSize.X)+lowerX];
+ float top = LinearInterpolate<float>(topLeft, topRight, lowerX, upperX, originalX);
+ float bottom = LinearInterpolate<float>(bottomLeft, bottomRight, lowerX, upperX, originalX);
+ float mid = LinearInterpolate<float>(top, bottom, lowerY, upperY, originalY);
+ bitmap[(y*size.X)+x] = mid > 128 ? 255 : 0;
+ }
+ }
+ }
+ }
+ }
+ virtual ~BitmapBrush()
+ {
+ if(origBitmap)
+ delete[] origBitmap;
+ }
+};
+
+#endif /* BTIMAPBRUSH_H_ */
diff --git a/src/game/Brush.h b/src/game/Brush.h
index 068ecf5..b59d017 100644
--- a/src/game/Brush.h
+++ b/src/game/Brush.h
@@ -61,7 +61,7 @@ public:
{
return size;
}
- void SetRadius(ui::Point radius)
+ virtual void SetRadius(ui::Point radius)
{
this->radius = radius;
this->size = radius+radius+ui::Point(1, 1);
diff --git a/src/game/GameController.cpp b/src/game/GameController.cpp
index 18b93d6..c929f3a 100644
--- a/src/game/GameController.cpp
+++ b/src/game/GameController.cpp
@@ -987,6 +987,15 @@ void GameController::OpenSavePreview(int saveID, int saveDate)
ui::Engine::Ref().ShowWindow(activePreview->GetView());
}
+void GameController::OpenSavePreview()
+{
+ if(gameModel->GetSave())
+ {
+ activePreview = new PreviewController(gameModel->GetSave()->GetID(), new SaveOpenCallback(this));
+ ui::Engine::Ref().ShowWindow(activePreview->GetView());
+ }
+}
+
void GameController::OpenLocalBrowse()
{
class LocalSaveOpenCallback: public FileSelectedCallback
diff --git a/src/game/GameController.h b/src/game/GameController.h
index 4c7a8c9..a5c4416 100644
--- a/src/game/GameController.h
+++ b/src/game/GameController.h
@@ -106,6 +106,7 @@ public:
void OpenLogin();
void OpenTags();
void OpenSavePreview(int saveID, int saveDate);
+ void OpenSavePreview();
void OpenLocalSaveWindow(bool asCurrent);
void OpenLocalBrowse();
void OpenOptions();
diff --git a/src/game/GameModel.cpp b/src/game/GameModel.cpp
index 5c4ee97..71d9263 100644
--- a/src/game/GameModel.cpp
+++ b/src/game/GameModel.cpp
@@ -9,6 +9,7 @@
#include "Brush.h"
#include "EllipseBrush.h"
#include "TriangleBrush.h"
+#include "BitmapBrush.h"
#include "client/Client.h"
#include "client/GameSave.h"
#include "game/DecorationTool.h"
@@ -310,6 +311,26 @@ void GameModel::BuildMenus()
brushList.push_back(new Brush(ui::Point(4, 4)));
brushList.push_back(new TriangleBrush(ui::Point(4, 4)));
+ //Load more from brushes folder
+ std::vector<string> brushFiles = Client::Ref().DirectorySearch(BRUSH_DIR, "", ".ptb");
+ for(int i = 0; i < brushFiles.size(); i++)
+ {
+ std::vector<unsigned char> brushData = Client::Ref().ReadFile(brushFiles[i]);
+ if(!brushData.size())
+ {
+ std::cout << "Brushes: Skipping " << brushFiles[i] << ". Could not open" << std::endl;
+ continue;
+ }
+ int dimension = std::sqrt(brushData.size());
+ if(dimension * dimension != brushData.size())
+ {
+ std::cout << "Brushes: Skipping " << brushFiles[i] << ". Invalid bitmap size" << std::endl;
+ continue;
+ }
+ brushList.push_back(new BitmapBrush(brushData, ui::Point(dimension, dimension)));
+ }
+
+
//Set default tools
regularToolset[0] = GetToolFromIdentifier("DEFAULT_PT_DUST");
regularToolset[1] = GetToolFromIdentifier("DEFAULT_PT_NONE");
diff --git a/src/game/GameView.cpp b/src/game/GameView.cpp
index 0e3f580..9d900ba 100644
--- a/src/game/GameView.cpp
+++ b/src/game/GameView.cpp
@@ -223,6 +223,10 @@ GameView::GameView():
{
v->c->ReloadSim();
}
+ void AltActionCallback(ui::Button * sender)
+ {
+ v->c->OpenSavePreview();
+ }
};
reloadButton = new ui::Button(ui::Point(currentX, Size.Y-16), ui::Point(17, 15), "", "Reload the simulation");
reloadButton->SetIcon(IconReload);
diff --git a/src/interface/Button.cpp b/src/interface/Button.cpp
index fbf9b54..4b9c5d9 100644
--- a/src/interface/Button.cpp
+++ b/src/interface/Button.cpp
@@ -156,26 +156,38 @@ void Button::Draw(const Point& screenPos)
void Button::OnMouseUnclick(int x, int y, unsigned int button)
{
- if(button != 1)
+ if(button == 1)
{
- return;
+ if(isButtonDown)
+ {
+ isButtonDown = false;
+ DoAction();
+ }
}
-
- if(isButtonDown)
+ else if(button == 3)
{
- isButtonDown = false;
- DoAction();
- }
+ if(isAltButtonDown)
+ {
+ isAltButtonDown = false;
+ DoAltAction();
+ }
+ }
}
void Button::OnMouseClick(int x, int y, unsigned int button)
{
- if(button != 1) return;
- if(isTogglable)
- {
- toggle = !toggle;
+ if(button == 1)
+ {
+ if(isTogglable)
+ {
+ toggle = !toggle;
+ }
+ isButtonDown = true;
+ }
+ else if(button == 3)
+ {
+ isAltButtonDown = true;
}
- isButtonDown = true;
}
void Button::OnMouseEnter(int x, int y)
@@ -206,6 +218,14 @@ void Button::DoAction()
actionCallback->ActionCallback(this);
}
+void Button::DoAltAction()
+{
+ if(!Enabled)
+ return;
+ if(actionCallback)
+ actionCallback->AltActionCallback(this);
+}
+
void Button::SetActionCallback(ButtonAction * action)
{
if(actionCallback)
diff --git a/src/interface/Button.h b/src/interface/Button.h
index 5bc7fc3..dff15b4 100644
--- a/src/interface/Button.h
+++ b/src/interface/Button.h
@@ -20,6 +20,7 @@ class ButtonAction
{
public:
virtual void ActionCallback(ui::Button * sender) {}
+ virtual void AltActionCallback(ui::Button * sender) {}
virtual void MouseEnterCallback(ui::Button * sender) {}
virtual ~ButtonAction() {}
};
@@ -45,6 +46,7 @@ public:
virtual void TextPosition();
inline bool GetState() { return state; }
virtual void DoAction(); //action of button what ever it may be
+ virtual void DoAltAction(); //action of button what ever it may be
void SetTogglable(bool isTogglable);
bool GetTogglable();
TPT_NO_INLINE bool GetToggleState();
@@ -60,7 +62,7 @@ protected:
std::string buttonDisplayText;
std::string ButtonText;
- bool isButtonDown, state, isMouseInside, isTogglable, toggle;
+ bool isButtonDown, isAltButtonDown, state, isMouseInside, isTogglable, toggle;
ButtonAction * actionCallback;
};
diff --git a/src/simulation/elements/CLST.cpp b/src/simulation/elements/CLST.cpp
index 3cab1f7..ab62acb 100644
--- a/src/simulation/elements/CLST.cpp
+++ b/src/simulation/elements/CLST.cpp
@@ -50,7 +50,7 @@ Element_CLST::Element_CLST()
int Element_CLST::update(UPDATE_FUNC_ARGS)
{
int r, rx, ry;
- float cxy;
+ float cxy = 0;
for (rx=-2; rx<3; rx++)
for (ry=-2; ry<3; ry++)
if (x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES && (rx || ry))
@@ -76,7 +76,7 @@ int Element_CLST::update(UPDATE_FUNC_ARGS)
cxy = 0.015;
if(parts[i].temp >= 295 && parts[i].temp <350)
cxy = 0.01;
- if(parts[i].temp > 350)
+ if(parts[i].temp >= 350)
cxy = 0.005;
parts[i].vx += cxy*rx;
parts[i].vy += cxy*ry;//These two can be set not to calculate over 350 later. They do virtually nothing over 0.005.
diff --git a/src/simulation/elements/SWCH.cpp b/src/simulation/elements/SWCH.cpp
index 818af27..422b7b5 100644
--- a/src/simulation/elements/SWCH.cpp
+++ b/src/simulation/elements/SWCH.cpp
@@ -76,7 +76,7 @@ int Element_SWCH::update(UPDATE_FUNC_ARGS)
parts[i].life = parts[r>>8].life;
}
}
- else if (rt==PT_SPRK&&parts[i].life==10&&parts[r>>8].ctype!=PT_PSCN&&parts[r>>8].ctype!=PT_NSCN) {
+ else if (rt==PT_SPRK && parts[i].life==10 && parts[r>>8].life>0 && parts[r>>8].ctype!=PT_PSCN && parts[r>>8].ctype!=PT_NSCN) {
sim->part_change_type(i,x,y,PT_SPRK);
parts[i].ctype = PT_SWCH;
parts[i].life = 4;
diff --git a/src/simulation/elements/VIBR.cpp b/src/simulation/elements/VIBR.cpp
index 68119f7..7a8c30c 100644
--- a/src/simulation/elements/VIBR.cpp
+++ b/src/simulation/elements/VIBR.cpp
@@ -149,7 +149,7 @@ int Element_VIBR::update(UPDATE_FUNC_ARGS) {
if (!r)
continue;
//Melts into EXOT
- if ((r&0xFF) == PT_EXOT && !(rand()%250))
+ if ((r&0xFF) == PT_EXOT && !(rand()%250) && !parts[i].life)
{
sim->create_part(i, x, y, PT_EXOT);
}
@@ -163,7 +163,7 @@ int Element_VIBR::update(UPDATE_FUNC_ARGS) {
parts[r>>8].tmp += 10;
}
//Absorbs energy particles
- if ((sim->elements[r&0xFF].Properties & TYPE_ENERGY))
+ if ((sim->elements[r&0xFF].Properties & TYPE_ENERGY) && !parts[i].life)
{
parts[i].tmp += 20;
sim->kill_part(r>>8);