scummvm/engines/hdb/ai-player.cpp
Eugene Sandulenko 944dbab7d6 HDB: Fix warning
2019-09-03 17:17:21 +02:00

1727 lines
46 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "hdb/hdb.h"
#include "hdb/menu.h"
namespace HDB {
void aiPlayerInit(AIEntity *e) {
g_hdb->_ai->clearInventory();
e->aiAction = aiPlayerAction;
e->draw = g_hdb->_ai->getStandFrameDir(e);
switch (e->dir) {
case DIR_UP:
e->state = STATE_STANDUP;
break;
case DIR_DOWN:
e->state = STATE_STANDDOWN;
break;
case DIR_LEFT:
e->state = STATE_STANDLEFT;
break;
case DIR_RIGHT:
e->state = STATE_STANDRIGHT;
break;
case DIR_NONE:
warning("AI-PLAYER: aiPlayerInit: DIR_NONE found");
break;
}
e->moveSpeed = kPlayerMoveSpeed;
strcpy(e->entityName, "player");
g_hdb->_ai->assignPlayer(e);
}
void aiPlayerInit2(AIEntity *e) {
if (!g_hdb->_ai->_clubUpGfx[0]) {
g_hdb->_ai->_weaponSelGfx = g_hdb->_gfx->loadTile(TILE_WEAPON_EQUIPPED);
g_hdb->_ai->_clubUpGfx[0] = g_hdb->_gfx->loadPic(CLUBUP1);
g_hdb->_ai->_clubUpGfx[1] = g_hdb->_gfx->loadPic(CLUBUP2);
g_hdb->_ai->_clubUpGfx[2] = g_hdb->_gfx->loadPic(CLUBUP3);
g_hdb->_ai->_clubUpGfx[3] = g_hdb->_gfx->loadPic(CLUBUP3);
g_hdb->_ai->_clubDownGfx[0] = g_hdb->_gfx->loadPic(CLUBDOWN1);
g_hdb->_ai->_clubDownGfx[1] = g_hdb->_gfx->loadPic(CLUBDOWN2);
g_hdb->_ai->_clubDownGfx[2] = g_hdb->_gfx->loadPic(CLUBDOWN3);
g_hdb->_ai->_clubDownGfx[3] = g_hdb->_gfx->loadPic(CLUBDOWN3);
g_hdb->_ai->_clubLeftGfx[0] = g_hdb->_gfx->loadPic(CLUBLEFT1);
g_hdb->_ai->_clubLeftGfx[1] = g_hdb->_gfx->loadPic(CLUBLEFT2);
g_hdb->_ai->_clubLeftGfx[2] = g_hdb->_gfx->loadPic(CLUBLEFT3);
g_hdb->_ai->_clubLeftGfx[3] = g_hdb->_gfx->loadPic(CLUBLEFT3);
g_hdb->_ai->_clubRightGfx[0] = g_hdb->_gfx->loadPic(CLUBRIGHT1);
g_hdb->_ai->_clubRightGfx[1] = g_hdb->_gfx->loadPic(CLUBRIGHT2);
g_hdb->_ai->_clubRightGfx[2] = g_hdb->_gfx->loadPic(CLUBRIGHT3);
g_hdb->_ai->_clubRightGfx[3] = g_hdb->_gfx->loadPic(CLUBRIGHT3);
g_hdb->_ai->_clubUpFrames = g_hdb->_ai->_clubDownFrames =
g_hdb->_ai->_clubLeftFrames = g_hdb->_ai->_clubRightFrames = 4;
g_hdb->_ai->_slugAttackGfx[0] = g_hdb->_gfx->loadPic(SLUG_SHOT1);
g_hdb->_ai->_slugAttackGfx[1] = g_hdb->_gfx->loadPic(SLUG_SHOT2);
g_hdb->_ai->_slugAttackGfx[2] = g_hdb->_gfx->loadPic(SLUG_SHOT3);
g_hdb->_ai->_slugAttackGfx[3] = g_hdb->_gfx->loadPic(SLUG_SHOT4);
int32 size = g_hdb->_fileMan->getLength("shock_spark_sit01", TYPE_TILE32);
g_hdb->_ai->_stunLightningGfx[0] = g_hdb->_gfx->getTileGfx("shock_spark_sit01", size);
size = g_hdb->_fileMan->getLength("shock_spark_sit02", TYPE_TILE32);
g_hdb->_ai->_stunLightningGfx[1] = g_hdb->_gfx->getTileGfx("shock_spark_sit02", size);
size = g_hdb->_fileMan->getLength("shock_spark_sit03", TYPE_TILE32);
g_hdb->_ai->_stunLightningGfx[2] = g_hdb->_gfx->getTileGfx("shock_spark_sit03", size);
size = g_hdb->_fileMan->getLength("shock_spark_sit04", TYPE_TILE32);
g_hdb->_ai->_stunLightningGfx[3] = g_hdb->_gfx->getTileGfx("shock_spark_sit04", size);
size = g_hdb->_fileMan->getLength("starstun_sit01", TYPE_TILE32);
g_hdb->_ai->_stunnedGfx[0] = g_hdb->_gfx->getTileGfx("starstun_sit01", size);
size = g_hdb->_fileMan->getLength("starstun_sit02", TYPE_TILE32);
g_hdb->_ai->_stunnedGfx[1] = g_hdb->_gfx->getTileGfx("starstun_sit02", size);
size = g_hdb->_fileMan->getLength("starstun_sit03", TYPE_TILE32);
g_hdb->_ai->_stunnedGfx[2] = g_hdb->_gfx->getTileGfx("starstun_sit03", size);
size = g_hdb->_fileMan->getLength("starstun_sit04", TYPE_TILE32);
g_hdb->_ai->_stunnedGfx[3] = g_hdb->_gfx->getTileGfx("starstun_sit04", size);
}
e->draw = g_hdb->_ai->getStandFrameDir(e);
}
void aiPlayerAction(AIEntity *e) {
AIState stand[5] = {STATE_NONE, STATE_STANDUP, STATE_STANDDOWN, STATE_STANDLEFT, STATE_STANDRIGHT};
int xvAhead[5] = {9, 0, 0, -1, 1}, yvAhead[5] = {9, -1, 1, 0, 0};
AIEntity *hit = NULL;
// Draw the STUN lightning if it exists
if (e->sequence) {
e->aiDraw = aiPlayerDraw;
g_hdb->_sound->playSound(SND_STUNNER_FIRE);
hit = g_hdb->_ai->findEntity(e->tileX + xvAhead[e->dir], e->tileY + yvAhead[e->dir]);
if (hit)
switch (hit->type) {
case AI_MEERKAT:
if (hit->sequence > 2)
g_hdb->_ai->stunEnemy(hit, 8);
break;
case AI_ICEPUFF:
if (hit->state == STATE_ICEP_APPEAR || hit->state == STATE_ICEP_THROWDOWN || hit->state == STATE_ICEP_THROWLEFT || hit->state == STATE_ICEP_THROWRIGHT) {
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->stunEnemy(hit, 8);
}
break;
case AI_BADFAIRY:
case AI_GOODFAIRY:
case AI_CHICKEN:
case AI_OMNIBOT:
case AI_TURNBOT:
case AI_PUSHBOT:
case AI_DEADEYE:
case AI_FATFROG:
case AI_BUZZFLY:
case AI_MAINTBOT:
case AI_RIGHTBOT:
case AI_GATEPUDDLE:
g_hdb->_ai->stunEnemy(hit, 8);
break;
default:
debug(9, "STUB: stunEnemy: Play sound");
break;
}
hit = g_hdb->_ai->findEntity(e->tileX + (xvAhead[e->dir] << 1), e->tileY + (yvAhead[e->dir] << 1));
if (hit)
switch (hit->type) {
case AI_MEERKAT:
if (hit->sequence > 2)
g_hdb->_ai->stunEnemy(hit, 8);
break;
case AI_ICEPUFF:
if (hit->state == STATE_ICEP_APPEAR || hit->state == STATE_ICEP_THROWDOWN || hit->state == STATE_ICEP_THROWLEFT || hit->state == STATE_ICEP_THROWRIGHT) {
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->stunEnemy(hit, 8);
}
break;
case AI_BADFAIRY:
case AI_GOODFAIRY:
case AI_CHICKEN:
case AI_OMNIBOT:
case AI_TURNBOT:
case AI_PUSHBOT:
case AI_DEADEYE:
case AI_FATFROG:
case AI_BUZZFLY:
case AI_MAINTBOT:
case AI_RIGHTBOT:
case AI_GATEPUDDLE:
g_hdb->_ai->stunEnemy(hit, 8);
break;
default:
debug(9, "STUB: stunEnemy: Play sound");
break;
}
}
int xOff[] = {0, 0, -8,-16};
int yOff[] = {-8,-24,-16,-16};
// If the player is supposed to animate for abit, check for it here
switch (e->state) {
case STATE_GRABUP:
case STATE_GRABDOWN:
case STATE_GRABLEFT:
case STATE_GRABRIGHT:
if (!e->animFrame--) {
// Done with the Grabbing Animation, switch to standing
switch (e->state) {
case STATE_GRABUP: e->draw = e->standupGfx[0]; e->state = STATE_STANDUP; break;
case STATE_GRABDOWN: e->draw = e->standdownGfx[0]; e->state = STATE_STANDDOWN; break;
case STATE_GRABLEFT: e->draw = e->standleftGfx[0]; e->state = STATE_STANDLEFT; break;
case STATE_GRABRIGHT: e->draw = e->standrightGfx[0]; e->state = STATE_STANDRIGHT; break;
default:
debug(9, "STUB: stunEnemy: Play sound");
break;
}
e->animDelay = 1;
e->animCycle = 1;
}
break;
case STATE_ATK_CLUB_UP:
case STATE_ATK_CLUB_DOWN:
case STATE_ATK_CLUB_LEFT:
case STATE_ATK_CLUB_RIGHT:
g_hdb->_ai->setPlayerInvisible(true);
e->aiDraw = aiPlayerDraw;
e->drawXOff = xOff[e->state - STATE_ATK_CLUB_UP];
e->drawYOff = yOff[e->state - STATE_ATK_CLUB_UP];
switch (e->state) {
case STATE_ATK_CLUB_UP: cycleFrames(e, g_hdb->_ai->_clubUpFrames); break;
case STATE_ATK_CLUB_DOWN: cycleFrames(e, g_hdb->_ai->_clubDownFrames); break;
case STATE_ATK_CLUB_LEFT: cycleFrames(e, g_hdb->_ai->_clubLeftFrames); break;
case STATE_ATK_CLUB_RIGHT: cycleFrames(e, g_hdb->_ai->_clubRightFrames); break;
default:
debug(9, "STUB: stunEnemy: Play sound");
break;
}
// Whack!
if ((e->animFrame >= 1) && (e->animDelay == e->animCycle)) {
switch (e->dir) {
case DIR_UP: hit = g_hdb->_ai->playerCollision(32, 0, 16, 16); break;
case DIR_DOWN: hit = g_hdb->_ai->playerCollision(0, 32, 16, 16); break;
case DIR_LEFT: hit = g_hdb->_ai->playerCollision(16, 16, 32, 0); break;
case DIR_RIGHT: hit = g_hdb->_ai->playerCollision(16, 16, 0, 32); break;
default:
warning("aiPlayerAction: DIR_NONE found");
break;
}
if (hit && hit->level == e->level && !hit->stunnedWait) {
switch (hit->type) {
case AI_MEERKAT:
if (hit->sequence > 2) // out of the ground?
g_hdb->_ai->stunEnemy(hit, 2);
break;
case AI_ICEPUFF:
if (hit->state == STATE_ICEP_APPEAR ||
hit->state == STATE_ICEP_THROWDOWN ||
hit->state == STATE_ICEP_THROWLEFT ||
hit->state == STATE_ICEP_THROWRIGHT)
g_hdb->_ai->stunEnemy(hit, 2);
break;
case AI_CHICKEN:
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->removeEntity(hit);
break;
case AI_BADFAIRY:
case AI_GOODFAIRY:
case AI_OMNIBOT:
case AI_TURNBOT:
case AI_PUSHBOT:
case AI_DEADEYE:
case AI_FATFROG:
case AI_BUZZFLY:
case AI_MAINTBOT:
case AI_RIGHTBOT:
case AI_SHOCKBOT:
case AI_GATEPUDDLE:
g_hdb->_ai->stunEnemy(hit, 2);
warning("STUB: Play MetalorFlesh SND");
break;
default:
break;
}
}
}
if ((!e->animFrame) && (e->animDelay == e->animCycle)) {
e->state = stand[e->dir];
e->aiDraw = NULL;
switch (e->state) {
case STATE_ATK_CLUB_UP: e->draw = e->standupGfx[0]; break;
case STATE_ATK_CLUB_DOWN: e->draw = e->standdownGfx[0]; break;
case STATE_ATK_CLUB_LEFT: e->draw = e->standleftGfx[0]; break;
case STATE_ATK_CLUB_RIGHT: e->draw = e->standrightGfx[0]; break;
default:
debug(9, "STUB: stunEnemy: Play sound");
break;
}
g_hdb->_ai->setPlayerInvisible(false);
e->drawXOff = e->drawYOff = 0;
}
return;
case STATE_ATK_STUN_UP:
e->draw = g_hdb->_ai->_stunUpGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_stunUpFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->aiDraw = NULL;
e->sequence = 0;
}
return;
case STATE_ATK_STUN_DOWN:
e->draw = g_hdb->_ai->_stunDownGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_stunDownFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->aiDraw = NULL;
e->sequence = 0;
}
return;
case STATE_ATK_STUN_LEFT:
e->draw = g_hdb->_ai->_stunLeftGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_stunLeftFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->aiDraw = NULL;
e->sequence = 0;
}
return;
case STATE_ATK_STUN_RIGHT:
e->draw = g_hdb->_ai->_stunRightGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_stunRightFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->aiDraw = NULL;
e->sequence = 0;
}
return;
case STATE_ATK_SLUG_UP:
e->draw = g_hdb->_ai->_slugUpGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_slugUpFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->sequence = 0;
}
return;
case STATE_ATK_SLUG_DOWN:
e->draw = g_hdb->_ai->_slugDownGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_slugDownFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->sequence = 0;
}
return;
case STATE_ATK_SLUG_LEFT:
e->draw = g_hdb->_ai->_slugLeftGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_slugLeftFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->sequence = 0;
}
return;
case STATE_ATK_SLUG_RIGHT:
e->draw = g_hdb->_ai->_slugRightGfx[e->animFrame];
cycleFrames(e, g_hdb->_ai->_slugRightFrames);
if (!e->animFrame && e->animDelay == e->animCycle) {
e->state = stand[e->dir];
e->sequence = 0;
}
return;
default:
debug(9, "STUB: stunEnemy: Play sound");
break;
}
// If the touchplate wait is on, keep it timing
if (e->touchpWait) {
e->touchpWait--;
if (!e->touchpWait)
e->touchpTile = -e->touchpTile;
} else if (e->touchpTile < 0 && (e->touchpX != e->tileX || e->touchpY != e->tileY)) {
g_hdb->_ai->checkActionList(e, e->touchpX, e->touchpY, false);
g_hdb->_map->setMapBGTileIndex(e->touchpX, e->touchpY, -e->touchpTile);
e->touchpX = e->touchpY = e->touchpTile = 0;
}
// If the player is moving somewhere, animate him
int bgFlags, fgFlags;
if (e->goalX) {
if (onEvenTile(e->x, e->y)) {
g_hdb->_ai->playerOnIce() ? g_hdb->_sound->playSound(SND_STEPS_ICE) : g_hdb->_sound->playSound(SND_FOOTSTEPS);
// Did we just fall down a PLUMMET?
bgFlags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
fgFlags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
if ((bgFlags & kFlagPlummet) && !(fgFlags & kFlagGrating) && !g_hdb->_ai->playerDead()) {
g_hdb->_ai->killPlayer(DEATH_PLUMMET);
g_hdb->_ai->animEntFrames(e);
return;
}
}
g_hdb->_ai->animateEntity(e);
} else {
// Sometimes the fading stays black
if (!g_hdb->_ai->cinematicsActive() && g_hdb->_gfx->isFadeStaying())
g_hdb->_gfx->turnOffFade();
// Did we just fall down a PLUMMET?
bgFlags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
fgFlags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
if ((bgFlags & kFlagPlummet) && !(fgFlags & kFlagGrating) && !g_hdb->_ai->playerDead()) {
g_hdb->_ai->killPlayer(DEATH_PLUMMET);
g_hdb->_ai->animEntFrames(e);
return;
}
// Standing on a TouchPlate will activate something WHILE standing on it
int bgTile = g_hdb->_ai->checkForTouchplate(e->tileX, e->tileY);
if (bgTile && !e->touchpWait && !e->touchpTile) {
if (g_hdb->_ai->checkActionList(e, e->tileX, e->tileY, false)) {
e->touchpTile = bgTile;
e->touchpX = e->tileX;
e->touchpY = e->tileY;
e->touchpWait = kPlayerTouchPWait;
g_hdb->_ai->stopEntity(e);
}
}
g_hdb->_ai->animEntFrames(e);
}
}
void aiPlayerDraw(AIEntity *e, int mx, int my) {
switch (e->state) {
case STATE_ATK_CLUB_UP:
g_hdb->_ai->_clubUpGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
break;
case STATE_ATK_CLUB_DOWN:
g_hdb->_ai->_clubDownGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
break;
case STATE_ATK_CLUB_LEFT:
g_hdb->_ai->_clubLeftGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
break;
case STATE_ATK_CLUB_RIGHT:
g_hdb->_ai->_clubRightGfx[e->animFrame]->drawMasked(e->x + e->drawXOff - mx, e->y + e->drawYOff - my);
break;
default:
warning("AI-PLAYER: aiPlayerDraw: Unintended State");
break;
}
if (e->sequence) {
static int frame = 0;
switch (e->dir) {
case DIR_UP:
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y - 32 - my);
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y - 64 - my);
break;
case DIR_DOWN:
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y + 32 - my);
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - mx, e->y + 64 - my);
break;
case DIR_LEFT:
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - 32 - mx, e->y - my);
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x - 64 - mx, e->y - my);
break;
case DIR_RIGHT:
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x + 32 - mx, e->y - my);
g_hdb->_ai->_stunLightningGfx[frame]->drawMasked(e->x + 64 - mx, e->y - my);
break;
case DIR_NONE:
warning("AI-PLAYER: aiPlayerDraw: DIR_NONE found");
break;
}
frame = (frame + 1) & 3;
}
}
void aiGemAttackInit(AIEntity *e) {
int xv[5] = {9, 0, 0, -1, 1}, yv[5] = {9, -1, 1, 0, 0};
e->moveSpeed = kPlayerMoveSpeed << 1;
g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
e->state = STATE_MOVEDOWN; // so it will draw & animate
e->sequence = 0; // flying out at something
e->aiAction = aiGemAttackAction;
e->draw = e->movedownGfx[0];
g_hdb->_sound->playSound(SND_GEM_THROW);
}
void aiGemAttackAction(AIEntity *e) {
int xv[5] = {9, 0, 0, -1, 1}, yv[5] = {9, -1, 1, 0, 0};
AIEntity *hit;
int result;
switch (e->sequence) {
// flying out at something
case 0:
if (e->goalX)
g_hdb->_ai->animateEntity(e);
else {
g_hdb->_ai->checkActionList(e, e->tileX, e->tileY, false);
g_hdb->_ai->checkAutoList(e, e->tileX, e->tileY);
hit = g_hdb->_ai->findEntityIgnore(e->tileX, e->tileY, e);
uint32 bgFlags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
uint32 fgFlags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
result = (e->level == 1 ? (bgFlags & (kFlagSolid)) : !(fgFlags & kFlagGrating) && (bgFlags & (kFlagSolid)));
if (hit) {
switch (hit->type) {
case AI_CHICKEN:
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->removeEntity(hit);
g_hdb->_sound->playSound(SND_CHICKEN_BAGAWK);
break;
case AI_BADFAIRY:
g_hdb->_ai->stunEnemy(hit, 2);
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
break;
case AI_NONE:
if (hit->value1 == (int)AI_DRAGON) {
// pull dragon's coords out of "lua_func_use" string.
char num1[4], num2[4];
memset(num1, 0, 4);
memset(num2, 0, 4);
memcpy(num1, hit->luaFuncUse, 3);
memcpy(num2, hit->luaFuncUse + 3, 3);
g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
AIEntity *found = g_hdb->_ai->findEntity(atoi(num1), atoi(num2));
if (found)
aiDragonWake(found);
}
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
g_hdb->_sound->playSound(SND_INV_SELECT);
break;
case AI_DRAGON:
g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
aiDragonWake(hit);
// fallthrough
default:
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
}
if (e->value1)
e->sequence = 1;
else
g_hdb->_ai->removeEntity(e); // bye bye!
return;
} else if (result) { // hit a wall
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
g_hdb->_sound->playSound(SND_INV_SELECT);
// come back to daddy?
if (e->value1)
e->sequence = 1;
else {
g_hdb->_ai->removeEntity(e);
return;
}
} else {
g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
e->state = STATE_MOVEDOWN; // so it will draw & animate
}
g_hdb->_ai->animateEntity(e);
}
break;
// coming back to daddy?
case 1:
AIEntity *p = g_hdb->_ai->getPlayer();
if (e->x < p->x)
e->x++;
else
e->x--;
if (e->y < p->y)
e->y++;
else
e->y--;
if (abs(e->x - p->x) < 4 && abs(e->y - p->y) < 4)
{
int amt = g_hdb->_ai->getGemAmount();
g_hdb->_ai->setGemAmount(amt + 1);
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
g_hdb->_ai->removeEntity(e);
g_hdb->_sound->playSound(SND_GET_GEM);
}
break;
}
}
void aiChickenAction(AIEntity *e) {
static int delay = 64;
if (g_hdb->_map->checkEntOnScreen(e) && !delay) {
g_hdb->_sound->playSound(SND_CHICKEN_AMBIENT);
delay = g_hdb->_rnd->getRandomNumber(127) + 160;
aiChickenUse(e);
}
if (delay)
delay--;
if (e->goalX)
g_hdb->_ai->animateEntity(e);
else
g_hdb->_ai->animEntFrames(e);
}
void aiChickenUse(AIEntity *e) {
g_hdb->_sound->playSound(SND_CHICKEN_BAGAWK);
}
void aiChickenInit(AIEntity *e) {
e->aiUse = aiChickenUse;
e->aiAction = aiChickenAction;
}
void aiChickenInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiDollyInit(AIEntity *e) {
e->moveSpeed = kPlayerMoveSpeed >> 1;
e->aiAction = aiGenericAction;
}
void aiDollyInit2(AIEntity *e) {
e->draw = e->movedownGfx[0];
}
void aiSergeantInit(AIEntity *e) {
e->moveSpeed = kPlayerMoveSpeed >> 1;
if (e->value1)
e->aiAction = aiSergeantAction;
}
void aiSergeantInit2(AIEntity *e) {
e->draw = g_hdb->_ai->getStandFrameDir(e);
}
void aiSergeantAction(AIEntity *e) {
if (e->goalX) {
g_hdb->_sound->playSound(SND_FOOTSTEPS);
g_hdb->_ai->animateEntity(e);
} else
g_hdb->_ai->animEntFrames(e);
}
void aiSpacedudeInit(AIEntity *e) {
e->moveSpeed = kPlayerMoveSpeed >> 1;
if (e->value1)
e->aiAction = aiGenericAction;
}
void aiSpacedudeInit2(AIEntity *e) {
e->standdownFrames = 1;
e->standdownGfx[0] = e->movedownGfx[0];
e->standupFrames = 1;
e->standupGfx[0] = e->moveupGfx[0];
e->standleftFrames = 1;
e->standleftGfx[0] = e->moveleftGfx[0];
e->standrightFrames = 1;
e->standrightGfx[0] = e->moverightGfx[0];
e->draw = g_hdb->_ai->getStandFrameDir(e);
}
void aiCrateAction(AIEntity *e) {
// if crate isn't moving somewhere, don't move it
if (!e->goalX) {
// crate is stopped in the water... should it continue downstream?
// not if it's marked by the Number of the Beast!
if (e->state == STATE_FLOATING) {
if (e->value1 != 0x666) {
int flags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
if (flags & (kFlagPushRight | kFlagPushLeft | kFlagPushUp | kFlagPushDown)) {
g_hdb->_ai->setEntityGoal(e, e->tileX, e->tileY);
g_hdb->_ai->animateEntity(e);
} else
g_hdb->_ai->animEntFrames(e);
} else
g_hdb->_ai->animEntFrames(e);
}
return;
}
g_hdb->_ai->animateEntity(e);
}
void aiCrateInit2(AIEntity *e) {
// point all crate move frames to the standing one
e->movedownFrames =
e->moveleftFrames =
e->moverightFrames =
e->moveupFrames = 1;
e->movedownGfx[0] =
e->moveupGfx[0] =
e->moveleftGfx[0] =
e->moverightGfx[0] = e->standdownGfx[0];
e->draw = e->standdownGfx[0]; // standing frame - doesn't move
}
void aiCrateInit(AIEntity *e) {
e->moveSpeed = kPushMoveSpeed;
e->aiAction = aiCrateAction;
e->value1 = 0;
}
void aiBarrelLightAction(AIEntity *e) {
if (!e->goalX) {
if (e->state == STATE_FLOATING)
g_hdb->_ai->animEntFrames(e);
return;
}
g_hdb->_ai->animateEntity(e);
}
void aiBarrelLightInit2(AIEntity *e) {
// point all light barrel move frames to the standing one
e->movedownFrames =
e->moveleftFrames =
e->moverightFrames =
e->moveupFrames = 1;
e->movedownGfx[0] =
e->moveupGfx[0] =
e->moveleftGfx[0] =
e->moverightGfx[0] = e->standdownGfx[0];
e->draw = e->standdownGfx[0]; // standing frame - doesn't move
}
void aiBarrelLightInit(AIEntity *e) {
e->moveSpeed = kPushMoveSpeed;
e->aiAction = aiBarrelLightAction;
}
void aiBarrelHeavyAction(AIEntity *e) {
if (!e->goalX) {
if (e->state == STATE_FLOATING)
g_hdb->_ai->animEntFrames(e);
return;
}
g_hdb->_ai->animateEntity(e);
}
void aiBarrelHeavyInit2(AIEntity *e) {
// point all heavy barrel move frames to the standing one
e->movedownFrames =
e->moveleftFrames =
e->moverightFrames =
e->moveupFrames = 1;
e->movedownGfx[0] =
e->moveupGfx[0] =
e->moveleftGfx[0] =
e->moverightGfx[0] = e->standdownGfx[0];
e->draw = e->standdownGfx[0]; // standing frame - doesn't move
}
void aiBarrelHeavyInit(AIEntity *e) {
e->moveSpeed = kPushMoveSpeed;
e->aiAction = aiBarrelHeavyAction;
}
void aiBarrelExplode(AIEntity *e) {
e->state = STATE_EXPLODING;
e->animDelay = e->animCycle;
e->animFrame = 0;
g_hdb->_sound->playSound(SND_BARREL_EXPLODE);
g_hdb->_map->setBoomBarrel(e->tileX, e->tileY, 0);
}
void aiBarrelExplodeInit(AIEntity *e) {
e->moveSpeed = kPushMoveSpeed;
e->aiAction = aiBarrelExplodeAction;
g_hdb->_map->setBoomBarrel(e->tileX, e->tileY, 1);
}
void aiBarrelExplodeInit2(AIEntity *e) {
// point all exploding barrel MOVE frames to the standing one
e->blinkFrames =
e->movedownFrames =
e->moveleftFrames =
e->moverightFrames =
e->moveupFrames = 1;
e->blinkGfx[0] =
e->movedownGfx[0] =
e->moveupGfx[0] =
e->moveleftGfx[0] =
e->moverightGfx[0] = e->standdownGfx[0];
e->draw = e->standdownGfx[0]; // standing frame - doesn't move
}
void aiBarrelExplodeAction(AIEntity *e) {
if (e->goalX)
g_hdb->_ai->animateEntity(e);
else if (e->state == STATE_EXPLODING)
g_hdb->_ai->animEntFrames(e);
}
void aiBarrelExplodeSpread(AIEntity *e) {
AIEntity *e2;
int x = e->tileX;
int y = e->tileY;
int xv, yv;
int index = e->animFrame;
int xv1[4] = {-1, 1, -1, 0};
int yv1[4] = {-1, -1, 0, -1};
int xv2[4] = {1, 0, 1, -1};
int yv2[4] = {0, 1, 1, 1};
// are we just starting an explosion ring?
if (e->animDelay != e->animCycle)
return;
// the animation frame is the index into which set of 2 explosions to spawn
xv = xv1[index];
yv = yv1[index];
// explosion 1: check to see if we can explode (non-solid tile)
// if so, spawn it and mark it in the explosion matrix
if (!(g_hdb->_map->getMapBGTileFlags(x + xv, y + yv) & kFlagSolid) && !g_hdb->_map->explosionExist(x + xv, y + yv)) {
aiBarrelBlowup(e, x + xv, y + yv);
// are we blowing up on another BOOMBARREL? if so, start it exploding.
e2 = g_hdb->_ai->findEntity(x + xv, y + yv);
if (e2 && e2->state != STATE_EXPLODING) {
switch (e2->type) {
case AI_GUY:
g_hdb->_ai->killPlayer(DEATH_FRIED);
break;
case AI_BOOMBARREL:
aiBarrelExplode(e2);
break;
case AI_OMNIBOT:
case AI_TURNBOT:
case AI_SHOCKBOT:
case AI_RIGHTBOT:
case AI_PUSHBOT:
case AI_RAILRIDER:
case AI_MAINTBOT:
case AI_DEADEYE:
case AI_FATFROG:
case AI_ICEPUFF:
case AI_MEERKAT:
case AI_BUZZFLY:
case AI_GOODFAIRY:
case AI_GATEPUDDLE:
case AI_BADFAIRY:
g_hdb->_ai->addAnimateTarget(x * kTileWidth,
y * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
if (e2->type != AI_LASERBEAM)
g_hdb->_ai->removeEntity(e2);
break;
default:
break;
}
}
}
xv = xv2[index];
yv = yv2[index];
// explosion 2: check to see if we can explode (non-solid tile)
// if so, spawn it and mark it in the explosion matrix
if (!(g_hdb->_map->getMapBGTileFlags(x + xv, y + yv) & kFlagSolid) && !g_hdb->_map->explosionExist(x + xv, y + yv)) {
aiBarrelBlowup(e, x + xv, y + yv);
// are we blowing up on another BOOMBARREL? if so, start it exploding.
e2 = g_hdb->_ai->findEntity(x + xv, y + yv);
if (e2 && e2->state != STATE_EXPLODING) {
switch (e2->type) {
case AI_GUY:
g_hdb->_ai->killPlayer(DEATH_FRIED);
break;
case AI_BOOMBARREL:
aiBarrelExplode(e2);
break;
case AI_OMNIBOT:
case AI_TURNBOT:
case AI_SHOCKBOT:
case AI_RIGHTBOT:
case AI_PUSHBOT:
case AI_RAILRIDER:
case AI_MAINTBOT:
case AI_DEADEYE:
case AI_FATFROG:
case AI_ICEPUFF:
case AI_MEERKAT:
case AI_BUZZFLY:
case AI_GOODFAIRY:
case AI_GATEPUDDLE:
case AI_BADFAIRY:
g_hdb->_ai->addAnimateTarget(x * kTileWidth,
y * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
if (e2->type != AI_LASERBEAM)
g_hdb->_ai->removeEntity(e2);
break;
default:
break;
}
}
}
}
void aiBarrelExplosionEnd(int x, int y) {
g_hdb->_map->setExplosion(x, y, 0);
}
void aiBarrelBlowup(AIEntity *e, int x, int y) {
g_hdb->_ai->addAnimateTarget(x * kTileWidth,
y * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
g_hdb->_map->setExplosion(x, y, 1);
g_hdb->_ai->addCallback(AI_BARREL_EXPLOSION_END, x, y, e->animCycle * 4);
}
void aiScientistInit(AIEntity *e) {
e->moveSpeed = kPlayerMoveSpeed >> 1;
if (g_hdb->_ai->findPath(e))
e->aiAction = aiGenericAction;
else if (e->value1)
e->aiAction = aiGenericAction;
}
void aiScientistInit2(AIEntity *e) {
e->draw = g_hdb->_ai->getStandFrameDir(e);
}
void aiSlugAttackAction(AIEntity *e) {
int xv[5] = {9, 0, 0, -1, 1}, yv[5] = {9, -1, 1, 0, 0};
AIEntity *hit;
int result;
if (e->goalX)
g_hdb->_ai->animateEntity(e);
g_hdb->_ai->checkActionList(e, e->tileX, e->tileY, false);
g_hdb->_ai->checkAutoList(e, e->tileX, e->tileY);
hit = g_hdb->_ai->findEntityIgnore(e->tileX, e->tileY, e);
if (hit && hit->type == AI_GUY)
hit = NULL;
// don't hit anything you can walk through...
if (hit && true == g_hdb->_ai->getTableEnt(hit->type))
hit = NULL;
// don't hit floating stuff
if (hit && hit->state == STATE_FLOATING)
hit = NULL;
uint32 bg_flags = g_hdb->_map->getMapBGTileFlags(e->tileX, e->tileY);
uint32 fg_flags = g_hdb->_map->getMapFGTileFlags(e->tileX, e->tileY);
result = (e->level == 1 ? (bg_flags & (kFlagSolid)) : !(fg_flags & kFlagGrating) && (bg_flags & (kFlagSolid)));
if (hit) {
g_hdb->_sound->playSound(SND_SLUG_HIT);
warning("STUB: Play MetalOrFleshSnd");
switch (hit->type) {
case AI_MEERKAT:
if (hit->sequence > 2) { // out of the ground?
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->stunEnemy(hit, 8);
} else {
g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
e->state = STATE_MOVEDOWN; // so it will draw & animate
g_hdb->_ai->animateEntity(e);
return;
}
break;
case AI_ICEPUFF:
if (hit->state == STATE_ICEP_APPEAR ||
hit->state == STATE_ICEP_THROWDOWN ||
hit->state == STATE_ICEP_THROWLEFT ||
hit->state == STATE_ICEP_THROWRIGHT) {
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->stunEnemy(hit, 8);
} else {
g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
e->state = STATE_MOVEDOWN; // so it will draw & animate
g_hdb->_ai->animateEntity(e);
return;
}
break;
case AI_OMNIBOT:
case AI_TURNBOT:
case AI_SHOCKBOT:
case AI_RIGHTBOT:
case AI_PUSHBOT:
case AI_LISTENBOT:
case AI_MAINTBOT:
case AI_FATFROG:
case AI_BADFAIRY:
case AI_BUZZFLY:
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->stunEnemy(hit, 8);
break;
case AI_CHICKEN:
g_hdb->_ai->addAnimateTarget(hit->x, hit->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->removeEntity(hit);
break;
case AI_BOOMBARREL:
g_hdb->_sound->playSound(SND_CLUB_HIT_METAL);
aiBarrelExplode(hit);
aiBarrelBlowup(hit, hit->tileX, hit->tileY);
break;
// ACTION MODE entities go away - except the FOURFIRER
case AI_GATEPUDDLE:
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 7, ANIM_NORMAL, false, false, TELEPORT_FLASH);
g_hdb->_ai->removeEntity(hit);
g_hdb->_sound->playSound(SND_TELEPORT);
break;
case AI_DEADEYE:
g_hdb->_ai->addAnimateTarget(e->tileX * kTileWidth,
e->tileY * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
g_hdb->_ai->removeEntity(hit);
g_hdb->_sound->playSound(SND_BARREL_EXPLODE);
break;
case AI_NONE:
if (hit->value1 == (int)AI_DRAGON) {
// pull dragon's coords out of "lua_func_use" string.
char num1[4], num2[4];
memset(num1, 0, 4);
memset(num2, 0, 4);
memcpy(num1, hit->luaFuncUse, 3);
memcpy(num2, hit->luaFuncUse + 3, 3);
g_hdb->_sound->playSound(SND_CLUB_HIT_FLESH);
AIEntity *found = g_hdb->_ai->findEntity(atoi(num1), atoi(num2));
if (found)
aiDragonWake(found);
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
}
break;
case AI_DRAGON:
aiDragonWake(hit);
break;
default:
break;
}
g_hdb->_ai->removeEntity(e); // bye bye!
return;
} else if (result) { // hit a wall
g_hdb->_sound->playSound(SND_SLUG_HIT);
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GROUP_STEAM_PUFF_SIT);
g_hdb->_ai->removeEntity(e);
} else {
g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
e->state = STATE_MOVEDOWN; // so it will draw & animate
g_hdb->_ai->animateEntity(e);
}
}
void aiSlugAttackDraw(AIEntity *e, int mx, int my) {
g_hdb->_ai->_slugAttackGfx[e->animFrame]->drawMasked(e->x - mx + 8, e->y - my + 8);
}
void aiSlugAttackInit(AIEntity *e) {
int xv[5] = {9, 0, 0, -1, 1}, yv[5] = {9, -1, 1, 0, 0};
e->moveSpeed = kPlayerMoveSpeed << 1;
g_hdb->_ai->setEntityGoal(e, e->tileX + xv[e->dir], e->tileY + yv[e->dir]);
e->draw = NULL; // use custom draw function
e->aiDraw = aiSlugAttackDraw;
e->state = STATE_MOVEDOWN; // so it will draw & animate
e->aiAction = aiSlugAttackAction;
g_hdb->_sound->playSound(SND_SLUG_FIRE);
}
void aiSlugAttackInit2(AIEntity *e) {
e->movedownFrames = 4;
}
void aiDeadWorkerInit(AIEntity *e) {
}
void aiDeadWorkerInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiWorkerInit(AIEntity *e) {
if (e->value1)
e->aiAction = aiGenericAction;
e->moveSpeed = kPlayerMoveSpeed >> 1;
}
void aiWorkerInit2(AIEntity *e) {
e->draw = g_hdb->_ai->getStandFrameDir(e);
}
void aiAccountantInit(AIEntity *e) {
}
void aiAccountantInit2(AIEntity *e) {
e->draw = g_hdb->_ai->getStandFrameDir(e);
}
void aiFrogStatueInit(AIEntity *e) {
e->moveSpeed = kPushMoveSpeed;
e->aiAction = aiFrogStatueAction;
}
void aiFrogStatueInit2(AIEntity *e) {
// point all frog statue MOVE frames to the standing one
e->blinkFrames =
e->movedownFrames =
e->moveleftFrames =
e->moverightFrames =
e->moveupFrames = 1;
e->blinkGfx[0] =
e->movedownGfx[0] =
e->moveupGfx[0] =
e->moveleftGfx[0] =
e->moverightGfx[0] = e->standdownGfx[0];
e->draw = e->standdownGfx[0]; // standing frame - doesn't move
}
void aiFrogStatueAction(AIEntity *e) {
// if frog statue isn't moving somewhere, don't move it
if (!e->goalX)
return;
g_hdb->_ai->animateEntity(e);
}
void aiRoboStunnerAction(AIEntity *e) {
aiAnimateStanddown(e, 1);
aiGetItemAction(e);
}
void aiRoboStunnerInit(AIEntity *e) {
e->aiAction = aiRoboStunnerAction;
strcpy(e->printedName, "Robostunner");
}
void aiRoboStunnerInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiClubInit(AIEntity *e) {
strcpy(e->printedName, "Creature Clubber");
e->aiAction = aiGetItemAction;
}
void aiClubInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiSlugSlingerInit(AIEntity *e) {
strcpy(e->printedName, "Slugslinger");
e->aiAction = aiGetItemAction;
}
void aiSlugSlingerInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiEnvelopeGreenInit(AIEntity *e) {
strcpy(e->printedName, "Green envelope");
e->aiAction = aiGetItemAction;
}
void aiEnvelopeGreenInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiGemBlueInit(AIEntity *e) {
e->aiAction = aiGemAction;
}
void aiGemBlueInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiGemRedInit(AIEntity *e) {
e->aiAction = aiGemAction;
}
void aiGemRedInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiGemGreenInit(AIEntity *e) {
e->aiAction = aiGemAction;
}
void aiGemGreenInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiTeaCupInit(AIEntity *e) {
strcpy(e->printedName, "a Teacup");
e->aiAction = aiGetItemAction;
}
void aiTeaCupInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiCookieInit(AIEntity *e) {
strcpy(e->printedName, "a Cookie");
e->aiAction = aiGetItemAction;
}
void aiCookieInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiBurgerInit(AIEntity *e) {
strcpy(e->printedName, "a Burger");
e->aiAction = aiGetItemAction;
}
void aiBurgerInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiBookInit(AIEntity *e) {
strcpy(e->printedName, "a Book");
e->aiAction = aiGetItemAction;
}
void aiBookInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiClipboardInit(AIEntity *e) {
strcpy(e->printedName, "a Clipboard");
e->aiAction = aiGetItemAction;
}
void aiClipboardInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiNoteInit(AIEntity *e) {
strcpy(e->printedName, "a Note");
e->aiAction = aiGetItemAction;
}
void aiNoteInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiKeycardWhiteInit(AIEntity *e) {
strcpy(e->printedName, "a White keycard");
e->aiAction = aiGetItemAction;
}
void aiKeycardWhiteInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiKeycardBlueInit(AIEntity *e) {
strcpy(e->printedName, "a Blue keycard");
e->aiAction = aiGetItemAction;
}
void aiKeycardBlueInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiKeycardRedInit(AIEntity *e) {
strcpy(e->printedName, "a Red keycard");
e->aiAction = aiGetItemAction;
}
void aiKeycardRedInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiKeycardGreenInit(AIEntity *e) {
strcpy(e->printedName, "a Green keycard");
e->aiAction = aiGetItemAction;
}
void aiKeycardGreenInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiKeycardPurpleInit(AIEntity *e) {
strcpy(e->printedName, "a Purple keycard");
e->aiAction = aiGetItemAction;
}
void aiKeycardPurpleInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiKeycardBlackInit(AIEntity *e) {
strcpy(e->printedName, "a Black keycard");
e->aiAction = aiGetItemAction;
}
void aiKeycardBlackInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiSeedInit(AIEntity *e) {
strcpy(e->printedName, "some Henscratch");
e->aiAction = aiGetItemAction;
}
void aiSeedInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiSodaInit(AIEntity *e) {
strcpy(e->printedName, "a Dr. Frostee");
e->aiAction = aiGetItemAction;
}
void aiSodaInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiDollyTool1Init(AIEntity *e) {
strcpy(e->printedName, "Dolly's Wrench");
e->aiAction = aiGetItemAction;
}
void aiDollyTool1Init2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiDollyTool2Init(AIEntity *e) {
strcpy(e->printedName, "Dolly's Torch");
e->aiAction = aiGetItemAction;
}
void aiDollyTool2Init2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiDollyTool3Init(AIEntity *e) {
strcpy(e->printedName, "Dolly's EMF Resonator");
e->aiAction = aiGetItemAction;
}
void aiDollyTool3Init2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiDollyTool4Init(AIEntity *e) {
strcpy(e->printedName, "Dolly's Toolbox");
e->aiAction = aiGetItemAction;
}
void aiDollyTool4Init2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiRouterInit(AIEntity *e) {
strcpy(e->printedName, "a Computer Router");
e->aiAction = aiGetItemAction;
}
void aiRouterInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiSlicerInit(AIEntity *e) {
strcpy(e->printedName, "a Pizza Slicer");
e->aiAction = aiGetItemAction;
}
void aiSlicerInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiPackageInit(AIEntity *e) {
strcpy(e->printedName, "a Package");
e->aiAction = aiGetItemAction;
}
void aiPackageInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiMagicEggAction(AIEntity *e) {
// if magic egg isn't moving somewhere, don't move it
if (!e->goalX)
return;
g_hdb->_ai->animateEntity(e);
}
void aiMagicEggInit(AIEntity *e) {
e->moveSpeed = kPushMoveSpeed;
e->aiAction = aiMagicEggAction;
}
void aiMagicEggInit2(AIEntity *e) {
// point all magic egg move frames to the standing one
e->movedownFrames =
e->moveleftFrames =
e->moverightFrames =
e->moveupFrames = 1;
e->movedownGfx[0] =
e->moveupGfx[0] =
e->moveleftGfx[0] =
e->moverightGfx[0] = e->standdownGfx[0];
e->draw = e->standdownGfx[0]; // standing frame - doesn't move
}
void aiMagicEggUse(AIEntity *e) {
if (!scumm_strnicmp(e->luaFuncAction, "ai_", 3) || !scumm_strnicmp(e->luaFuncAction, "item_", 5)) {
int i = 0;
AIEntity *spawned = NULL;
while (aiEntList[i].type != END_AI_TYPES) {
if (!scumm_stricmp(aiEntList[i].luaName, e->luaFuncAction)) {
spawned = g_hdb->_ai->spawn(aiEntList[i].type, e->dir, e->tileX, e->tileY, NULL, NULL, NULL, DIR_NONE, e->level, 0, 0, 1);
break;
}
i++;
}
if (spawned) {
g_hdb->_ai->addAnimateTarget(e->tileX * kTileWidth,
e->tileY * kTileHeight, 0, 3, ANIM_NORMAL, false, false, GROUP_EXPLOSION_BOOM_SIT);
g_hdb->_sound->playSound(SND_BARREL_EXPLODE);
g_hdb->_ai->removeEntity(e);
}
}
}
void aiIceBlockAction(AIEntity *e) {
// if ice block isn't moving somewhere, don't move it
if (!e->goalX)
return;
g_hdb->_ai->animateEntity(e);
}
void aiIceBlockInit(AIEntity *e) {
e->moveSpeed = kPushMoveSpeed;
e->aiAction = aiIceBlockAction;
}
void aiIceBlockInit2(AIEntity *e) {
// point all ice block move frames to the standing one
e->movedownFrames =
e->moveleftFrames =
e->moverightFrames =
e->moveupFrames = 1;
e->movedownGfx[0] =
e->moveupGfx[0] =
e->moveleftGfx[0] =
e->moverightGfx[0] = e->standdownGfx[0];
e->draw = e->standdownGfx[0]; // standing frame - doesn't move
}
void aiCabKeyInit(AIEntity *e) {
strcpy(e->printedName, "a Cabinet key");
}
void aiCabKeyInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiItemChickenInit(AIEntity *e) {
strcpy(e->printedName, "Cooper's chicken");
}
void aiItemChickenInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiPdaInit(AIEntity *e) {
strcpy(e->printedName, "a P.D.A.");
e->aiAction = aiGetItemAction;
}
void aiPdaInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
#if 0
void aiCellUse(AIEntity *e) {
g_hdb->_window->openMessageBar("You got the Energy Cell!", kMsgDelay);
}
#endif
void aiCellInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiCellInit(AIEntity *e) {
strcpy(e->printedName, "Energy Cell");
e->aiAction = aiGetItemAction;
}
void aiEnvelopeWhiteInit(AIEntity *e) {
strcpy(e->printedName, "White envelope");
e->aiAction = aiGetItemAction;
}
void aiEnvelopeWhiteInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiEnvelopeBlueInit(AIEntity *e) {
strcpy(e->printedName, "Blue envelope");
e->aiAction = aiGetItemAction;
}
void aiEnvelopeBlueInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiEnvelopeRedInit(AIEntity *e) {
strcpy(e->printedName, "Red envelope");
e->aiAction = aiGetItemAction;
}
void aiEnvelopeRedInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiTransceiverInit(AIEntity *e) {
e->aiAction = aiTransceiverAction;
strcpy(e->printedName, "Transceiver");
}
void aiTransceiverInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiTransceiverAction(AIEntity *e) {
aiAnimateStanddown(e, 5);
if (e->onScreen)
aiGetItemAction(e);
}
#if 0
void aiTransceiverUse(AIEntity *e) {
g_hdb->_window->openMessageBar("You got the Transceiver!", kMsgDelay);
}
#endif
char monkBuff[32];
void aiMonkeystoneInit(AIEntity *e) {
e->aiUse = aiMonkeystoneUse;
e->aiAction = aiMonkeystoneAction;
}
void aiMonkeystoneAction(AIEntity *e) {
if (!e->onScreen)
return;
AIEntity *p = g_hdb->_ai->getPlayer();
if (abs(p->x - e->x) < 16 && abs(p->y - e->y) < 16 && e->level == p->level) {
if (e->luaFuncUse[0])
g_hdb->_lua->callFunction(e->luaFuncUse, 0);
g_hdb->_ai->addToInventory(e);
aiMonkeystoneUse(NULL);
}
}
void aiMonkeystoneInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiMonkeystoneUse(AIEntity *e) {
int val = g_hdb->_ai->getMonkeystoneAmount();
sprintf(monkBuff, "You have %d Monkeystone", val);
if (val > 1)
strcat(monkBuff, "s");
strcat(monkBuff, "!");
g_hdb->_sound->playSound(SND_GET_MONKEYSTONE);
g_hdb->_window->openMessageBar(monkBuff, kMsgDelay);
// have we unlocked a secret star(tm)???
if (val == 7) {
g_hdb->_window->openMessageBar("Red Star is Ready!", kMsgDelay * 2);
g_hdb->setStarsMonkeystone7(STARS_MONKEYSTONE_7);
g_hdb->_menu->writeConfig();
g_hdb->_gfx->turnOnBonusStars(0);
}
if (val == 14) {
g_hdb->_window->openMessageBar("Green Star is GO!", kMsgDelay * 2);
g_hdb->setStarsMonkeystone14(STARS_MONKEYSTONE_14);
g_hdb->_menu->writeConfig();
g_hdb->_gfx->turnOnBonusStars(1);
}
if (val == 21) {
g_hdb->_window->openMessageBar("Blue Star is Born!", kMsgDelay * 2);
g_hdb->setStarsMonkeystone21(STARS_MONKEYSTONE_21);
g_hdb->_menu->writeConfig();
g_hdb->_gfx->turnOnBonusStars(2);
}
}
void aiGemAction(AIEntity *e) {
AIEntity *p;
int tolerance;
e->animFrame++;
if (e->animFrame >= e->standdownFrames) {
e->animFrame = 0;
// every 4th frame, check for player collision &
// add to inventory if it happens
p = g_hdb->_ai->getPlayer();
tolerance = 16;
if (g_hdb->_ai->playerRunning())
tolerance = 24;
if (e->onScreen && abs(p->x - e->x) < tolerance && abs(p->y - e->y) < tolerance && e->level == p->level) {
g_hdb->_ai->addAnimateTarget(e->x, e->y, 0, 3, ANIM_NORMAL, false, false, GEM_FLASH);
g_hdb->_ai->addToInventory(e);
g_hdb->_sound->playSound(SND_GET_GEM);
return;
}
}
e->draw = e->standdownGfx[e->animFrame];
}
void aiGemWhiteInit(AIEntity *e) {
e->aiAction = aiGemAction;
}
void aiGemWhiteInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiGooCupUse(AIEntity *e) {
g_hdb->_window->openMessageBar("Got a... cup of goo.", kMsgDelay);
}
void aiGooCupInit(AIEntity *e) {
e->aiUse = aiGooCupUse;
e->aiAction = aiGetItemAction;
}
void aiGooCupInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiVortexianAction(AIEntity *e) {
// anim the alpha blending : down to 32, up to 180, back down...
e->value2 += e->value1;
if ((e->value2 & 0xff) > 128) {
e->value2 = (e->value2 & 0xff00) | 128;
e->value1 = -e->value1;
} else if ((e->value2 & 0xff) < 32) {
e->value2 = (e->value2 & 0xff00) | 32;
e->value1 = -e->value1;
}
// anim the shape
e->animFrame++;
if (e->animFrame >= e->standdownFrames) {
e->animFrame = 0;
// every 4th frame, check for player collision &
// do an autosave
AIEntity *p = g_hdb->_ai->getPlayer();
if (abs(p->x - e->x) < 4 && abs(p->y - e->y) < 4) {
if (!(e->value2 & 0xff00)) {
// let's make sure we don't autosave every frikken second!
e->value2 |= 0xff00;
g_hdb->saveWhenReady(kAutoSaveSlot);
g_hdb->_window->openMessageBar("Saving progress at Vortexian...", 1);
}
} else
e->value2 &= 0x00ff;
}
e->draw = e->standdownGfx[e->animFrame];
}
void aiVortexianUse(AIEntity *e) {
}
void aiVortexianInit(AIEntity *e) {
e->aiUse = aiVortexianUse;
e->aiAction = aiVortexianAction;
e->value1 = 5;
e->value2 = 128;
}
void aiVortexianInit2(AIEntity *e) {
e->draw = e->standdownGfx[0];
}
void aiNoneInit(AIEntity *e) {
}
// Utility Functions
void aiAnimateStanddown(AIEntity *e, int speed) {
if (e->value2-- > 0)
return;
e->value2 = speed;
if (e->type == AI_GUY && e->animFrame > 0)
e->value2 = 0;
e->draw = e->standdownGfx[e->animFrame];
e->animFrame++;
if (e->animFrame >= e->standdownFrames)
e->animFrame = 0;
}
void aiGenericAction(AIEntity *e) {
if (!e->goalX)
g_hdb->_ai->findPath(e);
else if (onEvenTile(e->x, e->y))
g_hdb->_sound->playSound(SND_FOOTSTEPS);
g_hdb->_ai->animateEntity(e);
}
void aiGetItemAction(AIEntity *e) {
if (!e->onScreen)
return;
AIEntity *p = g_hdb->_ai->getPlayer();
if (abs(p->x - e->x) < 16 && abs(p->y - e->y) < 16 && e->level == p->level) {
if (e->aiUse)
e->aiUse(e);
if (e->luaFuncUse[0])
g_hdb->_lua->callFunction(e->luaFuncUse, 0);
g_hdb->_ai->getItemSound(e->type);
g_hdb->_ai->addToInventory(e);
}
}
} // End of Namespace