[Scummvm-git-logs] scummvm master -> 3d8b8f01b777b8d987fc45c46b3bc3394c2aac25
mduggan
mgithub at guarana.org
Tue Apr 6 12:38:31 UTC 2021
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
2ebcd4d57b ULTIMA8: Sanity check last attack timestamp
c26552d208 ULTIMA8: Animate all shapes on the same frame
3d8b8f01b7 ULTIMA8: Implement crusader attack timeouts
Commit: 2ebcd4d57b18e3772201ab731026c993a0b16635
https://github.com/scummvm/scummvm/commit/2ebcd4d57b18e3772201ab731026c993a0b16635
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-04-06T21:27:24+09:00
Commit Message:
ULTIMA8: Sanity check last attack timestamp
Changed paths:
engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
diff --git a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
index 5603c4bd41..eaab2bb8bf 100644
--- a/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
+++ b/engines/ultima/ultima8/world/actors/u8_avatar_mover_process.cpp
@@ -742,6 +742,14 @@ void U8AvatarMoverProcess::jump(Animation::Sequence action, Direction direction)
bool U8AvatarMoverProcess::canAttack() {
MainActor *avatar = getMainActor();
+ const uint32 frameno = Kernel::get_instance()->getFrameNum();
+
+ // Sanity check in case the frame num went backwards - eg, if
+ // frame counting changed after loading a game.
+ if (_lastAttack > frameno) {
+ _lastAttack = frameno;
+ }
+
return (Kernel::get_instance()->getFrameNum() > _lastAttack + (25 - avatar->getDex()));
}
Commit: c26552d208b8149f64462cf9148d241325c3dd82
https://github.com/scummvm/scummvm/commit/c26552d208b8149f64462cf9148d241325c3dd82
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-04-06T21:27:24+09:00
Commit Message:
ULTIMA8: Animate all shapes on the same frame
This is easily noticable on the falls west of town - all parts should animate
together, but they don't match.
Changed paths:
engines/ultima/ultima8/world/item.cpp
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index aeff4bf0f9..988792d0c9 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1680,7 +1680,7 @@ void Item::setupLerp(int32 gametick) {
// Animate it, if needed
const ShapeInfo *info = getShapeInfo();
if (info->_animType &&
- ((gametick % info->_animSpeed) == (_objId % info->_animSpeed)))
+ ((gametick % info->_animSpeed) == 0))
animateItem();
// Setup the prev values for lerping
@@ -1713,7 +1713,7 @@ void Item::animateItem() {
int anim_data = info->_animData;
int speed = info->_animSpeed;
- if ((static_cast<int>(_lastSetup) % speed * 2) != (_objId % speed * 2) && info->_animType != 1)
+ if ((static_cast<int>(_lastSetup) % speed * 2) != 0 && info->_animType != 1)
return;
const Shape *shp = getShapeObject();
Commit: 3d8b8f01b777b8d987fc45c46b3bc3394c2aac25
https://github.com/scummvm/scummvm/commit/3d8b8f01b777b8d987fc45c46b3bc3394c2aac25
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2021-04-06T21:27:24+09:00
Commit Message:
ULTIMA8: Implement crusader attack timeouts
To match the original, add some movement timeouts and a flag that affect the
aim quality of NPCs attacking the player.
Changed paths:
engines/ultima/ultima8/world/actors/actor.cpp
engines/ultima/ultima8/world/actors/actor.h
engines/ultima/ultima8/world/actors/attack_process.cpp
engines/ultima/ultima8/world/super_sprite_process.cpp
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 82305140df..6692a7e148 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -70,7 +70,8 @@ Actor::Actor() : _strength(0), _dexterity(0), _intelligence(0),
_fallStart(0), _unkByte(0), _actorFlags(0), _combatTactic(0),
_homeX(0), _homeY(0), _homeZ(0), _currentActivityNo(0),
_lastActivityNo(0), _activeWeapon(0), _lastTimeWasHit(0),
- _shieldType(0) {
+ _shieldType(0), _attackMoveStartTime(0), _attackMoveTimeout(0),
+ _attackMoveDodgeFactor(1), _attackAimFlag(false) {
_defaultActivity[0] = 0;
_defaultActivity[1] = 0;
_defaultActivity[2] = 0;
@@ -497,6 +498,47 @@ uint16 Actor::doAnim(Animation::Sequence anim, Direction dir, unsigned int steps
} else if (anim != Animation::kneel) {
clearActorFlag(ACT_KNEELING);
}
+
+ const uint32 frameno = Kernel::get_instance()->getFrameNum();
+ switch(anim) {
+ case Animation::walk:
+ case Animation::retreat: // SmallWeapon
+ _attackMoveStartTime = frameno;
+ _attackMoveTimeout = 120;
+ _attackMoveDodgeFactor = 3;
+ break;
+ case Animation::run:
+ case Animation::combatRollLeft:
+ case Animation::combatRollRight:
+ case Animation::stopRunningAndDrawLargeWeapon:
+ case Animation::stopRunningAndDrawSmallWeapon:
+ case Animation::jumpForward:
+ case Animation::jump:
+ case Animation::slowCombatRollLeft:
+ case Animation::slowCombatRollRight:
+ //case Animation::startRunSmallWeapon:
+ //case Animation::startRunLargeWeapon:
+ case Animation::startRun:
+ _attackMoveStartTime = frameno;
+ _attackMoveTimeout = 120;
+ _attackMoveDodgeFactor = 2;
+ break;
+ case Animation::slideLeft:
+ case Animation::slideRight:
+ _attackMoveStartTime = frameno;
+ _attackMoveTimeout = 60;
+ _attackMoveDodgeFactor = 3;
+ break;
+ case Animation::startKneeling:
+ case Animation::stopKneeling:
+ _attackMoveStartTime = frameno;
+ _attackMoveTimeout = 75;
+ _attackMoveDodgeFactor = 3;
+ break;
+ default:
+ break;
+ }
+
}
#if 1
@@ -1662,6 +1704,10 @@ void Actor::saveData(Common::WriteStream *ws) {
ws->writeUint16LE(_activeWeapon);
ws->writeSint32LE(_lastTimeWasHit);
ws->writeByte(_shieldType);
+ ws->writeUint32LE(_attackMoveStartTime);
+ ws->writeUint32LE(_attackMoveTimeout);
+ ws->writeUint16LE(_attackMoveDodgeFactor);
+ ws->writeByte(_attackAimFlag ? 1 : 0);
}
}
@@ -1695,6 +1741,10 @@ bool Actor::loadData(Common::ReadStream *rs, uint32 version) {
_activeWeapon = rs->readUint16LE();
_lastTimeWasHit = rs->readSint32LE();
_shieldType = rs->readByte();
+ _attackMoveStartTime = rs->readUint32LE();
+ _attackMoveTimeout = rs->readUint32LE();
+ _attackMoveDodgeFactor = rs->readUint16LE();
+ _attackAimFlag = rs->readByte() != 0;
}
return true;
diff --git a/engines/ultima/ultima8/world/actors/actor.h b/engines/ultima/ultima8/world/actors/actor.h
index 7eacb9a760..2d7de96497 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -300,6 +300,22 @@ public:
//! Add the x/y/z fire offsets given the current state of the actor
void addFireAnimOffsets(int32 &x, int32 &y, int32 &z);
+ uint32 getAttackMoveTimeoutFinish() const {
+ return _attackMoveStartTime + _attackMoveTimeout;
+ }
+
+ uint16 getAttackMoveDodgeFactor() const {
+ return _attackMoveDodgeFactor;
+ }
+
+ bool getAttackAimFlag() const {
+ return _attackAimFlag;
+ }
+
+ void setAttackAimFlag(bool val) {
+ _attackAimFlag = val;
+ }
+
ENABLE_RUNTIME_CLASSTYPE()
INTRINSIC(I_isNPC);
@@ -436,6 +452,18 @@ protected:
//! Type of shield (only used in Crusader)
uint8 _shieldType;
+ //! The frame certain animations last happened (for Crusader).
+ //! Used in calcualting how hard controlled actor is to hit.
+ uint32 _attackMoveStartTime;
+ //! The number of frames the above effect lasts for.
+ uint32 _attackMoveTimeout;
+ //! A spread divisor used by shots targeting the controlled actor when they
+ //! are within the above timeout.
+ uint16 _attackMoveDodgeFactor;
+
+ //! A flag used in Crusader attack process which adjusts the aim accuracy.
+ bool _attackAimFlag;
+
//! starts an activity (Ultima 8 version)
//! \return processID of process handling the activity or zero
uint16 setActivityU8(int activity);
diff --git a/engines/ultima/ultima8/world/actors/attack_process.cpp b/engines/ultima/ultima8/world/actors/attack_process.cpp
index 29862e9009..e656b17a57 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -61,11 +61,6 @@ const uint16 AttackProcess::ATTACK_PROCESS_TYPE = 0x259;
static uint16 someSleepGlobal = 0;
-// TODO: Implement me. Set timer for some avatar moves.
-static bool World_FinishedAvatarMoveTimeout() {
- return true;
-}
-
static inline int32 randomOf(int32 max) {
return (max > 0 ? getRandom() % max : 0);
}
@@ -98,6 +93,8 @@ _soundTimestamp(0), _fireTimestamp(0) {
_dataArray[i] = 0;
}
+ actor->setAttackAimFlag(false);
+
const Item *wpn = getItem(actor->getActiveWeapon());
if (wpn) {
const uint32 wpnshape = wpn->getShape();
@@ -606,7 +603,7 @@ void AttackProcess::genericAttack() {
if (_wpnField8 < 3) {
_wpnField8 = 1;
} else if ((_doubleDelay && (getRandom() % 2 == 0)) || (getRandom() % 5 == 0)) {
- // TODO: a->setField0x68(1);
+ a->setAttackAimFlag(true);
_wpnField8 *= 4;
}
_fireTimestamp = now;
@@ -648,8 +645,11 @@ void AttackProcess::genericAttack() {
}
if (targetdir == curdir) {
const uint16 rnd = randomOf(10);
+ const uint32 frameno = Kernel::get_instance()->getFrameNum();
+ const uint32 timeoutfinish = target->getAttackMoveTimeoutFinish();
+
if (!onscreen ||
- (!_field96 && !timer4and5Update(now) && !World_FinishedAvatarMoveTimeout()
+ (!_field96 && !timer4and5Update(now) && frameno < timeoutfinish
&& rnd > 2 && (!_isActivityAorB || rnd > 3))) {
sleep(0x14);
return;
@@ -700,7 +700,7 @@ void AttackProcess::genericAttack() {
if (wpn) {
_wpnField8 = wpnField8;
if (_wpnField8 > 2 && ((_doubleDelay && randomOf(2) == 0) || randomOf(5) == 0)) {
- // TODO: a->setField0x68(1);
+ a->setAttackAimFlag(true);
_wpnField8 *= 4;
}
}
diff --git a/engines/ultima/ultima8/world/super_sprite_process.cpp b/engines/ultima/ultima8/world/super_sprite_process.cpp
index 105c69f669..9db9ac6b15 100644
--- a/engines/ultima/ultima8/world/super_sprite_process.cpp
+++ b/engines/ultima/ultima8/world/super_sprite_process.cpp
@@ -77,13 +77,27 @@ SuperSpriteProcess::SuperSpriteProcess(int shape, int frame, int sx, int sy, int
else
rng /= 10;
} else {
- if (dynamic_cast<Actor *>(srcitem) != nullptr) {
- rng /= 2;
+ Actor *srcnpc = dynamic_cast<Actor *>(srcitem);
+ Actor *controlled = getControlledActor();
+ const uint32 frameno = Kernel::get_instance()->getFrameNum();
+ const uint32 timeoutfinish = controlled ? controlled->getAttackMoveTimeoutFinish() : 0;
+ if (!srcnpc || !srcnpc->getAttackAimFlag()) {
+ if (!srcnpc || frameno < timeoutfinish) {
+ if (!srcnpc && (controlled && controlled->isKneeling())) {
+ rng = rng / 5;
+ } else {
+ const uint16 dodgefactor = controlled ? controlled->getAttackMoveDodgeFactor() : 2;
+ if (!srcnpc) {
+ rng = rng / (dodgefactor * 3);
+ } else {
+ rng = rng / dodgefactor;
+ }
+ }
+ } else {
+ rng = rng / 8;
+ }
} else {
- // TODO: various other flags are checked in the game (around 1138:0bd1)
- // such as World_FinishedAvatarMoveTimeout() -> 8
- // to make it either 5 or 8. For now just use 5.
- rng /= 5;
+ rng = rng / 2;
}
}
More information about the Scummvm-git-logs
mailing list