mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-04-02 13:32:54 +02:00
jacksonmj: Reduce ETRD lag e7c4b989654e
Improvement isn't as good as the EMP one in normal cases, but for intentional lag bomb saves it is much better. Tested it and confirmed it worked just like before this commit. etrd_life0_count is hopefully valid, the accuracy may not be as good as in jacksonmj's fork
This commit is contained in:
parent
af48997228
commit
5ba34021bc
@ -1851,29 +1851,6 @@ int Simulation::parts_avg(int ci, int ni,int t)
|
||||
}
|
||||
|
||||
|
||||
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<distance)
|
||||
{
|
||||
distance = ndistance;
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
// unused function
|
||||
void Simulation::create_arc(int sx, int sy, int dx, int dy, int midpoints, int variance, int type, int flags)
|
||||
{
|
||||
@ -2686,6 +2663,8 @@ void Simulation::kill_part(int i)//kills particle number i
|
||||
{
|
||||
Element_SOAP::detach(this, i);
|
||||
}
|
||||
else if (parts[i].type == PT_ETRD && parts[i].life == 0)
|
||||
etrd_life0_count--;
|
||||
|
||||
parts[i].type = PT_NONE;
|
||||
parts[i].life = pfree;
|
||||
@ -2735,6 +2714,8 @@ void Simulation::part_change_type(int i, int x, int y, int t)//changes the type
|
||||
}
|
||||
else if (parts[i].type == PT_SOAP)
|
||||
Element_SOAP::detach(this, i);
|
||||
else if (parts[i].type == PT_ETRD && parts[i].life == 0)
|
||||
etrd_life0_count--;
|
||||
|
||||
if (parts[i].type > 0 && parts[i].type < PT_NUM && elementCount[parts[i].type])
|
||||
elementCount[parts[i].type]--;
|
||||
@ -2753,6 +2734,8 @@ void Simulation::part_change_type(int i, int x, int y, int t)//changes the type
|
||||
if (parts[i].tmp >= 0 && parts[i].tmp < MAX_FIGHTERS)
|
||||
Element_STKM::STKM_init_legs(this, &fighters[parts[i].tmp], i);
|
||||
}
|
||||
else if (t == PT_ETRD && parts[i].life == 0)
|
||||
etrd_life0_count++;
|
||||
|
||||
parts[i].type = t;
|
||||
if (elements[t].Properties & TYPE_ENERGY)
|
||||
@ -2934,6 +2917,8 @@ int Simulation::create_part(int p, int x, int y, int tv)
|
||||
{
|
||||
Element_SOAP::detach(this, p);
|
||||
}
|
||||
else if (parts[p].type == PT_ETRD && parts[p].life == 0)
|
||||
etrd_life0_count--;
|
||||
i = p;
|
||||
}
|
||||
|
||||
@ -3083,6 +3068,9 @@ int Simulation::create_part(int p, int x, int y, int tv)
|
||||
case PT_CRMC:
|
||||
parts[i].tmp2 = (rand() % 5);
|
||||
break;
|
||||
case PT_ETRD:
|
||||
etrd_life0_count++;
|
||||
break;
|
||||
case PT_STKM:
|
||||
{
|
||||
if (player.spwn == 0)
|
||||
@ -4820,6 +4808,8 @@ void Simulation::BeforeSim()
|
||||
emp_decor -= emp_decor/25+2;
|
||||
if(emp_decor < 0)
|
||||
emp_decor = 0;
|
||||
etrd_count_valid = false;
|
||||
etrd_life0_count = 0;
|
||||
|
||||
currentTick++;
|
||||
|
||||
@ -5083,6 +5073,8 @@ Simulation::Simulation():
|
||||
force_stacking_check(0),
|
||||
emp_decor(0),
|
||||
emp_trigger_count(0),
|
||||
etrd_count_valid(false),
|
||||
etrd_life0_count(0),
|
||||
lightningRecreate(0),
|
||||
gravWallChanged(false),
|
||||
CGOL(0),
|
||||
|
@ -63,6 +63,8 @@ public:
|
||||
int force_stacking_check;
|
||||
int emp_decor;
|
||||
int emp_trigger_count;
|
||||
bool etrd_count_valid;
|
||||
int etrd_life0_count;
|
||||
int lightningRecreate;
|
||||
//Stickman
|
||||
playerst player;
|
||||
@ -156,7 +158,6 @@ public:
|
||||
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 UpdateParticles(int start, int end);
|
||||
void SimulateGoL();
|
||||
void CheckStacking();
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include <algorithm>
|
||||
#include "simulation/Elements.h"
|
||||
|
||||
//#TPT-Directive ElementClass Element_ETRD PT_ETRD 50
|
||||
Element_ETRD::Element_ETRD()
|
||||
{
|
||||
@ -42,6 +44,129 @@ Element_ETRD::Element_ETRD()
|
||||
HighTemperatureTransition = NT;
|
||||
|
||||
Update = NULL;
|
||||
|
||||
Element_ETRD::initDeltaPos();
|
||||
}
|
||||
|
||||
class ETRD_deltaWithLength
|
||||
{
|
||||
public:
|
||||
ETRD_deltaWithLength(ui::Point a, int b):
|
||||
d(a),
|
||||
length(b)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ui::Point d;
|
||||
int length;
|
||||
};
|
||||
|
||||
const int maxLength = 12;
|
||||
std::vector<ETRD_deltaWithLength> deltaPos;
|
||||
|
||||
bool compareFunc(const ETRD_deltaWithLength &a, const ETRD_deltaWithLength &b)
|
||||
{
|
||||
return a.length < b.length;
|
||||
}
|
||||
|
||||
//#TPT-Directive ElementHeader Element_ETRD static void initDeltaPos()
|
||||
void Element_ETRD::initDeltaPos()
|
||||
{
|
||||
deltaPos.clear();
|
||||
for (int ry = -maxLength; ry <= maxLength; ry++)
|
||||
for (int rx = -maxLength; rx <= maxLength; rx++)
|
||||
{
|
||||
ui::Point d(rx, ry);
|
||||
if (std::abs(d.X) + std::abs(d.Y) <= maxLength)
|
||||
deltaPos.push_back(ETRD_deltaWithLength(d, std::abs(d.X) + std::abs(d.Y)));
|
||||
}
|
||||
std::stable_sort(deltaPos.begin(), deltaPos.end(), compareFunc);
|
||||
}
|
||||
|
||||
//#TPT-Directive ElementHeader Element_ETRD static int nearestSparkablePart(Simulation *sim, int targetId)
|
||||
int Element_ETRD::nearestSparkablePart(Simulation *sim, int targetId)
|
||||
{
|
||||
if (!sim->elementCount[PT_ETRD])
|
||||
return -1;
|
||||
if (sim->etrd_count_valid && sim->etrd_life0_count <= 0)
|
||||
return -1;
|
||||
|
||||
Particle *parts = sim->parts;
|
||||
int foundDistance = XRES + YRES;
|
||||
int foundI = -1;
|
||||
ui::Point targetPos = ui::Point(parts[targetId].x, parts[targetId].y);
|
||||
|
||||
if (sim->etrd_count_valid)
|
||||
{
|
||||
// countLife0 doesn't need recalculating, so just focus on finding the nearest particle
|
||||
|
||||
// If the simulation contains lots of particles, check near the target position first since going through all particles will be slow.
|
||||
// Threshold = number of positions checked, *2 because it's likely to access memory all over the place (less cache friendly) and there's extra logic needed
|
||||
// TODO: probably not optimal if excessive stacking is used
|
||||
if (sim->parts_lastActiveIndex > (int)deltaPos.size()*2)
|
||||
{
|
||||
for (std::vector<ETRD_deltaWithLength>::iterator iter = deltaPos.begin(), end = deltaPos.end(); iter != end; ++iter)
|
||||
{
|
||||
ETRD_deltaWithLength delta = (*iter);
|
||||
ui::Point checkPos = targetPos + delta.d;
|
||||
int checkDistance = delta.length;
|
||||
if (foundDistance < checkDistance)
|
||||
{
|
||||
// deltaPos is sorted in order of ascending length, so foundDistance < checkDistance means all later items are further away.
|
||||
break;
|
||||
}
|
||||
if (sim->InBounds(checkPos.X, checkPos.Y) && checkDistance <= foundDistance)
|
||||
{
|
||||
int r = sim->pmap[checkPos.Y][checkPos.X];
|
||||
if (r && (r&0xFF) == PT_ETRD && !parts[r>>8].life && r>>8 != targetId && checkDistance < foundDistance)
|
||||
{
|
||||
foundDistance = checkDistance;
|
||||
foundI = r>>8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If neighbor search didn't find a suitable particle, search all particles
|
||||
if (foundI < 0)
|
||||
{
|
||||
for (int i = 0; i <= sim->parts_lastActiveIndex; i++)
|
||||
{
|
||||
if (parts[i].type == PT_ETRD && !parts[i].life)
|
||||
{
|
||||
ui::Point checkPos = ui::Point(parts[i].x-targetPos.X, parts[i].y-targetPos.Y);
|
||||
int checkDistance = std::abs(checkPos.X) + std::abs(checkPos.Y);
|
||||
if (checkDistance < foundDistance && i != targetId)
|
||||
{
|
||||
foundDistance = checkDistance;
|
||||
foundI = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Recalculate countLife0, and search for the closest suitable particle
|
||||
int countLife0 = 0;
|
||||
for (int i = 0; i <= sim->parts_lastActiveIndex; i++)
|
||||
{
|
||||
if (parts[i].type == PT_ETRD && !parts[i].life)
|
||||
{
|
||||
countLife0++;
|
||||
ui::Point checkPos = ui::Point(parts[i].x-targetPos.X, parts[i].y-targetPos.Y);
|
||||
int checkDistance = std::abs(checkPos.X) + std::abs(checkPos.Y);
|
||||
if (checkDistance < foundDistance && i != targetId)
|
||||
{
|
||||
foundDistance = checkDistance;
|
||||
foundI = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
sim->etrd_life0_count = countLife0;
|
||||
sim->etrd_count_valid = true;
|
||||
}
|
||||
return foundI;
|
||||
}
|
||||
|
||||
Element_ETRD::~Element_ETRD() {}
|
||||
|
@ -57,7 +57,6 @@ int Element_SPRK::update(UPDATE_FUNC_ARGS)
|
||||
parts[i].temp = R_TEMP + 273.15f;
|
||||
if (ct<=0 || ct>=PT_NUM || !sim->elements[parts[i].ctype].Enabled)
|
||||
ct = PT_METL;
|
||||
sim->part_change_type(i,x,y,ct);
|
||||
parts[i].ctype = PT_NONE;
|
||||
parts[i].life = 4;
|
||||
if (ct == PT_WATR)
|
||||
@ -66,6 +65,7 @@ int Element_SPRK::update(UPDATE_FUNC_ARGS)
|
||||
parts[i].life = 54;
|
||||
else if (ct == PT_SWCH)
|
||||
parts[i].life = 14;
|
||||
sim->part_change_type(i,x,y,ct);
|
||||
return 0;
|
||||
}
|
||||
//Some functions of SPRK based on ctype (what it is on)
|
||||
@ -81,13 +81,13 @@ int Element_SPRK::update(UPDATE_FUNC_ARGS)
|
||||
case PT_ETRD:
|
||||
if (parts[i].life==1)
|
||||
{
|
||||
nearp = sim->nearest_part(i, PT_ETRD, -1);
|
||||
nearp = Element_ETRD::nearestSparkablePart(sim, i);
|
||||
if (nearp!=-1 && sim->parts_avg(i, nearp, PT_INSL)!=PT_INSL)
|
||||
{
|
||||
sim->CreateLine(x, y, (int)(parts[nearp].x+0.5f), (int)(parts[nearp].y+0.5f), PT_PLSM);
|
||||
parts[i].life = 20;
|
||||
sim->part_change_type(i,x,y,ct);
|
||||
ct = parts[i].ctype = PT_NONE;
|
||||
parts[i].life = 20;
|
||||
sim->part_change_type(nearp,(int)(parts[nearp].x+0.5f),(int)(parts[nearp].y+0.5f),PT_SPRK);
|
||||
parts[nearp].life = 9;
|
||||
parts[nearp].ctype = PT_ETRD;
|
||||
|
Loading…
x
Reference in New Issue
Block a user