transhumandesign / kag-base

King Arthur's Gold base folder.
257 stars 118 forks source link

Particles substitute each other's handles in the game? #2156

Open NoahTheLegend opened 1 week ago

NoahTheLegend commented 1 week ago

Description

When storing an array of particles in an object with .set(), the dead (timed out) particles' are replaced with any other particles in the game in an unknown order

Reproduction

Steps to reproduce the behavior: The code in following video that energy sphere runs:


void sparks(Vec2f pos, int amount, CBlob@ this)
{
    if (!getNet().isClient())
        return;

    CParticle@[] particleList;
    this.get("ParticleList",particleList);

    for(int a = 0; a < 2; a++)
    {   
        CParticle@ p = ParticleAnimated("ElectricBlob.png", this.getPosition() + Vec2f(8 + XORRandom(16), 0).RotateBy(XORRandom(360)), Vec2f(0,0), XORRandom(360), 1.0f, 1, 0.5f, true);
        if(p !is null)
        {
            p.fastcollision = true;
            p.gravity = Vec2f(0,0);
            p.bounce = 1;
            p.lighting = false;
            p.timeout = 90;
            p.setRenderStyle(RenderStyle::additive);

            particleList.push_back(p);
        }
    }
    for(int a = 0; a < particleList.length(); a++)
    {
        CParticle@ particle = particleList[a];
        //check
        if(particle.timeout < 1)
        {
            particleList.erase(a);
            a--;
            continue;
        }

        //Gravity
        Vec2f tempGrav = Vec2f(0,0);
        tempGrav.x = -(particle.position.x - pos.x);
        tempGrav.y = -(particle.position.y - pos.y);
        particle.gravity = tempGrav / 10;//tweak the 20 till your heart is content

        //particleList[a] = @particle;

    }
    this.set("ParticleList",particleList);
}```

https://github.com/user-attachments/assets/2afe4c46-5b42-4933-9e68-d945bb0d9101

**Expected Behavior**

most likely it is an optimization, however upcoming engine update and staging features should compensate that

Currently no workaround found
asumagic commented 1 week ago

This is due to how particles are implemented, storage is reused. If it weren't, you would get hard crashes or corruption instead anyway. I'm not sure what's the best way to detect particle destruction script-side at the moment, though, needs looking into.

We cannot nullify handles from the engine side. This would require something like weak references, which should have been done from the start, and that would require touching all the API that touches CParticle@.