diff options
Diffstat (limited to 'engines/hdb')
-rw-r--r-- | engines/hdb/ai.h | 2 | ||||
-rw-r--r-- | engines/hdb/hdb.cpp | 181 |
2 files changed, 176 insertions, 7 deletions
diff --git a/engines/hdb/ai.h b/engines/hdb/ai.h index 1a0f1d35b5..adb6ee89b9 100644 --- a/engines/hdb/ai.h +++ b/engines/hdb/ai.h @@ -398,7 +398,7 @@ struct AIEntity { AIDir dir2; // this is from TED uint16 x, y; - uint16 drawXOff, drawYOff; // might need a drawing offset + int16 drawXOff, drawYOff; // might need a drawing offset uint16 onScreen; // FLAG: is this entity onscreen? uint16 moveSpeed; // movement speed of this entity int16 xVel, yVel; // movement values diff --git a/engines/hdb/hdb.cpp b/engines/hdb/hdb.cpp index 3f2ca97419..4c48e06e59 100644 --- a/engines/hdb/hdb.cpp +++ b/engines/hdb/hdb.cpp @@ -448,12 +448,181 @@ void HDBGame::useEntity(AIEntity *e) { } } - /* - PUSHING - If its a pushable object, push it. Unless it's in/on water. - */ + // PUSHING + // If its a pushable object, push it. Unless it's in/on water. if (e->type == AI_CRATE || e->type == AI_LIGHTBARREL || e->type == AI_BOOMBARREL || e->type == AI_MAGIC_EGG || e->type == AI_ICE_BLOCK || e->type == AI_FROGSTATUE || e->type == AI_DIVERTER) { - warning("STUB: HDBGame::useEntity PUSHING required"); + int xDir, yDir, chX, chY; + uint32 flags; + AIEntity *e2; + + // if it's floating, don't touch! + if (e->state >= STATE_FLOATING && e->state <= STATE_FLOATRIGHT) { + g_hdb->_ai->lookAtEntity(e); + g_hdb->_ai->animGrabbing(); + g_hdb->_window->openMessageBar("I can't lift that!", 1); + return; + } + + xDir = yDir = 0; + if (p->tileX > e->tileX) + xDir = -2; + else if (p->tileX < e->tileX) + xDir = 2; + + if (p->tileY > e->tileY) + yDir = -2; + else if (p->tileY < e->tileY) + yDir = 2; + + // no diagonals allowed! + if (xDir && yDir) + return; + + chX = p->tileX + xDir; + chY = p->tileY + yDir; + + // are we going to push this over a sliding surface? (ok) + // are we going to push this into a blocking tile? (not ok) + if (e->level == 2) { + int fg_flags = g_hdb->_map->getMapFGTileFlags(chX, chY); + if (fg_flags & kFlagSolid) { + g_hdb->_sound->playSound(SND_GUY_UHUH); + g_hdb->_ai->lookAtXY(chX, chY); + g_hdb->_ai->animGrabbing(); + return; + } + + flags = g_hdb->_map->getMapBGTileFlags(chX, chY); + if (((flags & kFlagSolid) == kFlagSolid) && !(fg_flags & kFlagGrating)) { + g_hdb->_sound->playSound(SND_GUY_UHUH); + g_hdb->_ai->lookAtXY(chX, chY); + g_hdb->_ai->animGrabbing(); + return; + } + } else { + flags = g_hdb->_map->getMapBGTileFlags(chX, chY); + if (!(flags & kFlagSlide) && (flags & kFlagSolid)) { + g_hdb->_sound->playSound(SND_GUY_UHUH); + g_hdb->_ai->lookAtXY(chX, chY); + g_hdb->_ai->animGrabbing(); + return; + } + } + + // are we going to push this up the stairs? (not ok) + if (flags & kFlagStairBot) { + flags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY); + if (!(flags & kFlagStairTop)) { + g_hdb->_ai->lookAtEntity(e); + g_hdb->_ai->animGrabbing(); + g_hdb->_sound->playSound(SND_GUY_UHUH); + return; + } + } + + // is player trying to push across a dangerous floor (where the player would be ON the floor after the push)? + // don't allow it. + flags = g_hdb->_map->getMapBGTileFlags(p->tileX + (xDir >> 1), p->tileY + (yDir >> 1)); + if (((flags & kFlagRadFloor) == kFlagRadFloor || (flags & kFlagPlasmaFloor) == kFlagPlasmaFloor) && + false == g_hdb->_ai->checkFloating(p->tileX + (xDir >> 1), p->tileY + (yDir >> 1))) { + g_hdb->_ai->lookAtEntity(e); + g_hdb->_ai->animGrabbing(); + g_hdb->_sound->playSound(SND_NOPUSH_SIZZLE); + return; + } + + // are we going to push this into a gem? + // if it's a goodfairy, make it move! + e2 = g_hdb->_ai->findEntityIgnore(chX, chY, &g_hdb->_ai->_dummyLaser); + if (e2 && e2->type == ITEM_GEM_WHITE) { + g_hdb->_ai->addAnimateTarget(e2->x, e2->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH); + g_hdb->_ai->removeEntity(e2); + g_hdb->_sound->playSound(SND_BRIDGE_END); + g_hdb->_ai->animGrabbing(); + return; + } + + // if so, is it a MELTED or FLOATING entity? if so, that's cool... + if (e2) { + if (!g_hdb->_ai->checkFloating(e2->tileX, e2->tileY)) { + g_hdb->_ai->lookAtXY(chX, chY); + g_hdb->_ai->animGrabbing(); + g_hdb->_sound->playSound(SND_GUY_UHUH); + return; + } + } + + // are we trying to push this through a door? (teleporter!) + SingleTele info; + if (true == g_hdb->_ai->findTeleporterDest(chX, chY, &info)) { + g_hdb->_ai->lookAtXY(chX, chY); + g_hdb->_ai->animGrabbing(); + g_hdb->_sound->playSound(SND_GUY_UHUH); + return; + } + + // everything's clear - time to push! + // set goal for pushed object + if (e->type != AI_DIVERTER) + e->moveSpeed = kPushMoveSpeed; // push DIVERTERS real fast + g_hdb->_ai->setEntityGoal(e, chX, chY); + + // Diverters are very special - don't mess with their direction & state! + if (e->type == AI_DIVERTER) { + switch (e->dir2) { + case DIR_DOWN: e->state = STATE_DIVERTER_BL; break; + case DIR_UP: e->state = STATE_DIVERTER_BR; break; + case DIR_LEFT: e->state = STATE_DIVERTER_TL; break; + case DIR_RIGHT: e->state = STATE_DIVERTER_TR; break; + case DIR_NONE: break; + } + } + + // set goal for player + if (xDir) + xDir = xDir >> 1; + if (yDir) + yDir = yDir >> 1; + if (e->type != AI_DIVERTER) // push DIVERTERS real fast + p->moveSpeed = kPushMoveSpeed; + else + p->moveSpeed = kPlayerMoveSpeed; + + g_hdb->_ai->setEntityGoal(p, p->tileX + xDir, p->tileY + yDir); + + // need to set the state AFTER the SetEntityGoal! + switch (p->dir) { + case DIR_UP: p->state = STATE_PUSHUP; p->drawYOff = -10; break; + case DIR_DOWN: p->state = STATE_PUSHDOWN; p->drawYOff = 9; break; + case DIR_LEFT: p->state = STATE_PUSHLEFT; p->drawXOff = -10; break; + case DIR_RIGHT: p->state = STATE_PUSHRIGHT; p->drawXOff = 10; break; + case DIR_NONE: break; + } + + // if player is running, keep speed slow since we're pushing + if (g_hdb->_ai->playerRunning()) { + p->xVel = p->xVel >> 1; + p->yVel = p->yVel >> 1; + } + + switch (e->type) { + case AI_CRATE: + g_hdb->_sound->playSound(SND_CRATE_SLIDE); break; + case AI_LIGHTBARREL: + case AI_FROGSTATUE: + case AI_ICE_BLOCK: + g_hdb->_sound->playSound(SND_LIGHT_SLIDE); break; + case AI_HEAVYBARREL: + case AI_MAGIC_EGG: + case AI_BOOMBARREL: + g_hdb->_sound->playSound(SND_HEAVY_SLIDE); break; + case AI_DIVERTER: + g_hdb->_sound->playSound(SND_PUSH_DIVERTER); break; + default: + break; + } + + return; } // Look at Entity @@ -468,7 +637,7 @@ void HDBGame::useEntity(AIEntity *e) { // Can't push it - make a sound if (e->type == AI_HEAVYBARREL) { - warning("STUB: HDBGame::useEntity Play HEAVYBARREL sound"); + g_hdb->_sound->playSound(SND_GUY_UHUH); } } |