Improve animation.cc readability

This commit is contained in:
Alexander Batalov 2022-12-23 15:49:56 +03:00
parent 9a6d45541f
commit 9c34b26fec
3 changed files with 198 additions and 199 deletions

View File

@ -68,8 +68,7 @@ typedef enum AnimationKind {
ANIM_KIND_TOGGLE_OUTLINE = 24, ANIM_KIND_TOGGLE_OUTLINE = 24,
ANIM_KIND_ANIMATE_FOREVER = 25, ANIM_KIND_ANIMATE_FOREVER = 25,
ANIM_KIND_PING = 26, ANIM_KIND_PING = 26,
ANIM_KIND_27 = 27, ANIM_KIND_CONTINUE = 28,
ANIM_KIND_NOOP = 28,
// New animation to update both light distance and intensity. Required to // New animation to update both light distance and intensity. Required to
// impement Sfall's explosion light effects without resorting to hackery. // impement Sfall's explosion light effects without resorting to hackery.
@ -230,8 +229,8 @@ typedef struct PathNode {
int from; int from;
// actual type is likely char // actual type is likely char
int rotation; int rotation;
int field_C; int estimate;
int field_10; int cost;
} PathNode; } PathNode;
// TODO: I don't know what `sad` means, but it's definitely better than // TODO: I don't know what `sad` means, but it's definitely better than
@ -255,7 +254,7 @@ typedef struct AnimationSad {
int field_24; int field_24;
union { union {
unsigned char rotations[3200]; unsigned char rotations[3200];
STRUCT_530014_28 field_28[200]; StraightPathNode straightPathNodeList[200];
}; };
} AnimationSad; } AnimationSad;
@ -269,8 +268,8 @@ static int _anim_set_end(int a1);
static bool canUseDoor(Object* critter, Object* door); static bool canUseDoor(Object* critter, Object* door);
static int _idist(int a1, int a2, int a3, int a4); static int _idist(int a1, int a2, int a3, int a4);
static int _tile_idistance(int tile1, int tile2); static int _tile_idistance(int tile1, int tile2);
static int animateMoveObjectToObject(Object* from, Object* to, int a3, int anim, int animationSequenceIndex); static int animateMoveObjectToObject(Object* from, Object* to, int actionPoints, int anim, int animationSequenceIndex);
static int animateMoveObjectToTile(Object* obj, int tile_num, int elev, int a4, int anim, int animationSequenceIndex); static int animateMoveObjectToTile(Object* obj, int tile, int elev, int actionPoints, int anim, int animationSequenceIndex);
static int _anim_move(Object* obj, int tile, int elev, int a3, int anim, int a5, int animationSequenceIndex); static int _anim_move(Object* obj, int tile, int elev, int a3, int anim, int a5, int animationSequenceIndex);
static int animateMoveObjectToTileStraight(Object* obj, int tile, int elevation, int anim, int animationSequenceIndex, int flags); static int animateMoveObjectToTileStraight(Object* obj, int tile, int elevation, int anim, int animationSequenceIndex, int flags);
static int _anim_move_on_stairs(Object* obj, int tile, int elevation, int anim, int animationSequenceIndex); static int _anim_move_on_stairs(Object* obj, int tile, int elevation, int anim, int animationSequenceIndex);
@ -302,12 +301,6 @@ static bool gAnimationInStop = false;
// 0x510728 // 0x510728
static bool _anim_in_bk = false; static bool _anim_in_bk = false;
// 0x510730
static unsigned int _last_time_ = 0;
// 0x510734
static unsigned int _next_time = 0;
// 0x530014 // 0x530014
static AnimationSad gAnimationSads[ANIMATION_SAD_LIST_CAPACITY]; static AnimationSad gAnimationSads[ANIMATION_SAD_LIST_CAPACITY];
@ -326,9 +319,6 @@ static PathNode gOpenPathNodeList[2000];
// 0x56C7DC // 0x56C7DC
static int gAnimationDescriptionCurrentIndex; static int gAnimationDescriptionCurrentIndex;
// 0x56C7E0
static Object* dword_56C7E0[100];
// anim_init // anim_init
// 0x413A20 // 0x413A20
void animationInit() void animationInit()
@ -498,11 +488,11 @@ int reg_anim_end()
animationSequence->flags |= ANIM_SEQ_COMBAT_ANIM_STARTED; animationSequence->flags |= ANIM_SEQ_COMBAT_ANIM_STARTED;
} }
int v1 = gAnimationSequenceCurrentIndex; int index = gAnimationSequenceCurrentIndex;
gAnimationSequenceCurrentIndex = -1; gAnimationSequenceCurrentIndex = -1;
if (!(animationSequence->flags & ANIM_SEQ_0x10)) { if (!(animationSequence->flags & ANIM_SEQ_0x10)) {
_anim_set_continue(v1, 1); _anim_set_continue(index, 1);
} }
return 0; return 0;
@ -1288,10 +1278,10 @@ int animationRegisterPlaySoundEffect(Object* owner, const char* soundEffectName,
if (animationDescription->param1 != NULL) { if (animationDescription->param1 != NULL) {
animationDescription->callback = (AnimationCallback*)_gsnd_anim_sound; animationDescription->callback = (AnimationCallback*)_gsnd_anim_sound;
} else { } else {
animationDescription->kind = ANIM_KIND_NOOP; animationDescription->kind = ANIM_KIND_CONTINUE;
} }
} else { } else {
animationDescription->kind = ANIM_KIND_NOOP; animationDescription->kind = ANIM_KIND_CONTINUE;
} }
animationDescription->artCacheKey = NULL; animationDescription->artCacheKey = NULL;
@ -1527,7 +1517,7 @@ static int animationRunSequence(int animationSequenceIndex)
rc = _anim_set_continue(animationSequenceIndex, 0); rc = _anim_set_continue(animationSequenceIndex, 0);
} }
break; break;
case ANIM_KIND_NOOP: case ANIM_KIND_CONTINUE:
rc = _anim_set_continue(animationSequenceIndex, 0); rc = _anim_set_continue(animationSequenceIndex, 0);
break; break;
default: default:
@ -1731,10 +1721,10 @@ int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotation
} }
bool isCritter = false; bool isCritter = false;
int kt = 0; int critterType = 0;
if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) { if (PID_TYPE(object->pid) == OBJ_TYPE_CRITTER) {
isCritter = true; isCritter = true;
kt = critterGetKillType(object); critterType = critterGetKillType(object);
} }
bool isNotInCombat = !isInCombat(); bool isNotInCombat = !isInCombat();
@ -1746,8 +1736,8 @@ int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotation
gOpenPathNodeList[0].tile = from; gOpenPathNodeList[0].tile = from;
gOpenPathNodeList[0].from = -1; gOpenPathNodeList[0].from = -1;
gOpenPathNodeList[0].rotation = 0; gOpenPathNodeList[0].rotation = 0;
gOpenPathNodeList[0].field_C = _tile_idistance(from, to); gOpenPathNodeList[0].estimate = _tile_idistance(from, to);
gOpenPathNodeList[0].field_10 = 0; gOpenPathNodeList[0].cost = 0;
for (int index = 1; index < 2000; index += 1) { for (int index = 1; index < 2000; index += 1) {
gOpenPathNodeList[index].tile = -1; gOpenPathNodeList[index].tile = -1;
@ -1770,7 +1760,7 @@ int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotation
PathNode* curr = &(gOpenPathNodeList[index]); PathNode* curr = &(gOpenPathNodeList[index]);
if (curr->tile != -1) { if (curr->tile != -1) {
v12++; v12++;
if (v63 == -1 || (curr->field_C + curr->field_10) < (prev->field_C + prev->field_10)) { if (v63 == -1 || (curr->estimate + curr->cost) < (prev->estimate + prev->cost)) {
prev = curr; prev = curr;
v63 = index; v63 = index;
} }
@ -1841,27 +1831,27 @@ int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotation
int newY; int newY;
tileToScreenXY(tile, &newX, &newY, object->elevation); tileToScreenXY(tile, &newX, &newY, object->elevation);
v27->field_C = _idist(newX, newY, toScreenX, toScreenY); v27->estimate = _idist(newX, newY, toScreenX, toScreenY);
v27->field_10 = temp.field_10 + 50; v27->cost = temp.cost + 50;
if (isNotInCombat && temp.rotation != rotation) { if (isNotInCombat && temp.rotation != rotation) {
v27->field_10 += 10; v27->cost += 10;
} }
if (isCritter) { if (isCritter) {
Object* o = objectFindFirstAtLocation(object->elevation, v27->tile); Object* o = objectFindFirstAtLocation(object->elevation, v27->tile);
while (o != NULL) { while (o != NULL) {
if (o->pid >= 0x20003D9 && o->pid <= 0x20003DC) { if (o->pid >= FIRST_RADIOACTIVE_GOO_PID && o->pid <= LAST_RADIOACTIVE_GOO_PID) {
break; break;
} }
o = objectFindNextAtLocation(); o = objectFindNextAtLocation();
} }
if (o != NULL) { if (o != NULL) {
if (kt == KILL_TYPE_GECKO) { if (critterType == KILL_TYPE_GECKO) {
v27->field_10 += 100; v27->cost += 100;
} else { } else {
v27->field_10 += 400; v27->cost += 400;
} }
} }
} }
@ -1949,21 +1939,21 @@ static int _tile_idistance(int tile1, int tile2)
} }
// 0x4163AC // 0x4163AC
int _make_straight_path(Object* a1, int from, int to, STRUCT_530014_28* pathNodes, Object** a5, int a6) int _make_straight_path(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6)
{ {
return _make_straight_path_func(a1, from, to, pathNodes, a5, a6, _obj_blocking_at); return _make_straight_path_func(a1, from, to, straightPathNodeList, obstaclePtr, a6, _obj_blocking_at);
} }
// TODO: Rather complex, but understandable, needs testing. // TODO: Rather complex, but understandable, needs testing.
// //
// 0x4163C8 // 0x4163C8
int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4, Object** a5, int a6, Object* (*a7)(Object*, int, int)) int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback)
{ {
if (a5 != NULL) { if (obstaclePtr != NULL) {
Object* v11 = a7(a1, from, a1->elevation); Object* obstacle = callback(a1, from, a1->elevation);
if (v11 != NULL) { if (obstacle != NULL) {
if (v11 != *a5 && (a6 != 32 || (v11->flags & OBJECT_SHOOT_THRU) == 0)) { if (obstacle != *obstaclePtr && (a6 != 32 || (obstacle->flags & OBJECT_SHOOT_THRU) == 0)) {
*a5 = v11; *obstaclePtr = obstacle;
return 0; return 0;
} }
} }
@ -1983,24 +1973,26 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
int stepX; int stepX;
int deltaX = toX - fromX; int deltaX = toX - fromX;
if (deltaX > 0) if (deltaX > 0) {
stepX = 1; stepX = 1;
else if (deltaX < 0) } else if (deltaX < 0) {
stepX = -1; stepX = -1;
else } else {
stepX = 0; stepX = 0;
}
int stepY; int stepY;
int deltaY = toY - fromY; int deltaY = toY - fromY;
if (deltaY > 0) if (deltaY > 0) {
stepY = 1; stepY = 1;
else if (deltaY < 0) } else if (deltaY < 0) {
stepY = -1; stepY = -1;
else } else {
stepY = 0; stepY = 0;
}
int v48 = 2 * abs(toX - fromX); int ddx = 2 * abs(toX - fromX);
int v47 = 2 * abs(toY - fromY); int ddy = 2 * abs(toY - fromY);
int tileX = fromX; int tileX = fromX;
int tileY = fromY; int tileY = fromY;
@ -2010,8 +2002,8 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
int v22 = 0; int v22 = 0;
int tile; int tile;
if (v48 <= v47) { if (ddx <= ddy) {
int middle = v48 - v47 / 2; int middle = ddx - ddy / 2;
while (true) { while (true) {
tile = tileFromScreenXY(tileX, tileY, a1->elevation); tile = tileFromScreenXY(tileX, tileY, a1->elevation);
@ -2021,8 +2013,8 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
return 0; return 0;
} }
if (a4 != NULL) { if (straightPathNodeList != NULL) {
STRUCT_530014_28* pathNode = &(a4[pathNodeIndex]); StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = a1->elevation; pathNode->elevation = a1->elevation;
@ -2036,26 +2028,26 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
} }
if (tileY == toY) { if (tileY == toY) {
if (a5 != NULL) { if (obstaclePtr != NULL) {
*a5 = NULL; *obstaclePtr = NULL;
} }
break; break;
} }
if (middle >= 0) { if (middle >= 0) {
tileX += stepX; tileX += stepX;
middle -= v47; middle -= ddy;
} }
tileY += stepY; tileY += stepY;
middle += v48; middle += ddx;
if (tile != prevTile) { if (tile != prevTile) {
if (a5 != NULL) { if (obstaclePtr != NULL) {
Object* obj = a7(a1, tile, a1->elevation); Object* obj = callback(a1, tile, a1->elevation);
if (obj != NULL) { if (obj != NULL) {
if (obj != *a5 && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) { if (obj != *obstaclePtr && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) {
*a5 = obj; *obstaclePtr = obj;
break; break;
} }
} }
@ -2064,7 +2056,7 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
} }
} }
} else { } else {
int middle = v47 - v48 / 2; int middle = ddy - ddx / 2;
while (true) { while (true) {
tile = tileFromScreenXY(tileX, tileY, a1->elevation); tile = tileFromScreenXY(tileX, tileY, a1->elevation);
@ -2074,8 +2066,8 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
return 0; return 0;
} }
if (a4 != NULL) { if (straightPathNodeList != NULL) {
STRUCT_530014_28* pathNode = &(a4[pathNodeIndex]); StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = a1->elevation; pathNode->elevation = a1->elevation;
@ -2089,26 +2081,26 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
} }
if (tileX == toX) { if (tileX == toX) {
if (a5 != NULL) { if (obstaclePtr != NULL) {
*a5 = NULL; *obstaclePtr = NULL;
} }
break; break;
} }
if (middle >= 0) { if (middle >= 0) {
tileY += stepY; tileY += stepY;
middle -= v48; middle -= ddx;
} }
tileX += stepX; tileX += stepX;
middle += v47; middle += ddy;
if (tile != prevTile) { if (tile != prevTile) {
if (a5 != NULL) { if (obstaclePtr != NULL) {
Object* obj = a7(a1, tile, a1->elevation); Object* obj = callback(a1, tile, a1->elevation);
if (obj != NULL) { if (obj != NULL) {
if (obj != *a5 && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) { if (obj != *obstaclePtr && (a6 != 32 || (obj->flags & OBJECT_SHOOT_THRU) == 0)) {
*a5 = obj; *obstaclePtr = obj;
break; break;
} }
} }
@ -2123,8 +2115,8 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
return 0; return 0;
} }
if (a4 != NULL) { if (straightPathNodeList != NULL) {
STRUCT_530014_28* pathNode = &(a4[pathNodeIndex]); StraightPathNode* pathNode = &(straightPathNodeList[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = a1->elevation; pathNode->elevation = a1->elevation;
@ -2135,8 +2127,8 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
pathNodeIndex += 1; pathNodeIndex += 1;
} else { } else {
if (pathNodeIndex > 0 && a4 != NULL) { if (pathNodeIndex > 0 && straightPathNodeList != NULL) {
a4[pathNodeIndex - 1].elevation = a1->elevation; straightPathNodeList[pathNodeIndex - 1].elevation = a1->elevation;
} }
} }
@ -2144,7 +2136,7 @@ int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4,
} }
// 0x4167F8 // 0x4167F8
static int animateMoveObjectToObject(Object* from, Object* to, int a3, int anim, int animationSequenceIndex) static int animateMoveObjectToObject(Object* from, Object* to, int actionPoints, int anim, int animationSequenceIndex)
{ {
bool hidden = (to->flags & OBJECT_HIDDEN); bool hidden = (to->flags & OBJECT_HIDDEN);
to->flags |= OBJECT_HIDDEN; to->flags |= OBJECT_HIDDEN;
@ -2176,15 +2168,15 @@ static int animateMoveObjectToObject(Object* from, Object* to, int a3, int anim,
sad->field_24 = tileGetTileInDirection(sad->field_24, sad->rotations[sad->field_1C], 1); sad->field_24 = tileGetTileInDirection(sad->field_24, sad->rotations[sad->field_1C], 1);
} }
if (a3 != -1 && a3 < sad->field_1C) { if (actionPoints != -1 && actionPoints < sad->field_1C) {
sad->field_1C = a3; sad->field_1C = actionPoints;
} }
return 0; return 0;
} }
// 0x41695C // 0x41695C
int _make_stair_path(Object* object, int from, int fromElevation, int to, int toElevation, STRUCT_530014_28* a6, Object** obstaclePtr) int _make_stair_path(Object* object, int from, int fromElevation, int to, int toElevation, StraightPathNode* a6, Object** obstaclePtr)
{ {
int elevation = fromElevation; int elevation = fromElevation;
if (elevation > toElevation) { if (elevation > toElevation) {
@ -2251,7 +2243,7 @@ int _make_stair_path(Object* object, int from, int fromElevation, int to, int to
} }
if (a6 != NULL) { if (a6 != NULL) {
STRUCT_530014_28* pathNode = &(a6[pathNodeIndex]); StraightPathNode* pathNode = &(a6[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = elevation; pathNode->elevation = elevation;
@ -2298,7 +2290,7 @@ int _make_stair_path(Object* object, int from, int fromElevation, int to, int to
} }
if (a6 != NULL) { if (a6 != NULL) {
STRUCT_530014_28* pathNode = &(a6[pathNodeIndex]); StraightPathNode* pathNode = &(a6[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = elevation; pathNode->elevation = elevation;
@ -2341,7 +2333,7 @@ int _make_stair_path(Object* object, int from, int fromElevation, int to, int to
} }
if (a6 != NULL) { if (a6 != NULL) {
STRUCT_530014_28* pathNode = &(a6[pathNodeIndex]); StraightPathNode* pathNode = &(a6[pathNodeIndex]);
pathNode->tile = tile; pathNode->tile = tile;
pathNode->elevation = elevation; pathNode->elevation = elevation;
@ -2363,17 +2355,15 @@ int _make_stair_path(Object* object, int from, int fromElevation, int to, int to
} }
// 0x416CFC // 0x416CFC
static int animateMoveObjectToTile(Object* obj, int tile, int elev, int a4, int anim, int animationSequenceIndex) static int animateMoveObjectToTile(Object* obj, int tile, int elev, int actionPoints, int anim, int animationSequenceIndex)
{ {
int v1; int index = _anim_move(obj, tile, elev, -1, anim, 0, animationSequenceIndex);
if (index == -1) {
v1 = _anim_move(obj, tile, elev, -1, anim, 0, animationSequenceIndex);
if (v1 == -1) {
return -1; return -1;
} }
if (_obj_blocking_at(obj, tile, elev)) { if (_obj_blocking_at(obj, tile, elev)) {
AnimationSad* sad = &(gAnimationSads[v1]); AnimationSad* sad = &(gAnimationSads[index]);
sad->field_1C--; sad->field_1C--;
if (sad->field_1C <= 0) { if (sad->field_1C <= 0) {
sad->field_20 = -1000; sad->field_20 = -1000;
@ -2381,8 +2371,8 @@ static int animateMoveObjectToTile(Object* obj, int tile, int elev, int a4, int
} }
sad->field_24 = tileGetTileInDirection(tile, sad->rotations[sad->field_1C], 1); sad->field_24 = tileGetTileInDirection(tile, sad->rotations[sad->field_1C], 1);
if (a4 != -1 && a4 < sad->field_1C) { if (actionPoints != -1 && actionPoints < sad->field_1C) {
sad->field_1C = a4; sad->field_1C = actionPoints;
} }
} }
@ -2457,7 +2447,7 @@ static int animateMoveObjectToTileStraight(Object* obj, int tile, int elevation,
v15 = 32; v15 = 32;
} }
sad->field_1C = _make_straight_path(obj, obj->tile, tile, sad->field_28, NULL, v15); sad->field_1C = _make_straight_path(obj, obj->tile, tile, sad->straightPathNodeList, NULL, v15);
if (sad->field_1C == 0) { if (sad->field_1C == 0) {
sad->field_20 = -1000; sad->field_20 = -1000;
return -1; return -1;
@ -2488,7 +2478,7 @@ static int _anim_move_on_stairs(Object* obj, int tile, int elevation, int anim,
sad->animationTimestamp = 0; sad->animationTimestamp = 0;
sad->ticksPerFrame = animationComputeTicksPerFrame(obj, sad->fid); sad->ticksPerFrame = animationComputeTicksPerFrame(obj, sad->fid);
sad->animationSequenceIndex = animationSequenceIndex; sad->animationSequenceIndex = animationSequenceIndex;
sad->field_1C = _make_stair_path(obj, obj->tile, obj->elevation, tile, elevation, sad->field_28, NULL); sad->field_1C = _make_stair_path(obj, obj->tile, obj->elevation, tile, elevation, sad->straightPathNodeList, NULL);
if (sad->field_1C == 0) { if (sad->field_1C == 0) {
sad->field_20 = -1000; sad->field_20 = -1000;
return -1; return -1;
@ -2523,7 +2513,7 @@ static int _check_for_falling(Object* obj, int anim, int a3)
sad->animationTimestamp = 0; sad->animationTimestamp = 0;
sad->ticksPerFrame = animationComputeTicksPerFrame(obj, sad->fid); sad->ticksPerFrame = animationComputeTicksPerFrame(obj, sad->fid);
sad->animationSequenceIndex = a3; sad->animationSequenceIndex = a3;
sad->field_1C = _make_straight_path_func(obj, obj->tile, obj->tile, sad->field_28, 0, 16, _obj_blocking_at); sad->field_1C = _make_straight_path_func(obj, obj->tile, obj->tile, sad->straightPathNodeList, 0, 16, _obj_blocking_at);
if (sad->field_1C == 0) { if (sad->field_1C == 0) {
sad->field_20 = -1000; sad->field_20 = -1000;
return -1; return -1;
@ -2540,25 +2530,25 @@ static void _object_move(int index)
AnimationSad* sad = &(gAnimationSads[index]); AnimationSad* sad = &(gAnimationSads[index]);
Object* object = sad->obj; Object* object = sad->obj;
Rect dirty; Rect dirtyRect;
Rect temp; Rect tempRect;
if (sad->field_20 == -2000) { if (sad->field_20 == -2000) {
objectSetLocation(object, object->tile, object->elevation, &dirty); objectSetLocation(object, object->tile, object->elevation, &dirtyRect);
objectSetFrame(object, 0, &temp); objectSetFrame(object, 0, &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
objectSetRotation(object, sad->rotations[0], &temp); objectSetRotation(object, sad->rotations[0], &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
int fid = buildFid(FID_TYPE(object->fid), object->fid & 0xFFF, sad->anim, (object->fid & 0xF000) >> 12, object->rotation + 1); int fid = buildFid(FID_TYPE(object->fid), object->fid & 0xFFF, sad->anim, (object->fid & 0xF000) >> 12, object->rotation + 1);
objectSetFid(object, fid, &temp); objectSetFid(object, fid, &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
sad->field_20 = 0; sad->field_20 = 0;
} else { } else {
objectSetNextFrame(object, &dirty); objectSetNextFrame(object, &dirtyRect);
} }
int frameX; int frameX;
@ -2574,8 +2564,8 @@ static void _object_move(int index)
frameY = 0; frameY = 0;
} }
_obj_offset(object, frameX, frameY, &temp); _obj_offset(object, frameX, frameY, &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
int rotation = sad->rotations[sad->field_20]; int rotation = sad->rotations[sad->field_20];
int y = dword_51D984[rotation]; int y = dword_51D984[rotation];
@ -2584,73 +2574,72 @@ static void _object_move(int index)
x = object->x - x; x = object->x - x;
y = object->y - y; y = object->y - y;
int v10 = tileGetTileInDirection(object->tile, rotation, 1); int nextTile = tileGetTileInDirection(object->tile, rotation, 1);
Object* v12 = _obj_blocking_at(object, v10, object->elevation); Object* obstacle = _obj_blocking_at(object, nextTile, object->elevation);
if (v12 != NULL) { if (obstacle != NULL) {
if (!canUseDoor(object, v12)) { if (!canUseDoor(object, obstacle)) {
sad->field_1C = _make_path(object, object->tile, sad->field_24, sad->rotations, 1); sad->field_1C = _make_path(object, object->tile, sad->field_24, sad->rotations, 1);
if (sad->field_1C != 0) { if (sad->field_1C != 0) {
objectSetLocation(object, object->tile, object->elevation, &temp); objectSetLocation(object, object->tile, object->elevation, &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
objectSetFrame(object, 0, &temp); objectSetFrame(object, 0, &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
objectSetRotation(object, sad->rotations[0], &temp); objectSetRotation(object, sad->rotations[0], &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
sad->field_20 = 0; sad->field_20 = 0;
} else { } else {
sad->field_20 = -1000; sad->field_20 = -1000;
} }
v10 = -1; nextTile = -1;
} else { } else {
_obj_use_door(object, v12, 0); _obj_use_door(object, obstacle, 0);
} }
} }
if (v10 != -1) { if (nextTile != -1) {
objectSetLocation(object, v10, object->elevation, &temp); objectSetLocation(object, nextTile, object->elevation, &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
int v17 = 0; bool cannotMove = false;
if (isInCombat() && FID_TYPE(object->fid) == OBJ_TYPE_CRITTER) { if (isInCombat() && FID_TYPE(object->fid) == OBJ_TYPE_CRITTER) {
int v18 = critterGetMovementPointCostAdjustedForCrippledLegs(object, 1); int actionPointsRequired = critterGetMovementPointCostAdjustedForCrippledLegs(object, 1);
if (_combat_free_move < v18) { if (actionPointsRequired > _combat_free_move) {
int ap = object->data.critter.combat.ap; actionPointsRequired -= _combat_free_move;
int v20 = v18 - _combat_free_move;
_combat_free_move = 0; _combat_free_move = 0;
if (v20 > ap) { if (actionPointsRequired > object->data.critter.combat.ap) {
object->data.critter.combat.ap = 0; object->data.critter.combat.ap = 0;
} else { } else {
object->data.critter.combat.ap = ap - v20; object->data.critter.combat.ap -= actionPointsRequired;
} }
} else { } else {
_combat_free_move -= v18; _combat_free_move -= actionPointsRequired;
} }
if (object == gDude) { if (object == gDude) {
interfaceRenderActionPoints(gDude->data.critter.combat.ap, _combat_free_move); interfaceRenderActionPoints(gDude->data.critter.combat.ap, _combat_free_move);
} }
v17 = (object->data.critter.combat.ap + _combat_free_move) <= 0; cannotMove = (object->data.critter.combat.ap + _combat_free_move) <= 0;
} }
sad->field_20 += 1; sad->field_20 += 1;
if (sad->field_20 == sad->field_1C || v17) { if (sad->field_20 == sad->field_1C || cannotMove) {
sad->field_20 = -1000; sad->field_20 = -1000;
} else { } else {
objectSetRotation(object, sad->rotations[sad->field_20], &temp); objectSetRotation(object, sad->rotations[sad->field_20], &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
_obj_offset(object, x, y, &temp); _obj_offset(object, x, y, &tempRect);
rectUnion(&dirty, &temp, &dirty); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
} }
} }
} }
tileWindowRefreshRect(&dirty, object->elevation); tileWindowRefreshRect(&dirtyRect, object->elevation);
if (sad->field_20 == -1000) { if (sad->field_20 == -1000) {
_anim_set_continue(sad->animationSequenceIndex, 1); _anim_set_continue(sad->animationSequenceIndex, 1);
} }
@ -2663,7 +2652,7 @@ static void _object_straight_move(int index)
Object* object = sad->obj; Object* object = sad->obj;
Rect dirtyRect; Rect dirtyRect;
Rect temp; Rect tempRect;
if (sad->field_20 == -2000) { if (sad->field_20 == -2000) {
objectSetFid(object, sad->fid, &dirtyRect); objectSetFid(object, sad->fid, &dirtyRect);
@ -2680,19 +2669,19 @@ static void _object_straight_move(int index)
if ((sad->flags & ANIM_SAD_NO_ANIM) == 0) { if ((sad->flags & ANIM_SAD_NO_ANIM) == 0) {
if ((sad->flags & ANIM_SAD_WAIT_FOR_COMPLETION) == 0 || object->frame < lastFrame) { if ((sad->flags & ANIM_SAD_WAIT_FOR_COMPLETION) == 0 || object->frame < lastFrame) {
objectSetNextFrame(object, &temp); objectSetNextFrame(object, &tempRect);
rectUnion(&dirtyRect, &temp, &dirtyRect); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
} }
} }
if (sad->field_20 < sad->field_1C) { if (sad->field_20 < sad->field_1C) {
STRUCT_530014_28* v12 = &(sad->field_28[sad->field_20]); StraightPathNode* straightPathNode = &(sad->straightPathNodeList[sad->field_20]);
objectSetLocation(object, v12->tile, v12->elevation, &temp); objectSetLocation(object, straightPathNode->tile, straightPathNode->elevation, &tempRect);
rectUnion(&dirtyRect, &temp, &dirtyRect); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
_obj_offset(object, v12->x, v12->y, &temp); _obj_offset(object, straightPathNode->x, straightPathNode->y, &tempRect);
rectUnion(&dirtyRect, &temp, &dirtyRect); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
sad->field_20++; sad->field_20++;
} }
@ -2753,7 +2742,7 @@ void _object_animate()
return; return;
} }
_anim_in_bk = 1; _anim_in_bk = true;
for (int index = 0; index < gAnimationCurrentSad; index++) { for (int index = 0; index < gAnimationCurrentSad; index++) {
AnimationSad* sad = &(gAnimationSads[index]); AnimationSad* sad = &(gAnimationSads[index]);
@ -2876,9 +2865,8 @@ void _object_animate()
y = 0; y = 0;
} }
Rect v29; objectSetFid(object, sad->fid, &tempRect);
objectSetFid(object, sad->fid, &v29); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
rectUnion(&dirtyRect, &v29, &dirtyRect);
art = artLock(object->fid, &cacheHandle); art = artLock(object->fid, &cacheHandle);
if (art != NULL) { if (art != NULL) {
@ -2889,21 +2877,21 @@ void _object_animate()
frame = 0; frame = 0;
} }
objectSetFrame(object, frame, &v29); objectSetFrame(object, frame, &tempRect);
rectUnion(&dirtyRect, &v29, &dirtyRect); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
int frameX; int frameX;
int frameY; int frameY;
artGetFrameOffsets(art, object->frame, object->rotation, &frameX, &frameY); artGetFrameOffsets(art, object->frame, object->rotation, &frameX, &frameY);
Rect v19; Rect tempRect;
_obj_offset(object, x + frameX, y + frameY, &v19); _obj_offset(object, x + frameX, y + frameY, &tempRect);
rectUnion(&dirtyRect, &v19, &dirtyRect); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
artUnlock(cacheHandle); artUnlock(cacheHandle);
} else { } else {
objectSetFrame(object, 0, &v29); objectSetFrame(object, 0, &tempRect);
rectUnion(&dirtyRect, &v29, &dirtyRect); rectUnion(&dirtyRect, &tempRect, &dirtyRect);
} }
tileWindowRefreshRect(&dirtyRect, gElevation); tileWindowRefreshRect(&dirtyRect, gElevation);
@ -2928,21 +2916,21 @@ static void _object_anim_compact()
int index = 0; int index = 0;
for (; index < gAnimationCurrentSad; index++) { for (; index < gAnimationCurrentSad; index++) {
if (gAnimationSads[index].field_20 == -1000) { if (gAnimationSads[index].field_20 == -1000) {
int v2 = index + 1; int nextIndex = index + 1;
for (; v2 < gAnimationCurrentSad; v2++) { for (; nextIndex < gAnimationCurrentSad; nextIndex++) {
if (gAnimationSads[v2].field_20 != -1000) { if (gAnimationSads[nextIndex].field_20 != -1000) {
break; break;
} }
} }
if (v2 == gAnimationCurrentSad) { if (nextIndex == gAnimationCurrentSad) {
break; break;
} }
if (index != v2) { if (index != nextIndex) {
memcpy(&(gAnimationSads[index]), &(gAnimationSads[v2]), sizeof(AnimationSad)); memcpy(&(gAnimationSads[index]), &(gAnimationSads[nextIndex]), sizeof(AnimationSad));
gAnimationSads[v2].field_20 = -1000; gAnimationSads[nextIndex].field_20 = -1000;
gAnimationSads[v2].flags = 0; gAnimationSads[nextIndex].flags = 0;
} }
} }
} }
@ -3029,6 +3017,15 @@ int _dude_run(int actionPoints)
// 0x418168 // 0x418168
void _dude_fidget() void _dude_fidget()
{ {
// 0x510730
static unsigned int lastTime = 0;
// 0x510734
static unsigned int nextTime = 0;
// 0x56C7E0
static Object* candidates[100];
if (_game_user_wants_to_quit != 0) { if (_game_user_wants_to_quit != 0) {
return; return;
} }
@ -3045,17 +3042,17 @@ void _dude_fidget()
return; return;
} }
unsigned int v0 = _get_bk_time(); unsigned int currentTime = _get_bk_time();
if (getTicksBetween(v0, _last_time_) <= _next_time) { if (getTicksBetween(currentTime, lastTime) <= nextTime) {
return; return;
} }
_last_time_ = v0; lastTime = currentTime;
int v5 = 0; int candidatesLength = 0;
Object* object = objectFindFirstAtElevation(gDude->elevation); Object* object = objectFindFirstAtElevation(gDude->elevation);
while (object != NULL) { while (object != NULL) {
if (v5 >= 100) { if (candidatesLength >= 100) {
break; break;
} }
@ -3065,35 +3062,35 @@ void _dude_fidget()
Rect intersection; Rect intersection;
if (rectIntersection(&rect, &_scr_size, &intersection) == 0 && (gMapHeader.field_34 != 97 || object->pid != 0x10000FA)) { if (rectIntersection(&rect, &_scr_size, &intersection) == 0 && (gMapHeader.field_34 != 97 || object->pid != 0x10000FA)) {
dword_56C7E0[v5++] = object; candidates[candidatesLength++] = object;
} }
} }
object = objectFindNextAtElevation(); object = objectFindNextAtElevation();
} }
int v13; int delayInSeconds;
if (v5 != 0) { if (candidatesLength != 0) {
int r = randomBetween(0, v5 - 1); int index = randomBetween(0, candidatesLength - 1);
Object* object = dword_56C7E0[r]; Object* object = candidates[index];
reg_anim_begin(ANIMATION_REQUEST_UNRESERVED | ANIMATION_REQUEST_INSIGNIFICANT); reg_anim_begin(ANIMATION_REQUEST_UNRESERVED | ANIMATION_REQUEST_INSIGNIFICANT);
bool v8 = false; bool shoudPlaySound = false;
if (object == gDude) { if (object == gDude) {
v8 = true; shoudPlaySound = true;
} else { } else {
char v15[16]; char fileName[16];
v15[0] = '\0'; fileName[0] = '\0';
artCopyFileName(1, object->fid & 0xFFF, v15); artCopyFileName(1, object->fid & 0xFFF, fileName);
if (v15[0] == 'm' || v15[0] == 'M') { if (fileName[0] == 'm' || fileName[0] == 'M') {
if (objectGetDistanceBetween(object, gDude) < critterGetStat(gDude, STAT_PERCEPTION) * 2) { if (objectGetDistanceBetween(object, gDude) < critterGetStat(gDude, STAT_PERCEPTION) * 2) {
v8 = true; shoudPlaySound = true;
} }
} }
} }
if (v8) { if (shoudPlaySound) {
const char* sfx = sfxBuildCharName(object, ANIM_STAND, CHARACTER_SOUND_EFFECT_UNUSED); const char* sfx = sfxBuildCharName(object, ANIM_STAND, CHARACTER_SOUND_EFFECT_UNUSED);
animationRegisterPlaySoundEffect(object, sfx, 0); animationRegisterPlaySoundEffect(object, sfx, 0);
} }
@ -3101,18 +3098,18 @@ void _dude_fidget()
animationRegisterAnimate(object, ANIM_STAND, 0); animationRegisterAnimate(object, ANIM_STAND, 0);
reg_anim_end(); reg_anim_end();
v13 = 20 / v5; delayInSeconds = 20 / candidatesLength;
} else { } else {
v13 = 7; delayInSeconds = 7;
} }
if (v13 < 1) { if (delayInSeconds < 1) {
v13 = 1; delayInSeconds = 1;
} else if (v13 > 7) { } else if (delayInSeconds > 7) {
v13 = 7; delayInSeconds = 7;
} }
_next_time = randomBetween(0, 3000) + 1000 * v13; nextTime = randomBetween(0, 3000) + 1000 * delayInSeconds;
} }
// 0x418378 // 0x418378
@ -3241,14 +3238,14 @@ static int _anim_hide(Object* object, int animationSequenceIndex)
// 0x418660 // 0x418660
static int _anim_change_fid(Object* obj, int animationSequenceIndex, int fid) static int _anim_change_fid(Object* obj, int animationSequenceIndex, int fid)
{ {
Rect rect;
Rect v7;
if (FID_ANIM_TYPE(fid)) { if (FID_ANIM_TYPE(fid)) {
objectSetFid(obj, fid, &rect); Rect dirtyRect;
objectSetFrame(obj, 0, &v7); Rect tempRect;
rectUnion(&rect, &v7, &rect);
tileWindowRefreshRect(&rect, obj->elevation); objectSetFid(obj, fid, &dirtyRect);
objectSetFrame(obj, 0, &tempRect);
rectUnion(&dirtyRect, &tempRect, &dirtyRect);
tileWindowRefreshRect(&dirtyRect, obj->elevation);
} else { } else {
_dude_stand(obj, obj->rotation, fid); _dude_stand(obj, obj->rotation, fid);
} }

View File

@ -100,12 +100,12 @@ typedef int(AnimationCallback)(void* a1, void* a2);
// Signature of animation callback accepting 3 parameters. // Signature of animation callback accepting 3 parameters.
typedef int(AnimationCallback3)(void* a1, void* a2, void* a3); typedef int(AnimationCallback3)(void* a1, void* a2, void* a3);
typedef struct STRUCT_530014_28 { typedef struct StraightPathNode {
int tile; int tile;
int elevation; int elevation;
int x; int x;
int y; int y;
} STRUCT_530014_28; } StraightPathNode;
typedef Object* PathBuilderCallback(Object* object, int tile, int elevation); typedef Object* PathBuilderCallback(Object* object, int tile, int elevation);
@ -145,8 +145,8 @@ int animationRegisterAnimateForever(Object* owner, int anim, int delay);
int animationRegisterPing(int flags, int delay); int animationRegisterPing(int flags, int delay);
int _make_path(Object* object, int from, int to, unsigned char* a4, int a5); int _make_path(Object* object, int from, int to, unsigned char* a4, int a5);
int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback); int pathfinderFindPath(Object* object, int from, int to, unsigned char* rotations, int a5, PathBuilderCallback* callback);
int _make_straight_path(Object* a1, int from, int to, STRUCT_530014_28* pathNodes, Object** a5, int a6); int _make_straight_path(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6);
int _make_straight_path_func(Object* a1, int from, int to, STRUCT_530014_28* a4, Object** a5, int a6, Object* (*a7)(Object*, int, int)); int _make_straight_path_func(Object* a1, int from, int to, StraightPathNode* straightPathNodeList, Object** obstaclePtr, int a6, PathBuilderCallback* callback);
void _object_animate(); void _object_animate();
int _check_move(int* actionPointsPtr); int _check_move(int* actionPointsPtr);
int _dude_move(int actionPoints); int _dude_move(int actionPoints);

View File

@ -200,6 +200,8 @@ enum {
#define FID_0x20001F5 0x20001F5 #define FID_0x20001F5 0x20001F5
#define FIRST_EXIT_GRID_PID 0x5000010 #define FIRST_EXIT_GRID_PID 0x5000010
#define LAST_EXIT_GRID_PID 0x5000017 #define LAST_EXIT_GRID_PID 0x5000017
#define FIRST_RADIOACTIVE_GOO_PID 0x20003D9
#define LAST_RADIOACTIVE_GOO_PID 0x20003DC
typedef enum ItemProtoFlags { typedef enum ItemProtoFlags {
ItemProtoFlags_0x08 = 0x08, ItemProtoFlags_0x08 = 0x08,