Fix incorrect death animation in opKillCritterType
This commit is contained in:
parent
d03fd5e43f
commit
08691ce319
|
@ -389,21 +389,6 @@ static const char* _dbg_error_strs[SCRIPT_ERROR_COUNT] = {
|
||||||
"follows",
|
"follows",
|
||||||
};
|
};
|
||||||
|
|
||||||
// 0x518ED0
|
|
||||||
static const int _ftList[11] = {
|
|
||||||
ANIM_FALL_BACK_BLOOD_SF,
|
|
||||||
ANIM_BIG_HOLE_SF,
|
|
||||||
ANIM_CHARRED_BODY_SF,
|
|
||||||
ANIM_CHUNKS_OF_FLESH_SF,
|
|
||||||
ANIM_FALL_FRONT_BLOOD_SF,
|
|
||||||
ANIM_FALL_BACK_BLOOD_SF,
|
|
||||||
ANIM_DANCING_AUTOFIRE_SF,
|
|
||||||
ANIM_SLICED_IN_HALF_SF,
|
|
||||||
ANIM_EXPLODED_TO_NOTHING_SF,
|
|
||||||
ANIM_FALL_BACK_BLOOD_SF,
|
|
||||||
ANIM_FALL_FRONT_BLOOD_SF,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Last message type during op_float_msg sequential.
|
// Last message type during op_float_msg sequential.
|
||||||
//
|
//
|
||||||
// 0x518F00
|
// 0x518F00
|
||||||
|
@ -2389,6 +2374,21 @@ static int _correctDeath(Object* critter, int anim, bool forceBack)
|
||||||
// 0x457CB4
|
// 0x457CB4
|
||||||
static void opKillCritterType(Program* program)
|
static void opKillCritterType(Program* program)
|
||||||
{
|
{
|
||||||
|
// 0x518ED0
|
||||||
|
static const int ftList[] = {
|
||||||
|
ANIM_FALL_BACK_BLOOD_SF,
|
||||||
|
ANIM_BIG_HOLE_SF,
|
||||||
|
ANIM_CHARRED_BODY_SF,
|
||||||
|
ANIM_CHUNKS_OF_FLESH_SF,
|
||||||
|
ANIM_FALL_FRONT_BLOOD_SF,
|
||||||
|
ANIM_FALL_BACK_BLOOD_SF,
|
||||||
|
ANIM_DANCING_AUTOFIRE_SF,
|
||||||
|
ANIM_SLICED_IN_HALF_SF,
|
||||||
|
ANIM_EXPLODED_TO_NOTHING_SF,
|
||||||
|
ANIM_FALL_BACK_BLOOD_SF,
|
||||||
|
ANIM_FALL_FRONT_BLOOD_SF,
|
||||||
|
};
|
||||||
|
|
||||||
int deathFrame = programStackPopInteger(program);
|
int deathFrame = programStackPopInteger(program);
|
||||||
int pid = programStackPopInteger(program);
|
int pid = programStackPopInteger(program);
|
||||||
|
|
||||||
|
@ -2401,51 +2401,74 @@ static void opKillCritterType(Program* program)
|
||||||
|
|
||||||
Object* previousObj = NULL;
|
Object* previousObj = NULL;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int v3 = 0;
|
int ftIndex = 0;
|
||||||
|
|
||||||
Object* obj = objectFindFirst();
|
Object* obj = objectFindFirst();
|
||||||
while (obj != NULL) {
|
while (obj != NULL) {
|
||||||
if (FID_ANIM_TYPE(obj->fid) >= ANIM_FALL_BACK_SF) {
|
if (FID_ANIM_TYPE(obj->fid) < ANIM_FALL_BACK_SF) {
|
||||||
obj = objectFindNext();
|
if ((obj->flags & OBJECT_HIDDEN) == 0 && obj->pid == pid && !critterIsDead(obj)) {
|
||||||
continue;
|
if (obj == previousObj || count > 200) {
|
||||||
}
|
scriptPredefinedError(program, "kill_critter_type", SCRIPT_ERROR_FOLLOWS);
|
||||||
|
debugPrint(" Infinite loop destroying critters!");
|
||||||
if ((obj->flags & OBJECT_HIDDEN) == 0 && obj->pid == pid && !critterIsDead(obj)) {
|
program->flags &= ~PROGRAM_FLAG_0x20;
|
||||||
if (obj == previousObj || count > 200) {
|
return;
|
||||||
scriptPredefinedError(program, "kill_critter_type", SCRIPT_ERROR_FOLLOWS);
|
|
||||||
debugPrint(" Infinite loop destroying critters!");
|
|
||||||
program->flags &= ~PROGRAM_FLAG_0x20;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg_anim_clear(obj);
|
|
||||||
|
|
||||||
if (deathFrame != 0) {
|
|
||||||
_combat_delete_critter(obj);
|
|
||||||
if (deathFrame == 1) {
|
|
||||||
int anim = _correctDeath(obj, _ftList[v3], 1);
|
|
||||||
critterKill(obj, anim, 1);
|
|
||||||
v3 += 1;
|
|
||||||
if (v3 >= 11) {
|
|
||||||
v3 = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
critterKill(obj, ANIM_FALL_BACK_SF, 1);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
reg_anim_clear(obj);
|
reg_anim_clear(obj);
|
||||||
|
|
||||||
Rect rect;
|
if (deathFrame != 0) {
|
||||||
objectDestroy(obj, &rect);
|
_combat_delete_critter(obj);
|
||||||
tileWindowRefreshRect(&rect, gElevation);
|
if (deathFrame == 1) {
|
||||||
|
// Pick next animation from the |ftList|.
|
||||||
|
int anim = _correctDeath(obj, ftList[ftIndex], true);
|
||||||
|
|
||||||
|
// SFALL: Fix for incorrect death animation.
|
||||||
|
// CE: The fix is slightly different. Sfall passes
|
||||||
|
// |false| to |correctDeath| to disambiguate usage
|
||||||
|
// between this function and |opAnim|. On |false| it
|
||||||
|
// simply returns |ANIM_FALL_BACK_SF|. Instead of doing
|
||||||
|
// the same, check for standard death animations
|
||||||
|
// returned from |correctDeath| and convert them to
|
||||||
|
// appropariate single frame cousins.
|
||||||
|
switch (anim) {
|
||||||
|
case ANIM_FALL_BACK:
|
||||||
|
anim = ANIM_FALL_BACK_SF;
|
||||||
|
break;
|
||||||
|
case ANIM_FALL_FRONT:
|
||||||
|
anim = ANIM_FALL_FRONT_SF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
critterKill(obj, anim, true);
|
||||||
|
|
||||||
|
ftIndex += 1;
|
||||||
|
if (ftIndex >= (sizeof(ftList) / sizeof(ftList[0]))) {
|
||||||
|
ftIndex = 0;
|
||||||
|
}
|
||||||
|
} else if (deathFrame >= FIRST_SF_DEATH_ANIM && deathFrame <= LAST_SF_DEATH_ANIM) {
|
||||||
|
// CE: In some cases user-space scripts randomize death
|
||||||
|
// frame between front/back animations but technically
|
||||||
|
// speaking a scripter can provide any single frame
|
||||||
|
// death animation which original code simply ignores.
|
||||||
|
critterKill(obj, deathFrame, true);
|
||||||
|
} else {
|
||||||
|
critterKill(obj, ANIM_FALL_BACK_SF, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reg_anim_clear(obj);
|
||||||
|
|
||||||
|
Rect rect;
|
||||||
|
objectDestroy(obj, &rect);
|
||||||
|
tileWindowRefreshRect(&rect, gElevation);
|
||||||
|
}
|
||||||
|
|
||||||
|
previousObj = obj;
|
||||||
|
count += 1;
|
||||||
|
|
||||||
|
objectFindFirst();
|
||||||
|
|
||||||
|
gMapHeader.lastVisitTime = gameTimeGetTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
previousObj = obj;
|
|
||||||
count += 1;
|
|
||||||
|
|
||||||
objectFindFirst();
|
|
||||||
|
|
||||||
gMapHeader.lastVisitTime = gameTimeGetTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obj = objectFindNext();
|
obj = objectFindNext();
|
||||||
|
|
Loading…
Reference in New Issue