mirror of
https://github.com/pret/pmd-red.git
synced 2026-04-25 07:28:17 -05:00
515 lines
16 KiB
C
515 lines
16 KiB
C
#include "global.h"
|
|
#include "globaldata.h"
|
|
#include "dungeon_mon_sprite_render.h"
|
|
#include "constants/direction.h"
|
|
#include "constants/status.h"
|
|
#include "constants/ability.h"
|
|
#include "constants/type.h"
|
|
#include "constants/dungeon.h"
|
|
#include "constants/iq_skill.h"
|
|
#include "structs/str_dungeon.h"
|
|
#include "dungeon_vram.h"
|
|
#include "dungeon_8041AD0.h"
|
|
#include "code_805D8C8.h"
|
|
#include "dungeon_config.h"
|
|
#include "dungeon_items.h"
|
|
#include "dungeon_map_access.h"
|
|
#include "dungeon_message.h"
|
|
#include "dungeon_logic.h"
|
|
#include "dungeon_random.h"
|
|
#include "dungeon_misc.h"
|
|
#include "dungeon_util.h"
|
|
#include "dungeon_data.h"
|
|
#include "dungeon_pokemon_sprites.h"
|
|
#include "exclusive_pokemon.h"
|
|
#include "move_orb_effects_1.h"
|
|
#include "pokemon.h"
|
|
#include "position_util.h"
|
|
#include "random.h"
|
|
#include "sprite.h"
|
|
#include "text_util.h"
|
|
#include "sprite.h"
|
|
#include "random.h"
|
|
|
|
static const u8 gUnknown_8106EC8[][13] = {
|
|
{0, 1, 7, 7, 7, 5, 6, 7, 7, 7, 7, 7, 7},
|
|
{7, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7, 7, 7},
|
|
{7, 7, 7, 7, 7, 5, 6, 7, 7, 7, 7, 11, 7},
|
|
};
|
|
|
|
static const u8 gUnknown_8106EEF[] = {0x03, 0x04, 0x05, 0x0};
|
|
|
|
static u8 GetEntityShadowIndex(Entity *entity);
|
|
|
|
void UpdateMonsterSprite(Entity *entity)
|
|
{
|
|
s32 x, y, y2;
|
|
bool8 var_3C;
|
|
bool8 decoySprite;
|
|
s32 var_34;
|
|
DungeonPos pos1;
|
|
DungeonPos posArray[4];
|
|
u32 statusSprites;
|
|
bool8 r4;
|
|
u8 shadowIndex;
|
|
unkStruct_2039DB0 spriteMasks;
|
|
s32 xSprite, ySprite;
|
|
|
|
EntityInfo *entInfo = GetEntInfo(entity);
|
|
if (gDungeon->unk181e8.cameraTarget == entity) {
|
|
decoySprite = FALSE;
|
|
}
|
|
else {
|
|
decoySprite = gDungeon->unk181e8.hallucinating;
|
|
}
|
|
|
|
if (entInfo->curseClassStatus.status == STATUS_DECOY) {
|
|
decoySprite = TRUE;
|
|
}
|
|
|
|
if (entity->axObj.unk43_animId2 == entity->axObj.unk42_animId1 && entity->axObj.unk45_orientation == entity->axObj.unk44_direction1 && entity->axObj.unk47 == 0) {
|
|
bool8 r2 = FALSE;
|
|
|
|
if (!AxFlag8000_Not2000(&entity->axObj.axdata))
|
|
r2 = TRUE;
|
|
|
|
if (r2) {
|
|
s32 r0;
|
|
s32 r3 = sub_806CEBC(entity);
|
|
entity->unk21 = 1;
|
|
if (entInfo->unkFE == 99) {
|
|
if (entity->axObj.unk43_animId2 <= 12) {
|
|
s32 r2;
|
|
if (entInfo->bideClassStatus.status == STATUS_BIDE) {
|
|
r2 = 2;
|
|
}
|
|
else if (entity->unk23 < 3) {
|
|
r2 = 0;
|
|
}
|
|
else {
|
|
r2 = 1;
|
|
}
|
|
|
|
r0 = gUnknown_8106EC8[r2][entity->axObj.unk43_animId2];
|
|
if (r0 == 7) {
|
|
r0 = r3;
|
|
}
|
|
}
|
|
else {
|
|
r0 = 99;
|
|
}
|
|
}
|
|
else {
|
|
r0 = entInfo->unkFE;
|
|
}
|
|
|
|
if (r0 != 99) {
|
|
entity->axObj.unk42_animId1 = r0;
|
|
entity->axObj.unk44_direction1 = entity->axObj.unk45_orientation & DIRECTION_MASK;
|
|
entity->axObj.unk47 = 1;
|
|
if (entity->axObj.unk42_animId1 == 6 && ++entity->axObj.unk46 == 16) {
|
|
entity->axObj.unk42_animId1 = r3;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (entity->axObj.unk43_animId2 != entity->axObj.unk42_animId1 || entity->axObj.unk45_orientation != entity->axObj.unk44_direction1 || entity->axObj.unk47 != 0) {
|
|
s32 r7;
|
|
|
|
entity->axObj.unk43_animId2 = entity->axObj.unk42_animId1;
|
|
entity->axObj.unk45_orientation = entity->axObj.unk44_direction1;
|
|
entity->axObj.unk47 = 0;
|
|
r7 = entity->axObj.unk40_maybeAnimTimer;
|
|
if (sub_808DA44(entInfo->apparentID, entity->axObj.unk42_animId1)) {
|
|
r7 = 0;
|
|
}
|
|
|
|
if (!decoySprite) {
|
|
s32 rnd = Rand32Bit() & 3;
|
|
AxResInitFile(&entity->axObj.axdata, entity->axObj.spriteFile, entity->axObj.unk42_animId1, entity->axObj.unk44_direction1, r7, rnd, FALSE);
|
|
}
|
|
else {
|
|
OpenedFile *spriteData = GetSpriteData(MONSTER_DECOY);
|
|
s32 rnd = Rand32Bit() & 3;
|
|
AxResInitFile(&entity->axObj.axdata, spriteData, entity->axObj.unk42_animId1, entity->axObj.unk44_direction1, r7, rnd, FALSE);
|
|
}
|
|
|
|
if (entity->axObj.unk42_animId1 != 6) {
|
|
entity->axObj.unk46 = 0;
|
|
}
|
|
}
|
|
|
|
if (gDungeon->unk1356C) {
|
|
if (entity->axObj.unk43_animId2 != 7 || GetMovementType(entInfo->apparentID) == 2) {
|
|
if (entInfo->unk15C != 0) {
|
|
if (entInfo->unk160 == 0) {
|
|
if (entInfo->unk15F != 0) {
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
}
|
|
else {
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (entInfo->frozenClassStatus.status != STATUS_FROZEN && entInfo->frozenClassStatus.status != STATUS_PETRIFIED) {
|
|
if (gDungeon->unk644.unk28 != 0 && gDungeon->unk1BDD4.unk1C05F == 0) {
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
}
|
|
else if ((entity->axObj.unk43_animId2 == 0 || entity->axObj.unk43_animId2 == 7) && GetEntInfo(entity)->speedStage > 1) {
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
}
|
|
RunAxAnimationFrame(&entity->axObj.axdata);
|
|
}
|
|
}
|
|
|
|
if (entity->pixelPos.x == entity->prevPixelPos.x && entity->pixelPos.y == entity->prevPixelPos.y) {
|
|
if (entity->unk23 < 10) {
|
|
entity->unk23++;
|
|
}
|
|
}
|
|
else {
|
|
entity->unk23 = 0;
|
|
}
|
|
|
|
entity->prevPixelPos.x = entity->pixelPos.x;
|
|
entity->prevPixelPos.y = entity->pixelPos.y;
|
|
|
|
x = (entity->pixelPos.x / 256) - gDungeon->unk181e8.cameraPixelPos.x;
|
|
y = (((entity->pixelPos.y - entity->unk1C) - entInfo->unk174) / 256) - gDungeon->unk181e8.cameraPixelPos.y;
|
|
y2 = (entity->pixelPos.y / 256) - gDungeon->unk181e8.cameraPixelPos.y;
|
|
y2 /= 2;
|
|
if (entInfo->unk156 == 0) {
|
|
y2--;
|
|
}
|
|
|
|
if (entInfo->unk15C == 0) {
|
|
var_3C = sub_8042768(entity);
|
|
}
|
|
else {
|
|
if (entInfo->unk15D != 0) {
|
|
if (gDungeonFramesCounter & 4) {
|
|
x++;
|
|
}
|
|
else {
|
|
x--;
|
|
}
|
|
}
|
|
var_3C = (entInfo->unk15E == 0);
|
|
}
|
|
|
|
pos1.x = entity->pixelPos.x / 256;
|
|
pos1.y = ((entity->pixelPos.y - entity->unk1C) - entInfo->unk174) / 256;
|
|
|
|
sub_8005700(posArray, &entity->axObj.axdata);
|
|
UpdateDungeonPokemonSprite2(entInfo->dungeonSpriteId, &pos1, posArray, gDungeon->unk181e8.priority);
|
|
|
|
statusSprites = EntityGetStatusSprites(entity);
|
|
UpdateDungeonPokemonSprite(entInfo->dungeonSpriteId, entInfo->apparentID, statusSprites, (var_3C && entInfo->unk14C));
|
|
|
|
sub_8042EC8(entity, y2);
|
|
if (entInfo->unk15C == 0) {
|
|
if (entInfo->unkFF == 1) {
|
|
if (entInfo->unk174 <= IntToF248(199.999)) {
|
|
entInfo->unk174 += IntToF248(8);
|
|
if (entInfo->unk174 > IntToF248(200)) {
|
|
entInfo->unk174 = IntToF248(200);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
entInfo->unk174 -= IntToF248(12);
|
|
if (entInfo->unk174 < IntToF248(0)) {
|
|
entInfo->unk174 = IntToF248(0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!var_3C)
|
|
return;
|
|
|
|
r4 = FALSE;
|
|
shadowIndex = GetEntityShadowIndex(entity);
|
|
|
|
spriteMasks.unk0 = 0xF3FF;
|
|
spriteMasks.unk2 = 0xFFFF;
|
|
spriteMasks.unk4 = 0xF3FF;
|
|
spriteMasks.unk6 = 0;
|
|
spriteMasks.unk8 = 0;
|
|
spriteMasks.unkA = gDungeon->unk181e8.priority << 10;
|
|
|
|
if (entInfo->isNotTeamMember && (entInfo->apparentID == MONSTER_DEOXYS_ATTACK || entInfo->apparentID == MONSTER_DEOXYS_DEFENSE || entInfo->apparentID == MONSTER_DEOXYS_SPEED)) {
|
|
r4 = TRUE;
|
|
}
|
|
if (entInfo->invisibleClassStatus.status == STATUS_INVISIBLE && !gDungeon->unk181e8.showInvisibleTrapsMonsters) {
|
|
r4 = TRUE;
|
|
}
|
|
if (r4) {
|
|
spriteMasks.unk6 |= 0x400;
|
|
}
|
|
|
|
var_34 = 0;
|
|
if (!entInfo->isNotTeamMember || entInfo->curseClassStatus.status == STATUS_DECOY) {
|
|
var_34 = 1;
|
|
}
|
|
if (IsExperienceLocked(entInfo->joinedAt.id) || entInfo->monsterBehavior == 1) {
|
|
var_34 = 1;
|
|
}
|
|
|
|
if (entInfo->unkFF != 2) {
|
|
s32 overworldPal;
|
|
|
|
if (entInfo->frozenClassStatus.status == STATUS_PETRIFIED || entInfo->burnClassStatus.status == STATUS_PARALYSIS || entInfo->frozenClassStatus.status == STATUS_SHADOW_HOLD) {
|
|
x += gDungeonFramesCounter & 2;
|
|
}
|
|
|
|
if (decoySprite) {
|
|
overworldPal = GetPokemonOverworldPalette(MONSTER_DECOY, FALSE);
|
|
}
|
|
else {
|
|
overworldPal = GetPokemonOverworldPalette(entInfo->apparentID, FALSE);
|
|
}
|
|
|
|
if (entity->unk22 == 0) {
|
|
DoAxFrame_800558C(&entity->axObj.axdata, x, y, y2, overworldPal, &spriteMasks);
|
|
}
|
|
else if (entity->unk22 == 1 && (gDungeonFramesCounter & 1)) {
|
|
DoAxFrame_800558C(&entity->axObj.axdata, x, y, y2, overworldPal, &spriteMasks);
|
|
}
|
|
}
|
|
|
|
entInfo->pixelPos.x = (entity->pixelPos.x / 256) + entity->axObj.axdata.sub1.shadow.x;
|
|
entInfo->pixelPos.y = (entity->pixelPos.y / 256) + entity->axObj.axdata.sub1.shadow.y;
|
|
|
|
xSprite = entInfo->pixelPos.x - gDungeon->unk181e8.cameraPixelPos.x;
|
|
ySprite = entInfo->pixelPos.y - gDungeon->unk181e8.cameraPixelPos.y;
|
|
if (xSprite >= -32 && ySprite >= -32 && xSprite <= 271 && ySprite <= 191 && shadowIndex != 6 && entity->unk22 == 0) {
|
|
struct unkStruct_202ED28 *spriteStructPtr = &gUnknown_202ED28[var_34][shadowIndex];
|
|
if (entInfo->unk156 != 0) {
|
|
SpriteSetX(&spriteStructPtr->sprite, xSprite + spriteStructPtr->pos.x);
|
|
SpriteSetY(&spriteStructPtr->sprite, ySprite + spriteStructPtr->pos.y);
|
|
|
|
AddSprite(&spriteStructPtr->sprite, 0, NULL, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_806CC10(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < DUNGEON_MAX_POKEMON; i++) {
|
|
Entity *entity = gDungeon->activePokemon[i];
|
|
|
|
if (EntityIsValid(entity)) {
|
|
EntityInfo *entityInfo = GetEntInfo(entity);
|
|
|
|
if (entityInfo->unk166 != 0) {
|
|
entityInfo->unk166--;
|
|
if ((entityInfo->unk166 & 1) == 0) // If value is even:
|
|
sub_806CDD4(entity, 0, (entityInfo->action.direction - 1) & DIRECTION_MASK);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_806CC70(void)
|
|
{
|
|
s32 i;
|
|
Entity *entity;
|
|
|
|
for (i = 0; i < DUNGEON_MAX_POKEMON; i++) {
|
|
entity = gDungeon->activePokemon[i];
|
|
|
|
if (EntityIsValid(entity))
|
|
sub_806CCB4(entity, sub_806CEBC(entity));
|
|
}
|
|
}
|
|
|
|
void sub_806CCB4(Entity *entity, u8 a1)
|
|
{
|
|
s32 sVar1;
|
|
bool8 flag;
|
|
EntityInfo *info;
|
|
|
|
info = GetEntInfo(entity);
|
|
flag = gDungeon->unk181e8.hallucinating;
|
|
|
|
if (entity == gDungeon->unk181e8.cameraTarget)
|
|
flag = FALSE;
|
|
|
|
entity->axObj.unk43_animId2 = a1;
|
|
entity->axObj.unk42_animId1 = a1;
|
|
entity->axObj.unk45_orientation = info->action.direction;
|
|
entity->axObj.unk44_direction1 = info->action.direction;
|
|
entity->axObj.unk47 = 0;
|
|
sVar1 = entity->axObj.unk40_maybeAnimTimer;
|
|
|
|
if (info->curseClassStatus.status != STATUS_DECOY && !flag)
|
|
AxResInitFile(&entity->axObj.axdata,
|
|
entity->axObj.spriteFile, entity->axObj.unk42_animId1,
|
|
entity->axObj.unk44_direction1, sVar1,
|
|
Rand32Bit() & 3, FALSE);
|
|
else
|
|
AxResInitFile(&entity->axObj.axdata,
|
|
GetSpriteData(MONSTER_DECOY),
|
|
entity->axObj.unk42_animId1,
|
|
entity->axObj.unk44_direction1, sVar1, Rand32Bit() & 3,
|
|
FALSE);
|
|
|
|
entity->axObj.unk46 = 0;
|
|
}
|
|
|
|
void sub_806CD90(void)
|
|
{
|
|
s32 i;
|
|
Entity *entity;
|
|
|
|
for (i = 0; i < DUNGEON_MAX_POKEMON; i++) {
|
|
entity = gDungeon->activePokemon[i];
|
|
|
|
if (EntityIsValid(entity))
|
|
sub_806CCB4(entity, sub_806CEBC(entity));
|
|
}
|
|
}
|
|
|
|
void sub_806CDD4(Entity *entity, u8 animId, u32 direction)
|
|
{
|
|
if (GetEntityType(entity) == ENTITY_MONSTER) {
|
|
entity->axObj.unk42_animId1 = animId;
|
|
|
|
if (direction < NUM_DIRECTIONS)
|
|
entity->axObj.unk44_direction1 = direction;
|
|
}
|
|
}
|
|
|
|
void sub_806CDFC(Entity *entity, u8 a1, u32 direction)
|
|
{
|
|
if (GetEntityType(entity) == ENTITY_MONSTER) {
|
|
if (entity->axObj.unk43_animId2 == a1 && entity->axObj.unk45_orientation == direction)
|
|
return;
|
|
sub_806CDD4(entity, a1, direction);
|
|
}
|
|
}
|
|
|
|
void sub_806CE34(Entity *entity, u32 newDir)
|
|
{
|
|
if (GetEntityType(entity) == ENTITY_MONSTER) {
|
|
entity->axObj.unk42_animId1 = sub_806CEBC(entity);
|
|
|
|
if (newDir < NUM_DIRECTIONS) {
|
|
GetEntInfo(entity)->action.direction = newDir & DIRECTION_MASK;
|
|
entity->axObj.unk44_direction1 = newDir & DIRECTION_MASK;
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_806CE68(Entity *entity, u32 newDir)
|
|
{
|
|
if (GetEntityType(entity) == ENTITY_MONSTER) {
|
|
entity->axObj.unk42_animId1 = sub_806CEBC(entity);
|
|
|
|
if (newDir < NUM_DIRECTIONS)
|
|
entity->axObj.unk44_direction1 = newDir;
|
|
}
|
|
}
|
|
|
|
void sub_806CE94(Entity *entity, u32 newDir)
|
|
{
|
|
if (GetEntityType(entity) == ENTITY_MONSTER) {
|
|
entity->axObj.unk42_animId1 = 6;
|
|
|
|
if (newDir < NUM_DIRECTIONS)
|
|
entity->axObj.unk44_direction1 = newDir;
|
|
}
|
|
}
|
|
|
|
u8 sub_806CEBC(Entity *entity)
|
|
{
|
|
u8 sleepClassStatus;
|
|
EntityInfo *entityInfo;
|
|
|
|
entityInfo = GetEntInfo(entity);
|
|
sleepClassStatus = entityInfo->sleepClassStatus.status;
|
|
|
|
if (sleepClassStatus == STATUS_SLEEP || sleepClassStatus == STATUS_NAPPING || sleepClassStatus == STATUS_NIGHTMARE) {
|
|
if (entityInfo->apparentID != MONSTER_SUDOWOODO || entityInfo->sleepClassStatus.turns != 0x7F)
|
|
return 5;
|
|
else
|
|
return 7;
|
|
}
|
|
if (entityInfo->bideClassStatus.status == STATUS_BIDE)
|
|
return 11;
|
|
return 7;
|
|
}
|
|
|
|
void sub_806CEFC(Entity *entity, u32 newDir)
|
|
{
|
|
GetEntInfo(entity)->action.direction = newDir & DIRECTION_MASK;
|
|
sub_806CE68(entity, newDir & DIRECTION_MASK);
|
|
}
|
|
|
|
void sub_806CF18(Entity *entity)
|
|
{
|
|
s32 i;
|
|
EntityInfo *entityInfo;
|
|
|
|
if (!EntityIsValid(entity))
|
|
return;
|
|
|
|
entityInfo = GetEntInfo(entity);
|
|
for (i = 0; i < 100; i++) {
|
|
DungeonRunFrameActions(33);
|
|
|
|
if (!sub_808DA44(entityInfo->apparentID, entity->axObj.unk43_animId2))
|
|
break;
|
|
}
|
|
}
|
|
|
|
static u8 GetEntityShadowIndex(Entity *entity)
|
|
{
|
|
return GetEntInfo(entity)->shadowIndex;
|
|
}
|
|
|
|
void DetermineAllMonsterShadow(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < DUNGEON_MAX_POKEMON; i++) {
|
|
Entity *entity = gDungeon->activePokemon[i];
|
|
|
|
if (EntityIsValid(entity))
|
|
DetermineMonsterShadow(entity);
|
|
}
|
|
}
|
|
|
|
u32 DetermineMonsterShadow(Entity *entity)
|
|
{
|
|
const Tile *mapTile = GetTileAtEntitySafe(entity);
|
|
u16 terrainType = GetTerrainType(mapTile);
|
|
EntityInfo *entityInfo = GetEntInfo(entity);
|
|
u32 shadowSize = GetShadowSize(entityInfo->apparentID);
|
|
|
|
if (terrainType == (TERRAIN_TYPE_NORMAL | TERRAIN_TYPE_SECONDARY))
|
|
return 6;
|
|
|
|
if (terrainType == TERRAIN_TYPE_NORMAL) {
|
|
if (IsWaterTileset())
|
|
shadowSize = gUnknown_8106EEF[shadowSize];
|
|
}
|
|
else if (terrainType == TERRAIN_TYPE_SECONDARY && gDungeonWaterType[gDungeon->tileset] != DUNGEON_WATER_TYPE_LAVA)
|
|
shadowSize = gUnknown_8106EEF[shadowSize];
|
|
|
|
entityInfo->shadowIndex = shadowSize;
|
|
return shadowSize;
|
|
}
|