From ce1e212317021696b4d19547e17c7dd3972e531b Mon Sep 17 00:00:00 2001 From: Misa Date: Tue, 5 May 2020 13:49:12 -0700 Subject: [PATCH] Prevent updating an entity if updateentities() removed it Otherwise, this would result in the game updating an entity twice, which isn't good. This is most noticeable in the Gravitron, where many Gravitron squares are created and destroyed at a time, and it's especially noticeable during the part near the end of the Gravitron where the pattern is two Gravitron squares, one at the top and bottom, and then two Gravitron squares in the middle afterwards. The timing is just right such that the top one of the two middle ones would be misaligned with the bottom one of the two when a Gravitron square gets outside the screen. To do this, I changed entityclass::updateentities() into a bool, and made every single caller check its return value. I only needed to do this for the ones preceding updateentitylogic() and entitymapcollision(), but I wanted to play it safe and be defensive, so I did it for the disappearing platform kludge, as well as the updateentities() within the updateentities() function. --- desktop_version/src/Entity.cpp | 79 ++++++++++++++++++++++++++-------- desktop_version/src/Entity.h | 2 +- desktop_version/src/Logic.cpp | 35 ++++++++++++--- 3 files changed, 91 insertions(+), 25 deletions(-) diff --git a/desktop_version/src/Entity.cpp b/desktop_version/src/Entity.cpp index db9ea765..4b000e75 100644 --- a/desktop_version/src/Entity.cpp +++ b/desktop_version/src/Entity.cpp @@ -2066,12 +2066,13 @@ void entityclass::createentity( float xp, float yp, int t, float vx /*= 0*/, flo entities.push_back(entity); } -void entityclass::updateentities( int i ) +//Returns true if entity is removed +bool entityclass::updateentities( int i ) { if (i < 0 || i >= (int) entities.size()) { puts("updateentities() out-of-bounds!"); - return; + return true; } if(entities[i].statedelay<=0) @@ -2088,7 +2089,8 @@ void entityclass::updateentities( int i ) if (entities[i].state == 0) //Init { entities[i].state = 3; - updateentities(i); + bool entitygone = updateentities(i); + if (entitygone) return true; } else if (entities[i].state == 1) { @@ -2111,7 +2113,8 @@ void entityclass::updateentities( int i ) if (entities[i].state == 0) //Init { entities[i].state = 2; - updateentities(i); + bool entitygone = updateentities(i); + if (entitygone) return true; } else if (entities[i].state == 1) { @@ -2134,7 +2137,8 @@ void entityclass::updateentities( int i ) if (entities[i].state == 0) //Init { entities[i].state = 3; - updateentities(i); + bool entitygone = updateentities(i); + if (entitygone) return true; } else if (entities[i].state == 1) { @@ -2157,7 +2161,8 @@ void entityclass::updateentities( int i ) if (entities[i].state == 0) //Init { entities[i].state = 3; - updateentities(i); + bool entitygone = updateentities(i); + if (entitygone) return true; } else if (entities[i].state == 1) { @@ -2252,10 +2257,18 @@ void entityclass::updateentities( int i ) } else if (entities[i].state == 1) { - if (entities[i].xp >= 335) removeentity(i); + if (entities[i].xp >= 335) + { + removeentity(i); + return true; + } if (game.roomx == 117) { - if (entities[i].xp >= (33*8)-32) removeentity(i); + if (entities[i].xp >= (33*8)-32) + { + removeentity(i); + return true; + } //collector for LIES } } @@ -2281,10 +2294,18 @@ void entityclass::updateentities( int i ) } else if (entities[i].state == 1) { - if (entities[i].yp <= -60) removeentity(i); + if (entities[i].yp <= -60) + { + removeentity(i); + return true; + } if (game.roomy == 108) { - if (entities[i].yp <= 60) removeentity(i); + if (entities[i].yp <= 60) + { + removeentity(i); + return true; + } //collector for factory } } @@ -2297,7 +2318,8 @@ void entityclass::updateentities( int i ) if (entities[j].type == 2 && entities[j].state== 3 && entities[j].xp == (entities[i].xp-32) ) { entities[i].state = 3; - updateentities(i); + bool entitygone = updateentities(i); + if (entitygone) return true; } } } @@ -2326,7 +2348,8 @@ void entityclass::updateentities( int i ) if (entities[j].type == 2 && entities[j].state==3 && entities[j].xp==entities[i].xp+32) { entities[i].state = 3; - updateentities(i); + bool entitygone = updateentities(i); + if (entitygone) return true; } } } @@ -2367,14 +2390,16 @@ void entityclass::updateentities( int i ) //approach from the left entities[i].xp = -64; entities[i].state = 2; - updateentities(i); //right + bool entitygone = updateentities(i); //right + if (entitygone) return true; } else { //approach from the left entities[i].xp = 320; entities[i].state = 3; - updateentities(i); //left + bool entitygone = updateentities(i); //left + if (entitygone) return true; } } @@ -2475,6 +2500,7 @@ void entityclass::updateentities( int i ) { removeblockat(entities[i].xp, entities[i].yp); removeentity(i); + return true; } } break; @@ -2484,6 +2510,7 @@ void entityclass::updateentities( int i ) { removeentity(i); game.gravitycontrol = (game.gravitycontrol + 1) % 2; + return true; } break; @@ -2491,7 +2518,11 @@ void entityclass::updateentities( int i ) if (entities[i].state == 0) { entities[i].life--; - if (entities[i].life < 0) removeentity(i); + if (entities[i].life < 0) + { + removeentity(i); + return true; + } } break; case 6: //Small pickup @@ -2502,6 +2533,7 @@ void entityclass::updateentities( int i ) collect[entities[i].para] = true; removeentity(i); + return true; } break; case 7: //Found a trinket @@ -2526,6 +2558,7 @@ void entityclass::updateentities( int i ) } removeentity(i); + return true; } break; case 8: //Savepoints @@ -3022,6 +3055,7 @@ void entityclass::updateentities( int i ) { game.scmprogress++; removeentity(i); + return true; } } break; @@ -3044,14 +3078,22 @@ void entityclass::updateentities( int i ) if (entities[i].state == 0) //Init { entities[i].vx = 7; - if (entities[i].xp > 320) removeentity(i); + if (entities[i].xp > 320) + { + removeentity(i); + return true; + } } break; case 1: if (entities[i].state == 0) //Init { entities[i].vx = -7; - if (entities[i].xp <-20) removeentity(i); + if (entities[i].xp <-20) + { + removeentity(i); + return true; + } } break; } @@ -3143,6 +3185,7 @@ void entityclass::updateentities( int i ) } removeentity(i); + return true; } break; case 100: //The teleporter @@ -3217,6 +3260,8 @@ void entityclass::updateentities( int i ) entities[i].statedelay = 0; } } + + return false; } void entityclass::animateentities( int _i ) diff --git a/desktop_version/src/Entity.h b/desktop_version/src/Entity.h index 3cc07069..edc194b2 100644 --- a/desktop_version/src/Entity.h +++ b/desktop_version/src/Entity.h @@ -76,7 +76,7 @@ public: void createentity(float xp, float yp, int t, float vx = 0, float vy = 0, int p1 = 0, int p2 = 0, int p3 = 320, int p4 = 240 ); - void updateentities(int i); + bool updateentities(int i); void animateentities(int i); diff --git a/desktop_version/src/Logic.cpp b/desktop_version/src/Logic.cpp index fe58d269..9ca91f24 100644 --- a/desktop_version/src/Logic.cpp +++ b/desktop_version/src/Logic.cpp @@ -342,14 +342,32 @@ void gamelogic() { //ok, unfortunate case where the disappearing platform hasn't fully disappeared. Accept a little //graphical uglyness to avoid breaking the room! - while (obj.entities[i].state == 2) obj.updateentities(i); - obj.entities[i].state = 4; + bool entitygone = false; + while (obj.entities[i].state == 2) + { + entitygone = obj.updateentities(i); + if (entitygone) + { + i--; + break; + } + } + if (!entitygone) obj.entities[i].state = 4; } else if (map.finalstretch && obj.entities[i].type == 2) { //for the final level. probably something 99% of players won't see. - while (obj.entities[i].state == 2) obj.updateentities(i); - obj.entities[i].state = 4; + bool entitygone = false; + while (obj.entities[i].state == 2) + { + entitygone = obj.updateentities(i); + if (entitygone) + { + i--; + break; + } + } + if (!entitygone) obj.entities[i].state = 4; } else if (obj.entities[i].type == 23 && game.swnmode && game.deathseq<15) { @@ -699,7 +717,8 @@ void gamelogic() { obj.removeblockat(obj.entities[i].xp, obj.entities[i].yp); - obj.updateentities(i); // Behavioral logic + bool entitygone = obj.updateentities(i); // Behavioral logic + if (entitygone) continue; obj.updateentitylogic(i); // Basic Physics obj.entitymapcollision(i); // Collisions with walls @@ -728,7 +747,8 @@ void gamelogic() { obj.removeblockat(obj.entities[ie].xp, obj.entities[ie].yp); - obj.updateentities(ie); // Behavioral logic + bool entitygone = obj.updateentities(ie); // Behavioral logic + if (entitygone) continue; obj.updateentitylogic(ie); // Basic Physics obj.entitymapcollision(ie); // Collisions with walls @@ -759,7 +779,8 @@ void gamelogic() { if (!obj.entities[ie].isplatform) { - obj.updateentities(ie); // Behavioral logic + bool entitygone = obj.updateentities(ie); // Behavioral logic + if (entitygone) continue; obj.updateentitylogic(ie); // Basic Physics obj.entitymapcollision(ie); // Collisions with walls }