summaryrefslogtreecommitdiff
path: root/src/bossMegaGoomba.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/bossMegaGoomba.cpp349
1 files changed, 254 insertions, 95 deletions
diff --git a/src/bossMegaGoomba.cpp b/src/bossMegaGoomba.cpp
index bac2516..34f521e 100644
--- a/src/bossMegaGoomba.cpp
+++ b/src/bossMegaGoomba.cpp
@@ -34,6 +34,7 @@ class daMegaGoomba_c : public dEn_c {
unsigned int Ykey_count;
char life;
+ bool already_hit;
//TODO use these for MegaGecko testing of params
u32 marker1_start;
@@ -58,13 +59,13 @@ class daMegaGoomba_c : public dEn_c {
void setupBodyModel();
void updateModelMatrices();
-// bool preSpriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
-// bool prePlayerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ bool preSpriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ bool prePlayerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
// bool preYoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther);
// bool stageActorCollision(ActivePhysics *apThis, ActivePhysics *apOther);
-// void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
-// void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther);
+ void playerCollision(ActivePhysics *apThis, ActivePhysics *apOther);
// void yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther);
void collisionCat1_Fireball_E_Explosion(ActivePhysics *apThis, ActivePhysics *apOther);
@@ -85,8 +86,10 @@ class daMegaGoomba_c : public dEn_c {
DECLARE_STATE(Grow);
DECLARE_STATE(Shrink);
DECLARE_STATE(Walk);
+ DECLARE_STATE(Turn);
DECLARE_STATE(Jump);
DECLARE_STATE(Launch);
+ //DECLARE_STATE(SomethingCool);
};
daMegaGoomba_c *daMegaGoomba_c::build() {
@@ -94,6 +97,32 @@ daMegaGoomba_c *daMegaGoomba_c::build() {
return new(buffer) daMegaGoomba_c;
}
+void HexDump(char* address, u32 length) {
+ length = (length + 0x1f) & ~0x1f;
+ char line[0x11] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+ for(u32 ii=0; ii < length; ii += 0x10) {
+ for(u32 jj=0; jj < 0x10; jj++) {
+ if((address[ii+jj] < 0x20) || (address[ii+jj] > 0x7e)) {
+ line[jj] = '.';
+ }else{
+ line[jj] = address[ii+jj];
+ }
+ }
+ OSReport("%08x: %04x %04x %04x %04x %04x %04x %04x %04x |%s|\n",
+ (u32)(address+ii),
+ *(u16*)(address+ii+0x00),
+ *(u16*)(address+ii+0x02),
+ *(u16*)(address+ii+0x04),
+ *(u16*)(address+ii+0x06),
+ *(u16*)(address+ii+0x08),
+ *(u16*)(address+ii+0x0a),
+ *(u16*)(address+ii+0x0c),
+ *(u16*)(address+ii+0x0e),
+ line);
+ for(u32 jj=0; jj<0x10; jj++) line[jj] = 0;
+ }
+}
+
extern "C" void *PlaySound(daMegaGoomba_c *, int soundID);
@@ -106,45 +135,113 @@ extern "C" u8 dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(daMegaGoomb
extern "C" dStageActor_c *CreateActor(u16 classID, int settings, Vec pos, char rot, char layer);
extern "C" dStageActor_c *GetSpecificPlayerActor(int number);
+//FIXME make this dEn_c->used...
+extern "C" char usedForDeterminingStatePress_or_playerCollision(dEn_c* t, ActivePhysics *apThis, ActivePhysics *apOther, int unk1);
+extern "C" void doSpriteMovement(dStageActor_c* actor);
+extern "C" int SomeStrangeModification(dStageActor_c* actor);
+extern "C" int CollidedWithTile(u8* c_1EC);
+extern "C" void DoStuffAndMarkDead(dStageActor_c *actor, Vec vector, float unk);
+extern "C" int SmoothRotation(short* rot, u16 amt, int unk2);
+
CREATE_STATE(daMegaGoomba_c, Grow);
CREATE_STATE(daMegaGoomba_c, Shrink);
CREATE_STATE(daMegaGoomba_c, Walk);
+CREATE_STATE(daMegaGoomba_c, Turn);
CREATE_STATE(daMegaGoomba_c, Jump);
CREATE_STATE(daMegaGoomba_c, Launch);
+//CREATE_STATE(daMegaGoomba_c, SomethingCool);
//TODO better fix for possible bug with sign (ex. life=120; count=-9;)
bool daMegaGoomba_c::takeHit(char count) {
- int c = count;
- int l = this->life;
- if(l - c > 127) {
- c = 127 - l;
+ if(!this->already_hit) {
+ int c = count;
+ int l = this->life;
+ if(l - c > 127) {
+ c = 127 - l;
+ }
+ this->life -= c;
+ this->XSpeed += 0.25;
+ this->JumpHeight += 12.0;
+ this->JumpDist += 12.0;
+ this->JumpTime += 5.0;
+ doStateChange(&StateID_Shrink);
+ this->already_hit = true;
}
- this->life -= c;
- this->XSpeed += 0.25;
- this->JumpHeight += 12.0;
- this->JumpDist += 12.0;
- this->JumpTime += 5.0;
- doStateChange(&StateID_Shrink);
- setNewActivePhysicsRect(this, &this->scale);
return (life <= 0) ? true : false;
}
#define ACTIVATE 1
#define DEACTIVATE 0
-//bool daMegaGoomba_c::preSpriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("preSpriteCollision\n"); return false; }
-//bool daMegaGoomba_c::prePlayerCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("prePlayerCollision\n"); return false; }
+bool daMegaGoomba_c::preSpriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ OSReport("preSpriteCollision\n");
+ return false;
+}
+bool daMegaGoomba_c::prePlayerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ OSReport("prePlayerCollision\n");
+ return false;
+}
//bool daMegaGoomba_c::preYoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("preYoshiCollision\n"); return false; }
//bool daMegaGoomba_c::stageActorCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("stageActorCollision\n"); return true; }
-//void daMegaGoomba_c::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("spriteCollision\n"); }
-/*void daMegaGoomba_c::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
- this->_vf220(apOther->owner);
- OSReport("I hit Mario.\n");
-}*/
+void daMegaGoomba_c::spriteCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ OSReport("spriteCollision\n");
+ float me = apThis->firstFloatArray[3];
+ if(((this->direction == 1) && (me > 0.0)) || ((this->direction == 0) && (me < 0.0))) {
+ dStateBase_c* state = this->acState.getCurrentState();
+ if(!state->isEqual(&StateID_Turn)) {
+ doStateChange(&StateID_Turn);
+ }
+ }
+}
+
+void daMegaGoomba_c::playerCollision(ActivePhysics *apThis, ActivePhysics *apOther) {
+ OSReport("Mario collision.\n");
+
+ //FIXME rename and make part of dStageActor_c
+ char ret = usedForDeterminingStatePress_or_playerCollision(this, apThis, apOther, 0);
+ if(ret == 1) { // regular jump
+ // _vf2D8 == play_SE_EMY_KURIBO_M_SPLIT
+ //this->_vf2D8();
+ // _vf2DC == nullsub()
+ //this->_vf2DC();
+ apOther->someFlagByte |= 2;
+ OSReport("ret == 1; doStateChange('&StateID_SomethingCool');\n");
+ if(this->takeHit(1))
+ doStateChange(&StateID_DieFall);
+ } else if(ret == 3) { // spinning
+ // _vf2D8 == play_SE_EMY_KURIBO_M_SPLIT
+ //this->_vf2D8();
+ // _vf2DC == nullsub()
+ //this->_vf2DC();
+ apOther->someFlagByte |= 2;
+ OSReport("ret == 3; doStateChange('&StateID_SomethingCool');\n");
+ if(this->takeHit(1))
+ doStateChange(&StateID_DieFall);
+ //this->doStateChange(&StateID_SomethingCool);
+ } else if(ret == 0) {
+ OSReport("calling dEn_c::playerCollsiion(apThis, apOther);\n");
+ this->dEn_c::playerCollision(apThis, apOther);
+ this->_vf220(apOther->owner);
+ } else if(ret == 2) {
+ OSReport("Y U USIN' MINIMARIO?\n");
+ } else {
+ OSReport("usedForDeter...() returned %d\n", ret);
+ }
+
+ //FIXME hack to make multiple playerCollisions work
+ this->isDead = 0;
+ this->flags_4FC |= (1<<(31-7));
+ if(apOther->owner->_38D > 3) {
+ OSReport("!!!ATTENTION!!!\napOther->owner->_38D > 3\n");
+ }else{
+ this->counter_504[apOther->owner->_38D] = 0;
+ }
+}
+
//void daMegaGoomba_c::yoshiCollision(ActivePhysics *apThis, ActivePhysics *apOther) { OSReport("yoshiCollision\n"); }
@@ -184,7 +281,7 @@ void daMegaGoomba_c::bindAnimChr_and_setUpdateRate(const char* name, int unk, fl
void daMegaGoomba_c::dieFall_Begin() {
// DOESN'T LOOK GOOD
//this->bindAnimChr_and_setUpdateRate("damage", 0, 0.0, 1.0);
- //dSprite_c::dieFall_Begin();
+ this->dEn_c::dieFall_Begin();
}
//TODO make this real perty like
void daMegaGoomba_c::dieFall_Execute() {
@@ -199,32 +296,6 @@ void daMegaGoomba_c::dieFall_Execute() {
this->dEn_c::dieFall_Execute();
}
-void HexDump(char* address, u32 length) {
- length = (length + 0x1f) & ~0x1f;
- char line[0x11] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
- for(u32 ii=0; ii < length; ii += 0x10) {
- for(u32 jj=0; jj < 0x10; jj++) {
- if((address[ii+jj] < 0x20) || (address[ii+jj] > 0x7e)) {
- line[jj] = '.';
- }else{
- line[jj] = address[ii+jj];
- }
- }
- OSReport("%08x: %04x %04x %04x %04x %04x %04x %04x %04x |%s|\n",
- (u32)(address+ii),
- *(u16*)(address+ii+0x00),
- *(u16*)(address+ii+0x02),
- *(u16*)(address+ii+0x04),
- *(u16*)(address+ii+0x06),
- *(u16*)(address+ii+0x08),
- *(u16*)(address+ii+0x0a),
- *(u16*)(address+ii+0x0c),
- *(u16*)(address+ii+0x0e),
- line);
- for(u32 jj=0; jj<0x10; jj++) line[jj] = 0;
- }
-}
-
void daMegaGoomba_c::setupBodyModel() {
allocator.link(-1, GameHeaps[0], 0, 0x20);
@@ -280,6 +351,14 @@ int daMegaGoomba_c::onCreate() {
OSReport("Creating MG's body model\n");
setupBodyModel();
+ // FROM 80033288
+ this->max_speed.y = -4.0;
+ this->_518 = 2;
+ //sub_80034060
+ this->_36D = 0;
+ //FIXME add this method
+ //this->_vf2BC();
+
OSReport("Creating MegaGoomba's Physics Struct\n");
//TODO find data for a fun, yet challenging, battle
ActivePhysics::Info HitMeBaby;
@@ -300,13 +379,15 @@ int daMegaGoomba_c::onCreate() {
//sub_80034060();
//FIXME move this stuff elsewhere
- pos.y -= 16.0;
+ //pos.y -= 16.0;
+ speed.y = 0.0;
pos.z = 3000.0;
- speed.x = dying = 0.0;
+ dying = 0.0;
rot.x = rot.z = 0;
rot.y = 0x2000; // 0x2000 is left. 0xe000 is for right.
direction = 0;
life = 3;
+ already_hit = false;
//TODO 1) allow setting bounding rect with settings
//TODO 2) don't use bounding rect. use wall/floor/ceiling detection
Bounding.left = pos.x - 212.0;
@@ -323,6 +404,7 @@ int daMegaGoomba_c::onCreate() {
this->pickedChoice = -1;
// 2.0 is good final speed
this->XSpeed = 1.5;
+ this->x_speed_inc = 0.1;
this->JumpHeight = 48.0;
this->JumpDist = 64.0;
this->JumpTime = 50.0;
@@ -340,9 +422,17 @@ int daMegaGoomba_c::onDelete() {
}
int daMegaGoomba_c::onExecute() {
+ //80033450
acState.execute();
+ //if(CheckSomethingEnemyRelated())
+ // sub_80033f10(this);
+ //else
+ // dStageActor_c__checkZoneBoundaries(this, 0);
+ //// dont do updateModelMatrices ////
+
updateModelMatrices();
+ /*
if (this->aPhysics.result1 == 1) {
char PlayerID = NearestPlayer(this);
@@ -351,12 +441,40 @@ int daMegaGoomba_c::onExecute() {
this->_vf220(Player);
}
}
+ */
+
+#if 0
+ int ret2 = SomeStrangeModification(this);
+ OSReport("Bitfield88: %08x\n", *(u32*)&this->classAt1EC[0x88]);
+#else
+ /*
+ if(this->life > 0) {
+ if(this->pos.x < this->Bounding.left) {
+ OSReport("Too far left: %f %f\n", this->pos.x, this->Bounding.left);
+ doStateChange(&StateID_Turn);
+ this->pos.x = Bounding.left + 4.0;
+ } else if (this->pos.x > this->Bounding.right) {
+ OSReport("Too far right: %f %f\n", this->pos.x, this->Bounding.right);
+ doStateChange(&StateID_Turn);
+ this->pos.x = Bounding.right - 4.0;
+ }
+ if(this->pos.y < this->Bounding.bottom) {
+ this->speed.y = 0.0;
+ this->pos.y = this->Bounding.bottom;
+ } else if (this->pos.y > this->Bounding.top) {
+ this->speed.y = 0.0;
+ this->pos.y = this->Bounding.bottom;
+ }
+ }
+ */
+#endif
return true;
}
int daMegaGoomba_c::onDraw() {
bodyModel.scheduleForDrawing();
+ //DONT DO REST HERE//
bodyModel._vf1C();
animationPat.process();
/* SRT TESTS
@@ -367,29 +485,6 @@ int daMegaGoomba_c::onDraw() {
void daMegaGoomba_c::updateModelMatrices() {
- // Bounds checking // move to onExecute();
- // TODO possibly change to a state change
- if(this->life > 0) {
- if(this->pos.x < this->Bounding.left) {
- this->direction = !this->direction;
- rot.y = (this->direction) ? 0xe000 : 0x2000;
- this->speed.x = -this->speed.x;
- this->pos.x = this->Bounding.left;
- } else if (this->pos.x > this->Bounding.right) {
- this->direction = !this->direction;
- rot.y = (this->direction) ? 0xe000 : 0x2000;
- this->speed.x = -this->speed.x;
- this->pos.x = this->Bounding.right;
- }
- if(this->pos.y < this->Bounding.bottom) {
- this->speed.y = 0.0;
- this->pos.y = this->Bounding.bottom;
- } else if (this->pos.y > this->Bounding.top) {
- this->speed.y = 0.0;
- this->pos.y = this->Bounding.bottom;
- }
- }
-
// This won't work with wrap because I'm lazy.
matrix.translation(pos.x, pos.y, pos.z);
matrix.applyRotationYXZ(&rot.x, &rot.y, &rot.z);
@@ -443,27 +538,31 @@ void daMegaGoomba_c::endState_Grow() { }
void daMegaGoomba_c::beginState_Shrink() {
this->timer = 1.0;
Xkey_count = 4;
- keysX[0] = (HermiteKey){ 0.0, this->scale.x, 1.0 };
- keysX[1] = (HermiteKey){ 20.0, this->scale.x - 2.0, 1.0 };
- keysX[2] = (HermiteKey){ 40.0, this->scale.x, 1.0 };
- keysX[3] = (HermiteKey){ 59.0, this->scale.x - 2.0, 1.0 };
+ keysX[0] = (HermiteKey){ 0.0, this->scale.y, 1.0 };
+ keysX[1] = (HermiteKey){ 20.0, this->scale.y - 2.0, 1.0 };
+ keysX[2] = (HermiteKey){ 40.0, this->scale.y, 1.0 };
+ keysX[3] = (HermiteKey){ 59.0, this->scale.y - 2.0, 1.0 };
// using this to stop walk animation
- this->animationChr.setCurrentFrame(600.0);
+ this->animationChr.setCurrentFrame(900.0);
+ Vec tempVec = (Vec){0.0, 0.0, 0.0};
+ setNewActivePhysicsRect(this, &tempVec );
}
void daMegaGoomba_c::executeState_Shrink() {
this->timer += 1.0;
float modifier = GetHermiteCurveValue(this->timer, this->keysX, Xkey_count);
this->scale = (Vec){modifier, modifier, modifier};
- setNewActivePhysicsRect(this, &this->scale);
if(this->timer == 2.0)
PlaySound(this, SE_EMY_KURIBO_L_DAMAGE_02);
if (this->timer > 60.0) { doStateChange(&StateID_Walk); }
}
-void daMegaGoomba_c::endState_Shrink() { }
+void daMegaGoomba_c::endState_Shrink() {
+ setNewActivePhysicsRect(this, &this->scale);
+ this->already_hit = false;
+}
@@ -473,7 +572,7 @@ void daMegaGoomba_c::beginState_Launch() {
rot.y = 0x0;
// using this to stop walk animation
- this->animationChr.setCurrentFrame(600.0);
+ this->animationChr.setCurrentFrame(900.0);
}
void daMegaGoomba_c::executeState_Launch() {
@@ -484,26 +583,26 @@ void daMegaGoomba_c::executeState_Launch() {
dStageActor_c *spawner = NULL;
// 120ticks / 120numbers * 3cases = 3avg kuribo
int randChoice = GenerateRandomNumber(120);
- int randChoiceX = GenerateRandomNumber(12);
+ int randChoiceX = GenerateRandomNumber(10);
int randChoiceY = GenerateRandomNumber(7);
switch(randChoice) {
case 0:
case 1:
spawner = CreateActor(EN_KURIBO, 0, this->pos, 0, 0);
- spawner->speed.x = randChoiceX - 6.0;
- spawner->speed.y = randChoiceY + 3.0;
+ spawner->speed.x = randChoiceX - 5.0;
+ spawner->speed.y = randChoiceY + 6.0;
spawner->scale = (Vec){1.0, 1.0, 1.0};
break;
case 2:
spawner = CreateActor(EN_BEANS_KURIBO, 0, this->pos, 0, 0);
- spawner->speed.x = randChoiceX - 6.0;
- spawner->speed.y = randChoiceY + 3.0;
+ spawner->speed.x = randChoiceX - 5.0;
+ spawner->speed.y = randChoiceY + 6.0;
spawner->scale = (Vec){1.0, 1.0, 1.0};
break;
case 3:
spawner = CreateActor(EN_PATA_KURIBO, 0, this->pos, 0, 0);
- spawner->speed.x = randChoiceX - 6.0;
- spawner->speed.y = randChoiceY + 3.0;
+ spawner->speed.x = randChoiceX - 5.0;
+ spawner->speed.y = randChoiceY + 6.0;
spawner->scale = (Vec){1.0, 1.0, 1.0};
break;
default:
@@ -542,7 +641,7 @@ void daMegaGoomba_c::beginState_Jump() {
keysY[2] = (HermiteKey){ fullTime, this->pos.y, 0.8 };
// using this to stop walk animation
- this->animationChr.setCurrentFrame(600.0);
+ this->animationChr.setCurrentFrame(900.0);
}
void daMegaGoomba_c::executeState_Jump() {
@@ -560,11 +659,58 @@ void daMegaGoomba_c::executeState_Jump() {
void daMegaGoomba_c::endState_Jump() { }
+// Turn State
+void daMegaGoomba_c::beginState_Turn() {
+ /*
+ this->direction = !this->direction;
+ rot.y = (this->direction) ? 0xe000 : 0x2000;
+ this->speed.x = 0.0;
+ this->max_speed.x = (this->direction) ? -this->XSpeed : this->XSpeed;
+ */
+ this->direction ^= 1;
+ this->speed.x = 0.0;
+ this->speed.y = 0.0;
+}
+void daMegaGoomba_c::executeState_Turn() {
+ this->bodyModel._vf1C();
+ this->animationPat.process();
+
+ //FIXME removed falling goomba with these 2 lines out
+#if 0
+ HandleYSpeed(this);
+ doSpriteMovement(this);
+#endif
+
+ //nullsub();
+ //this->_vf2D0();
+ //int ret = Kuribo_References0x274();
+ int ret = SomeStrangeModification(this);
+ //OSReport("SomeStrangeModification() : %08x [%08x]\n", ret, *(u32*)&this->classAt1EC[0x88]);
+ if(ret & 1)
+ this->speed.y = 0.0;
+ if(ret & 4)
+ this->pos.x = this->last_pos.x;
+ DoStuffAndMarkDead(this, this->pos, 1.0);
+ u16 amt = (this->direction == 0) ? 0x2000 : 0xE000;
+ int done = SmoothRotation(&this->rot.y, amt, 0x200);
+ if(done) {
+ this->doStateChange(&StateID_Walk);
+ }
+}
+void daMegaGoomba_c::endState_Turn() {
+ this->max_speed.x = (this->direction) ? -this->XSpeed : this->XSpeed;
+}
+
+
// Walk State
void daMegaGoomba_c::beginState_Walk() {
this->timer = 1.0;
+
+ //inline this piece of code
this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, this->pos);
rot.y = (this->direction) ? 0xe000 : 0x2000;
+ this->speed.x = 0.0;
+ this->max_speed.x = (this->direction) ? -this->XSpeed : this->XSpeed;
//SETUP WALK ANIMATION//
bindAnimChr_and_setUpdateRate("walk", 1, 0.0, 1.0);
@@ -591,11 +737,21 @@ void daMegaGoomba_c::executeState_Walk() {
this->animationChr.setCurrentFrame(0.0);
//HandleAcceleration(this);
- //HandleXSpeed(this);
- //UpdateObjectPosBasedOnSpeedValues_real(this);
+ HandleXSpeed(this);
+ //HandleYSpeed(this);
+ UpdateObjectPosBasedOnSpeedValues_real(this);
//DoGravityMaybe();
- float delta = (this->direction) ? -this->XSpeed : this->XSpeed;
+
+ if(CollidedWithTile(this->classAt1EC)) {
+ OSReport("CollidedWithTile() : true [%08x]\n", *(u32*)&this->classAt1EC[0x88]);
+ }
+ int ret2 = SomeStrangeModification(this);
+ OSReport("Bitfield88: %08x [%08x]\n", *(u32*)&this->classAt1EC[0x88], ret2);
+
+ /*
+ float delta = (this->direction) ? -this->speed.x : this->speed.x;
this->pos.x += delta;
+ */
int Choice;
float TimerMax = 150.0;
@@ -611,11 +767,14 @@ void daMegaGoomba_c::executeState_Walk() {
doStateChange(&StateID_Jump);
break;
case 1:
+#if 0
doStateChange(&StateID_Launch);
+#endif
break;
default:
- this->direction = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, pos);
- rot.y = (this->direction) ? 0xe000 : 0x2000;
+ int new_dir = dSprite_c__getXDirectionOfFurthestPlayerRelativeToVEC3(this, pos);
+ if(this->direction != new_dir)
+ doStateChange(&StateID_Turn);
this->timer = 0;
break;
};