[Scummvm-git-logs] scummvm master -> f9b14adc62e4e6d0d010a40f07940b49bd4f7f1c
mduggan
mgithub at guarana.org
Sun Dec 20 00:39:14 UTC 2020
This automated email contains information about 10 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
69f5a76100 ULTIMA8: Small cleanups of unused code in RemorseMenuGump
f3cd1452a4 ULTIMA8: Note what 2 more engine functions do
90064583b2 ULTIMA8: Add original CD game variant
28d9667a9e ULTIMA8: Remove misleading/incorrect comment
2647bfd0a8 ULTIMA8: Ignore 'combat' music in Cruader
d1992cb52c ULTIMA8: Improve comments in Process
fa9694739f ULTIMA8: Animation cleanups
fe32fcf596 ULTIMA8: Apply crusader anim rotation flag
280c103bc5 ULTIMA8: Enable crusader firing from animation flags
f9b14adc62 ULTIMA8: Correct the way typeflags are used
Commit: 69f5a761007f6856fcb9bbd75f852bca496415fd
https://github.com/scummvm/scummvm/commit/69f5a761007f6856fcb9bbd75f852bca496415fd
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Small cleanups of unused code in RemorseMenuGump
Changed paths:
engines/ultima/ultima8/gumps/remorse_menu_gump.cpp
engines/ultima/ultima8/gumps/remorse_menu_gump.h
diff --git a/engines/ultima/ultima8/gumps/remorse_menu_gump.cpp b/engines/ultima/ultima8/gumps/remorse_menu_gump.cpp
index 682ac3d188..91fe8f8a63 100644
--- a/engines/ultima/ultima8/gumps/remorse_menu_gump.cpp
+++ b/engines/ultima/ultima8/gumps/remorse_menu_gump.cpp
@@ -27,20 +27,13 @@
#include "ultima/ultima8/graphics/shape.h"
#include "ultima/ultima8/graphics/shape_frame.h"
#include "ultima/ultima8/ultima8.h"
-#include "ultima/ultima8/gumps/desktop_gump.h"
#include "ultima/ultima8/gumps/widgets/button_widget.h"
-#include "ultima/ultima8/gumps/widgets/text_widget.h"
#include "ultima/ultima8/gumps/quit_gump.h"
-#include "ultima/ultima8/gumps/paged_gump.h"
#include "ultima/ultima8/games/game.h"
#include "ultima/ultima8/world/actors/main_actor.h"
-#include "ultima/ultima8/graphics/fonts/font.h"
#include "ultima/ultima8/graphics/fonts/rendered_text.h"
-#include "ultima/ultima8/graphics/fonts/font_manager.h"
#include "ultima/ultima8/graphics/palette_manager.h"
-#include "ultima/ultima8/conf/setting_manager.h"
#include "ultima/ultima8/audio/music_process.h"
-#include "ultima/ultima8/gumps/widgets/edit_widget.h"
#include "ultima/ultima8/gumps/u8_save_gump.h"
#include "ultima/ultima8/world/get_object.h"
#include "ultima/ultima8/meta_engine.h"
@@ -77,7 +70,6 @@ RemorseMenuGump::~RemorseMenuGump() {
MetaEngine::setGameMenuActive(false);
}
-
void RemorseMenuGump::Close(bool no_del) {
// Restore old music state and palette.
// Music state can be changed by the Intro and Credits
@@ -172,7 +164,6 @@ void RemorseMenuGump::InitGump(Gump *newparent, bool take_focus) {
}
}
-
void RemorseMenuGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
Gump::PaintThis(surf, lerp_factor, scaled);
}
@@ -200,11 +191,6 @@ void RemorseMenuGump::ChildNotify(Gump *child, uint32 message) {
}
void RemorseMenuGump::selectEntry(int entry) {
- SettingManager *settingman = SettingManager::get_instance();
- bool endgame, quotes;
- settingman->get("endgame", endgame);
- settingman->get("quotes", quotes);
-
switch (entry) {
case 1: // New Game
Game::get_instance()->playIntroMovie(true);
@@ -233,7 +219,6 @@ void RemorseMenuGump::selectEntry(int entry) {
bool RemorseMenuGump::OnTextInput(int unicode) {
if (Gump::OnTextInput(unicode)) return true;
-
return true;
}
diff --git a/engines/ultima/ultima8/gumps/remorse_menu_gump.h b/engines/ultima/ultima8/gumps/remorse_menu_gump.h
index f7fe405d93..55de6709d0 100644
--- a/engines/ultima/ultima8/gumps/remorse_menu_gump.h
+++ b/engines/ultima/ultima8/gumps/remorse_menu_gump.h
@@ -29,8 +29,6 @@
namespace Ultima {
namespace Ultima8 {
-class RenderedText;
-
/**
* The game menu for Crusader: No Remorse. Different enough to the U8 menu that it's implemented separately.
*/
Commit: f3cd1452a47139b7b5507cc32817c5afe0271a5a
https://github.com/scummvm/scummvm/commit/f3cd1452a47139b7b5507cc32817c5afe0271a5a
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Note what 2 more engine functions do
Changed paths:
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 130fa293b1..edf27b0c2c 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -265,7 +265,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 Item::I_use(Item *)", // same coff as 080, 0D5
"void AudioProcess:I_stopAllSFX(void)", // based on disasm.
"void I_playMovieCutscene(int *item,char *flicname,word sizex,word sizey)", // play flic
- "void Intrinsic0D3(void)", // clears some globals and calls a kernel function.. TODO: work out what those globals do?
+ "void I_clearKeyboardState(void)", // clears some globals and calls a keyboard reset function.. TODO: work out what those globals do?
"void I_playSFX(2 bytes)", // same coff as 0AA. Based on disasm.
"int16 Item::I_use(Item *)", // same coff as 080, 0D0
"byte CameraProcess::I_getCameraZ(void)",
@@ -368,7 +368,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
"void Item::I_andStatus(Item *, int16 status)", // part of same coff set 01A, 031, 069, 06E, 099, 0B2, 0BF, 0C1, 0C3, 0E9, 0FC, 101, 104, 106, 108, 10A, 10C, 10E, 110, 114, 117, 11A, 128, 132
"int16 Item::I_getQHi(Item *)", // same as 026 based on same coff set 026, 045, 047, 049, 04B, 04D, 04F, 0AF, 0BE, 0C9, 0F0, 0F3, 0FB, 133
- "void Intrinsic134(2 bytes)", // something to do with Wezzy/Weasel? Only called from WEA_BOOT::func0A
+ "void WeaselGump::I_showGump(uint16 param)",
"void Actor::I_setDead(Actor *)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
"void UNUSEDInt136()",
"void UNUSEDInt137()"
Commit: 90064583b2e115c419b06d96e9809b7636735040
https://github.com/scummvm/scummvm/commit/90064583b2e115c419b06d96e9809b7636735040
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Add original CD game variant
Provided by ddeluca1com (bug #11944)
Changed paths:
engines/ultima/detection_tables.h
diff --git a/engines/ultima/detection_tables.h b/engines/ultima/detection_tables.h
index 36c7a8e09e..2ad1230b33 100644
--- a/engines/ultima/detection_tables.h
+++ b/engines/ultima/detection_tables.h
@@ -239,6 +239,21 @@ static const UltimaGameDescription GAME_DESCRIPTIONS[] = {
GF_VGA_ENHANCED
},
+ // Ultima VIII - CD (provided by ddeluca1com, bug #11944)
+ {
+ {
+ "ultima8",
+ "",
+ AD_ENTRY1s("eusecode.flx", "5494165cbf4b07be04a465e28350e086", 1209018),
+ Common::EN_ANY,
+ Common::kPlatformDOS,
+ ADGF_NO_FLAGS,
+ GUIO1(GUIO_NOMIDI)
+ },
+ GAME_ULTIMA8,
+ 0
+ },
+
// Ultima VIII - Ultima Collection 1998
{
{
Commit: 28d9667a9eae1ef8bee9d0de71280f9b56c58400
https://github.com/scummvm/scummvm/commit/28d9667a9eae1ef8bee9d0de71280f9b56c58400
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Remove misleading/incorrect comment
Changed paths:
engines/ultima/ultima8/graphics/anim_dat.cpp
diff --git a/engines/ultima/ultima8/graphics/anim_dat.cpp b/engines/ultima/ultima8/graphics/anim_dat.cpp
index 8b56e93156..22f14eed9a 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -240,10 +240,6 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
// bytes 6, 7: more flags
f._flags += rs->readUint16LE() << 16;
- // Map the "flipped" flag to match U8.. is this right?
- //if (f._flags & AnimFrame::AFF_CRUFLIP)
- // f._flags |= AnimFrame::AFF_FLIPPED;
-
/*if (f._flags & AnimFrame::AFF_UNKNOWN) {
warning("AnimFlags: shape %d action %d dir %d frame %d has unknown flags %08X", shape, action, dir, j,
f._flags & AnimFrame::AFF_UNKNOWN);
Commit: 2647bfd0a8680809c4708dc59fde8318cb3f7dff
https://github.com/scummvm/scummvm/commit/2647bfd0a8680809c4708dc59fde8318cb3f7dff
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Ignore 'combat' music in Cruader
Changed paths:
engines/ultima/ultima8/audio/remorse_music_process.cpp
diff --git a/engines/ultima/ultima8/audio/remorse_music_process.cpp b/engines/ultima/ultima8/audio/remorse_music_process.cpp
index aeb39a4dcc..c817ea69db 100644
--- a/engines/ultima/ultima8/audio/remorse_music_process.cpp
+++ b/engines/ultima/ultima8/audio/remorse_music_process.cpp
@@ -108,7 +108,7 @@ void RemorseMusicProcess::playMusic(int track) {
}
void RemorseMusicProcess::playCombatMusic(int track) {
- playMusic_internal(track);
+ // Only U8 has combat music.. ignore it.
}
void RemorseMusicProcess::queueMusic(int track) {
@@ -149,7 +149,7 @@ void RemorseMusicProcess::playMusic_internal(int track) {
Audio::Mixer *mixer = Ultima8Engine::get_instance()->_mixer;
assert(mixer);
- if (track == _currentTrack && mixer->isSoundHandleActive(_soundHandle))
+ if (track == _currentTrack && (track == 0 || mixer->isSoundHandleActive(_soundHandle)))
// Already playing what we want.
return;
Commit: d1992cb52c81c25cb9e755b310e1dd4afed578d9
https://github.com/scummvm/scummvm/commit/d1992cb52c81c25cb9e755b310e1dd4afed578d9
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Improve comments in Process
Changed paths:
engines/ultima/ultima8/kernel/process.cpp
engines/ultima/ultima8/kernel/process.h
diff --git a/engines/ultima/ultima8/kernel/process.cpp b/engines/ultima/ultima8/kernel/process.cpp
index 879e5bfc6c..94d44cf666 100644
--- a/engines/ultima/ultima8/kernel/process.cpp
+++ b/engines/ultima/ultima8/kernel/process.cpp
@@ -74,10 +74,14 @@ void Process::waitFor(ProcId pid) {
if (pid) {
Kernel *kernel = Kernel::get_instance();
- // add this process to waiting list of process pid_
+ // add this process to waiting list of other process
Process *p = kernel->getProcess(pid);
assert(p);
p->_waiting.push_back(_pid);
+
+ // Note: The original games sync itemnum between processes
+ // here if either one is zero, but that seems to break things
+ // for us so we don't do it.
}
_flags |= PROC_SUSPENDED;
diff --git a/engines/ultima/ultima8/kernel/process.h b/engines/ultima/ultima8/kernel/process.h
index 80a47a09f4..f8ece170d1 100644
--- a/engines/ultima/ultima8/kernel/process.h
+++ b/engines/ultima/ultima8/kernel/process.h
@@ -74,8 +74,8 @@ public:
_flags |= PROC_RUNPAUSED;
};
- //! suspend until process '_pid' returns. If _pid is 0, suspend indefinitely
- void waitFor(ProcId _pid);
+ //! suspend until process 'pid' returns. If pid is 0, suspend indefinitely
+ void waitFor(ProcId pid);
//! suspend until process returns. If proc is 0, suspend indefinitely
void waitFor(Process *proc);
Commit: fa9694739f7953a419c8067c9f0b0ff8be30b7df
https://github.com/scummvm/scummvm/commit/fa9694739f7953a419c8067c9f0b0ff8be30b7df
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Animation cleanups
>From reading through the AnimPrimitive disassemblies for U8 and Crusader
side-by-side.
Changed paths:
engines/ultima/ultima8/graphics/anim_dat.cpp
engines/ultima/ultima8/world/actors/actor_anim_process.cpp
engines/ultima/ultima8/world/actors/anim_action.cpp
engines/ultima/ultima8/world/actors/anim_action.h
engines/ultima/ultima8/world/actors/animation_tracker.cpp
diff --git a/engines/ultima/ultima8/graphics/anim_dat.cpp b/engines/ultima/ultima8/graphics/anim_dat.cpp
index 22f14eed9a..cd8f8730c8 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -188,15 +188,16 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
uint32 actionsize = rs->readByte();
a->_actions[action]->_size = actionsize;
// byte 1: flags low byte
- a->_actions[action]->_flags = rs->readByte();
+ uint32 rawflags = rs->readByte();
// byte 2: frame repeat
a->_actions[action]->_frameRepeat = rs->readByte();
// byte 3: flags high byte
- a->_actions[action]->_flags |= rs->readByte() << 8;
+ rawflags |= rs->readByte() << 8;
+
+ a->_actions[action]->_flags = AnimAction::loadAnimActionFlags(rawflags);
unsigned int dirCount = 8;
- if (GAME_IS_CRUSADER &&
- (a->_actions[action]->_flags & AnimAction::AAF_CRUS_16DIRS)) {
+ if (a->_actions[action]->hasFlags(AnimAction::AAF_16DIRS)) {
dirCount = 16;
}
@@ -234,7 +235,7 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
f._sfx = rs->readByte();
// byte 4: deltadir (signed) - convert to pixels
f._deltaDir = rs->readSByte();
- // byte 5: flags TODO: Ensure "flipped" flag is mapped correctly
+ // byte 5: flags
f._flags = rs->readByte();
f._flags += (x & 0xF0) << 8;
// bytes 6, 7: more flags
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
index 49258ea8c2..6b863532b9 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
@@ -221,10 +221,9 @@ void ActorAnimProcess::run() {
return;
}
-
if (_tracker->isBlocked() &&
- !(_tracker->getAnimAction()->hasFlags(AnimAction::AAF_UNSTOPPABLE))) {
- // FIXME: For blocked large _steps we may still want to do
+ !_tracker->getAnimAction()->hasFlags(AnimAction::AAF_UNSTOPPABLE)) {
+ // FIXME: For blocked large steps we may still want to do
// a partial move. (But how would that work with
// repeated frames?)
@@ -255,18 +254,18 @@ void ActorAnimProcess::run() {
}
const AnimFrame *curframe = _tracker->getAnimFrame();
- if (curframe && curframe->_sfx) {
- AudioProcess *audioproc = AudioProcess::get_instance();
- if (audioproc) audioproc->playSFX(curframe->_sfx, 0x60, _itemNum, 0);
- }
-
if (curframe) {
+ if (curframe->_sfx) {
+ AudioProcess *audioproc = AudioProcess::get_instance();
+ if (audioproc) audioproc->playSFX(curframe->_sfx, 0x60, _itemNum, 0);
+ }
+
if (curframe->_flags & AnimFrame::AFF_SPECIAL) {
// Flag to trigger a special action
// E.g.: play draw/sheathe SFX for avatar when weapon equipped,
// throw skull-fireball when ghost attacks, ...
doSpecial();
- } else if (curframe->_flags & AnimFrame::AFF_HURTY) {
+ } else if (curframe->_flags & AnimFrame::AFF_HURTY && GAME_IS_CRUSADER) {
a->tookHitCru();
}
}
diff --git a/engines/ultima/ultima8/world/actors/anim_action.cpp b/engines/ultima/ultima8/world/actors/anim_action.cpp
index 5194402d2b..b2a00486ee 100644
--- a/engines/ultima/ultima8/world/actors/anim_action.cpp
+++ b/engines/ultima/ultima8/world/actors/anim_action.cpp
@@ -23,6 +23,7 @@
#include "ultima/ultima8/misc/pent_include.h"
#include "ultima/ultima8/world/actors/anim_action.h"
#include "ultima/ultima8/world/actors/actor.h"
+#include "ultima/ultima8/kernel/core_app.h"
namespace Ultima {
namespace Ultima8 {
@@ -34,9 +35,11 @@ void AnimAction::getAnimRange(unsigned int lastanim, Direction lastdir,
endframe = _size;
if (_flags & AAF_TWOSTEP) {
+ const bool looping = hasFlags(AAF_LOOPING);
+
// two-step animation?
if (firststep) {
- if (_flags & (AAF_LOOPING | AAF_LOOPING2)) {// CHECKME: unknown flag
+ if (looping) {
// for a looping animation, start at the end to
// make things more fluid
startframe = _size - 1;
@@ -47,7 +50,7 @@ void AnimAction::getAnimRange(unsigned int lastanim, Direction lastdir,
} else {
// second step starts halfway
startframe = _size / 2;
- if (_flags & (AAF_LOOPING | AAF_LOOPING2)) {// CHECKME: unknown flag
+ if (looping) {
endframe = _size - 1;
}
}
@@ -79,5 +82,31 @@ const AnimFrame &AnimAction::getFrame(Direction dir, unsigned int frameno) const
return _frames[diroff][frameno];
}
+/**
+ Translate data file flags of U8 or Crusader into single format, to avoid
+ having to check against game type each time they are used
+*/
+/*static*/
+AnimAction::AnimActionFlags AnimAction::loadAnimActionFlags(uint16 rawflags) {
+ uint32 ret = AAF_NONE;
+ ret |= (rawflags & AAF_COMMONFLAGS);
+ if (GAME_IS_U8) {
+ if (rawflags & AAF_ATTACK)
+ ret |= AAF_ATTACK;
+ if (rawflags & AAF_LOOPING2_U8)
+ ret |= AAF_LOOPING; // FIXME: handled like this is in pentagram code.. is it used?
+ } else {
+ assert(GAME_IS_CRUSADER);
+ if (rawflags & AAF_ROTATED)
+ ret |= AAF_ROTATED;
+ if (rawflags & AAF_16DIRS)
+ ret |= AAF_16DIRS;
+ }
+
+ return static_cast<AnimActionFlags>(ret);
+}
+
+
+
} // End of namespace Ultima8
} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/actors/anim_action.h b/engines/ultima/ultima8/world/actors/anim_action.h
index 0e7ddc218f..7725153abf 100644
--- a/engines/ultima/ultima8/world/actors/anim_action.h
+++ b/engines/ultima/ultima8/world/actors/anim_action.h
@@ -38,29 +38,37 @@ struct AnimFrame {
int _sfx;
uint32 _flags;
+ /** Frame level flags */
enum AnimFrameFlags {
- AFF_UNK1 = 0x00000001,
AFF_ONGROUND = 0x00000002,
AFF_FLIPPED = 0x00000020,
- AFF_CRUFLIP = 0x00000080,
AFF_SPECIAL = 0x00000800, // U8 only
AFF_HURTY = 0x00001000, // Crusader only - TODO: find a better name for this.
AFF_USECODE = 0x00004000,
- AFF_NOSTOP = 0x00008000 // Crusader only - Probably - applied to most death animations
+ AFF_CRUFLIP = 0x00008000 // Crusader only
//AFF_UNKNOWN = 0xF0E0B01C,
//AFF_FIRE = 0x0F1F00C0
};
+ inline bool is_onground() const {
+ return (_flags & AFF_ONGROUND) != 0;
+ }
+
inline bool is_flipped() const {
return (_flags & AFF_FLIPPED) != 0;
}
- inline int attack_range() const {
- return ((_flags >> 2) & 0x07);
- }
inline bool is_callusecode() const {
return (_flags & AFF_USECODE) != 0;
}
+
+ inline bool is_cruflipped() const {
+ return (_flags & AFF_CRUFLIP) != 0;
+ }
+
+ inline int attack_range() const {
+ return ((_flags >> 2) & 0x07);
+ }
};
class AnimAction {
@@ -93,47 +101,59 @@ public:
unsigned int getSize() const {
return _size;
}
-
+
int getFrameRepeat() const {
return _frameRepeat;
}
-
+
uint32 getShapeNum() const {
return _shapeNum;
}
-
+
uint32 getAction() const {
return _action;
}
-
+
bool hasFlags(uint32 mask) const {
return (_flags & mask) != 0;
}
-
+
const AnimFrame &getFrame(Direction dir, unsigned int frameno) const;
+ /**
+ * Animation level flags
+ *
+ * Note: Although these match the original values in the dat files, there is cleanup
+ * at load time to avoid having to check game type in many places in the code.
+ * See loadAnimActionFlags in anim_action.cpp
+ */
enum AnimActionFlags {
+ AAF_NONE = 0x0000,
AAF_TWOSTEP = 0x0001,
- AAF_ATTACK = 0x0002,
+ AAF_ATTACK = 0x0002, // U8 only
AAF_LOOPING = 0x0004,
AAF_UNSTOPPABLE = 0x0008,
- AAF_LOOPING2 = 0x0010, // CHECKME: guessing at this flag
- AAF_LOOPING3 = 0x0040, // CHECKME: Crusader triggers a new anim in the terminate if this flag is set and the start point was null
+ AAF_LOOPING2_U8 = 0x0010,
+ AAF_ENDLOOP_U8 = 0x0020, // TODO: This starts a new anim at the end if pathfinding
+ AAF_ENDLOOP_CRU = 0x0040, // TODO: This starts a new anim at the end if pathfinding
AAF_HANGING = 0x0080,
- AAF_CRUS_ROTATED = 0x1000,
- AAF_CRUS_16DIRS = 0x4000, // Crusader
+ AAF_ROTATED = 0x1000, // Cru only
+ AAF_16DIRS = 0x4000, // Cru only
AAF_DESTROYACTOR = 0x8000, // destroy actor after animation finishes
- AAF_UNKFLAGS = 0x3F20
+ AAF_COMMONFLAGS = (AAF_TWOSTEP | AAF_LOOPING | AAF_UNSTOPPABLE | AAF_HANGING | AAF_DESTROYACTOR)
};
+
private:
+ static AnimActionFlags loadAnimActionFlags(uint16 rawflags);
+
uint32 _shapeNum;
uint32 _action;
Std::vector<AnimFrame> _frames[16]; // 8 or 16 directions
unsigned int _size;
int _frameRepeat;
- uint32 _flags;
+ AnimActionFlags _flags;
unsigned int _dirCount;
};
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index 7d2d8a93ec..8e76254201 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -118,8 +118,7 @@ unsigned int AnimationTracker::getNextFrame(unsigned int frame) const {
// loop if necessary
if (frame >= _animAction->getSize()) {
- if (_animAction->hasFlags(AnimAction::AAF_LOOPING |
- AnimAction::AAF_LOOPING2)) {
+ if (_animAction->hasFlags(AnimAction::AAF_LOOPING)) {
// CHECKME: unknown flag
frame = 1;
} else {
@@ -189,6 +188,9 @@ bool AnimationTracker::step() {
return false;
}
+ const bool is_u8 = GAME_IS_U8;
+ const bool is_crusader = !is_u8;
+
_prevX = _x;
_prevY = _y;
_prevZ = _z;
@@ -203,14 +205,15 @@ bool AnimationTracker::step() {
const AnimFrame &f = _animAction->getFrame(_dir, _currentFrame);
_shapeFrame = f._frame;
- _flipped = f.is_flipped();
+ _flipped = (is_u8 && f.is_flipped())
+ || (is_crusader && f.is_cruflipped());
// determine movement for this frame
int32 dx = 4 * Direction_XFactor(_dir) * f._deltaDir;
int32 dy = 4 * Direction_YFactor(_dir) * f._deltaDir;
int32 dz = f._deltaZ;
- if (_mode == TargetMode && !(f._flags & AnimFrame::AFF_ONGROUND)) {
+ if (_mode == TargetMode && !f.is_onground()) {
dx += _targetDx / _targetOffGroundLeft;
dy += _targetDy / _targetOffGroundLeft;
dz += _targetDz / _targetOffGroundLeft;
@@ -306,7 +309,7 @@ bool AnimationTracker::step() {
a->getShapeInfo()->_flags,
_actor, &support, 0);
- if (GAME_IS_U8 && targetok && support) {
+ if (is_u8 && targetok && support) {
// Might need to check for bridge traversal adjustments
uint32 supportshape = support->getShape();
if (supportshape >= 675 && supportshape <= 681) {
@@ -337,14 +340,14 @@ bool AnimationTracker::step() {
}
}
- if (!targetok || ((f._flags & AnimFrame::AFF_ONGROUND) && !support)) {
+ if (!targetok || (f.is_onground() && !support)) {
// If on ground, try to adjust properly
// TODO: Profile the effect of disabling this for pathfinding.
// It shouldn't be necessary in that case, and may provide a
// worthwhile speed-up.
- if ((f._flags & AnimFrame::AFF_ONGROUND) && zd > 8) {
- if (GAME_IS_CRUSADER && !targetok && support) {
+ if (f.is_onground() && zd > 8) {
+ if (is_crusader && !targetok && support) {
// Possibly trying to step onto an elevator platform which stops at a z slightly
// above the floor. Re-scan with a small adjustment.
// This is a bit of a temporary hack to make navigation possible.. it "hurls"
@@ -393,7 +396,7 @@ bool AnimationTracker::step() {
checkWeaponHit();
}
- if (f._flags & AnimFrame::AFF_ONGROUND) {
+ if (f.is_onground()) {
// needs support
/*bool targetok = */ cm->isValidPosition(tx, ty, tz,
@@ -423,7 +426,7 @@ bool AnimationTracker::step() {
}
}
- if (f.is_callusecode() && GAME_IS_CRUSADER) {
+ if (f.is_callusecode()) {
a->callUsecodeEvent_calledFromAnim();
}
@@ -445,7 +448,7 @@ void AnimationTracker::setTargetedMode(int32 x, int32 y, int32 z) {
const AnimFrame &f = _animAction->getFrame(_dir, i);
totaldir += f._deltaDir; // This line sometimes seg faults.. ????
totalz += f._deltaZ;
- if (!(f._flags & AnimFrame::AFF_ONGROUND))
+ if (!f.is_onground())
++offGround;
}
@@ -550,7 +553,7 @@ void AnimationTracker::updateActorFlags() {
else
a->clearActorFlag(Actor::ACT_FIRSTSTEP);
- if (_animAction) {
+ if (_animAction && GAME_IS_U8) {
bool hanging = _animAction->hasFlags(AnimAction::AAF_HANGING);
if (hanging)
a->setFlag(Item::FLG_HANGING);
@@ -672,7 +675,7 @@ bool AnimationTracker::load(Common::ReadStream *rs, uint32 version) {
for (; i != _endFrame; i = getNextFrame(i)) {
const AnimFrame &f = _animAction->getFrame(_dir, i);
- if (!(f._flags & AnimFrame::AFF_ONGROUND))
+ if (f.is_onground())
++_targetOffGroundLeft;
}
Commit: fe32fcf59602cad9c0799298d0e0ffe4c8634e75
https://github.com/scummvm/scummvm/commit/fe32fcf59602cad9c0799298d0e0ffe4c8634e75
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Apply crusader anim rotation flag
Changed paths:
engines/ultima/ultima8/world/actors/animation_tracker.cpp
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index 8e76254201..fc1954e581 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -209,8 +209,13 @@ bool AnimationTracker::step() {
|| (is_crusader && f.is_cruflipped());
// determine movement for this frame
- int32 dx = 4 * Direction_XFactor(_dir) * f._deltaDir;
- int32 dy = 4 * Direction_YFactor(_dir) * f._deltaDir;
+ Direction movedir = _dir;
+ if (_animAction->hasFlags(AnimAction::AAF_ROTATED)) {
+ movedir = Direction_TurnByDelta(movedir, 4, dirmode_16dirs);
+ }
+
+ int32 dx = 4 * Direction_XFactor(movedir) * f._deltaDir;
+ int32 dy = 4 * Direction_YFactor(movedir) * f._deltaDir;
int32 dz = f._deltaZ;
if (_mode == TargetMode && !f.is_onground()) {
Commit: 280c103bc520a44d418b28eff5873034aad2a0d6
https://github.com/scummvm/scummvm/commit/280c103bc520a44d418b28eff5873034aad2a0d6
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Enable crusader firing from animation flags
Changed paths:
engines/ultima/ultima8/world/actors/actor_anim_process.cpp
engines/ultima/ultima8/world/actors/actor_anim_process.h
engines/ultima/ultima8/world/actors/anim_action.h
engines/ultima/ultima8/world/item.cpp
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
index 6b863532b9..8673129ac9 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
@@ -267,6 +267,8 @@ void ActorAnimProcess::run() {
doSpecial();
} else if (curframe->_flags & AnimFrame::AFF_HURTY && GAME_IS_CRUSADER) {
a->tookHitCru();
+ } else if (curframe->is_cruattack() && GAME_IS_CRUSADER) {
+ doFireWeaponCru(a, curframe);
}
}
@@ -497,6 +499,30 @@ void ActorAnimProcess::doSpecial() {
}
+void ActorAnimProcess::doFireWeaponCru(Actor *a, const AnimFrame *f) {
+ assert(a);
+ assert(f);
+ if (!f->is_cruattack())
+ return;
+
+ // TODO: there is some special casing in the game for larger weapons here..
+ const Item *wpn = getItem(a->getActiveWeapon());
+ if (!wpn)
+ return;
+ const ShapeInfo *wpninfo = wpn->getShapeInfo();
+ if (!wpninfo || !wpninfo->_weaponInfo)
+ return;
+
+ a->fireWeapon(f->cru_attackx(), f->cru_attacky(), f->cru_attackz(),
+ dir_current, wpninfo->_weaponInfo->_damageType, 1);
+
+ AudioProcess *audioproc = AudioProcess::get_instance();
+ if (audioproc)
+ audioproc->playSFX(wpninfo->_weaponInfo->_sound, 0x80, a->getObjId(), 0, false);
+
+}
+
+
void ActorAnimProcess::doHitSpecial(Item *hit) {
Actor *a = getActor(_itemNum);
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.h b/engines/ultima/ultima8/world/actors/actor_anim_process.h
index 0c87d8fdd3..7fb4fa354e 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.h
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.h
@@ -32,6 +32,7 @@ namespace Ultima8 {
class Actor;
class AnimAction;
+class AnimFrame;
class AnimationTracker;
class Item;
@@ -69,6 +70,9 @@ protected:
//! perform special action when hitting an opponent
void doHitSpecial(Item *hit);
+ //! Fire weapon
+ void doFireWeaponCru(Actor *actor, const AnimFrame *frame);
+
Animation::Sequence _action;
Direction _dir;
uint32 _steps;
diff --git a/engines/ultima/ultima8/world/actors/anim_action.h b/engines/ultima/ultima8/world/actors/anim_action.h
index 7725153abf..683cd9ae2c 100644
--- a/engines/ultima/ultima8/world/actors/anim_action.h
+++ b/engines/ultima/ultima8/world/actors/anim_action.h
@@ -69,6 +69,28 @@ struct AnimFrame {
inline int attack_range() const {
return ((_flags >> 2) & 0x07);
}
+
+ // Note: The next 3 functions each have a 4-bit
+ // signed value to unpack from the flags.
+ inline int cru_attackx() const {
+ uint32 rawx = (_flags & 0x00000780) << 5;
+ int16 signedx = static_cast<int16>(rawx) >> 12;
+ return signedx * 16;
+ }
+
+ inline int cru_attacky() const {
+ uint32 rawy = (_flags & 0x00F00000) >> 16;
+ return static_cast<int8>(rawy);
+ }
+
+ inline int cru_attackz() const {
+ uint32 rawz = (_flags & 0x0F000000) >> 20;
+ return static_cast<int8>(rawz) / 2;
+ }
+
+ inline bool is_cruattack() const {
+ return (cru_attackx() || cru_attacky() || cru_attackz());
+ }
};
class AnimAction {
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 9db234fce9..5a280c16bd 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1176,7 +1176,9 @@ uint16 Item::fireWeapon(int32 x, int32 y, int32 z, Direction dir, int firetype,
int damage = firetypedat->getRandomDamage();
const Item *blocker = nullptr;
- bool isvalid = currentmap->isValidPosition(ix, iy, iz, BULLET_SPLASH_SHAPE, 0, nullptr, nullptr, &blocker);
+ // CHECKME: the original doesn't exclude the source like this,
+ // but it seems obvious we have to or NPCs shoot themselves?
+ bool isvalid = currentmap->isValidPosition(ix, iy, iz, BULLET_SPLASH_SHAPE, _objId, nullptr, nullptr, &blocker);
if (!isvalid && blocker) {
Item *block = getItem(blocker->getObjId());
Point3 blockpt;
Commit: f9b14adc62e4e6d0d010a40f07940b49bd4f7f1c
https://github.com/scummvm/scummvm/commit/f9b14adc62e4e6d0d010a40f07940b49bd4f7f1c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-12-20T09:35:32+09:00
Commit Message:
ULTIMA8: Correct the way typeflags are used
For both U8 and Crusader, load and use "animSpeed" bits. Finally everything
animates at the right speed in both games!
Changed paths:
engines/ultima/ultima8/graphics/shape_info.cpp
engines/ultima/ultima8/graphics/shape_info.h
engines/ultima/ultima8/graphics/type_flags.cpp
engines/ultima/ultima8/gumps/game_map_gump.cpp
engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
engines/ultima/ultima8/world/item.cpp
engines/ultima/ultima8/world/item_selection_process.cpp
diff --git a/engines/ultima/ultima8/graphics/shape_info.cpp b/engines/ultima/ultima8/graphics/shape_info.cpp
index df2c308468..e1d43f1e6d 100644
--- a/engines/ultima/ultima8/graphics/shape_info.cpp
+++ b/engines/ultima/ultima8/graphics/shape_info.cpp
@@ -62,8 +62,8 @@ bool ShapeInfo::getTypeFlagU8(int typeFlag) const {
} else if (typeFlag <= 39) { // animdata Byte 4:4-7 Bits 36-49
return (_animData >> (typeFlag - 36)) & 1;
} else if (typeFlag <= 43) { // unknown Byte 5:0-3 Bits 40-43
- return (_unknown >> (typeFlag - 40)) & 1;
- } else if (typeFlag <= 47) { // _flags Byte 5:4-7 Bits 44-47
+ return (_animSpeed >> (typeFlag - 40)) & 1;
+ } else if (typeFlag <= 47) { // _flags Byte 5:4-7 Bits 44-47
return (_flags >> (12 + typeFlag - 44)) & 1;
} else if (typeFlag <= 55) { // weight Byte 6 Bits 48-55
return (_weight >> (typeFlag - 48)) & 1;
@@ -80,7 +80,7 @@ bool ShapeInfo::getTypeFlagCrusader(int typeFlag) const {
} else if (typeFlag <= 16) { // _family Byte 1:4-7,2:0 Bits 12-16
return (_family >> (typeFlag - 12)) & 1;
} else if (typeFlag <= 20) { // unknown Byte 2:0-3 Bits 17-20
- perr << "Warning: unknown typeFlag requested." << Std::endl;
+ perr << "Warning: unknown typeFlag " << typeFlag << " requested." << Std::endl;
} else if (typeFlag <= 26) { // x Byte 2:4-7,3:0-1 Bits 21-26
return (_x >> (typeFlag - 21)) & 1;
} else if (typeFlag <= 31) { // y Byte 3:2-6 Bits 27-31
@@ -88,11 +88,11 @@ bool ShapeInfo::getTypeFlagCrusader(int typeFlag) const {
} else if (typeFlag <= 36) { // z Byte 3:7,4:0-3 Bits 32-36
return (_z >> (typeFlag - 32)) & 1;
} else if (typeFlag <= 47) {
- perr << "Warning: unknown typeFlag requested." << Std::endl;
+ perr << "Warning: unknown typeFlag " << typeFlag << " requested." << Std::endl;
} else if (typeFlag <= 55) { // _flags Byte 6: 0-7 Bits 48-55
return (_flags >> (12 + typeFlag - 55)) & 1;
} else if (typeFlag <= 71) {
- perr << "Warning: unknown typeFlag requested." << Std::endl;
+ perr << "Warning: unknown typeFlag " << typeFlag << " requested." << Std::endl;
}
return false;
diff --git a/engines/ultima/ultima8/graphics/shape_info.h b/engines/ultima/ultima8/graphics/shape_info.h
index e1f65ab17d..32eed9b3a5 100644
--- a/engines/ultima/ultima8/graphics/shape_info.h
+++ b/engines/ultima/ultima8/graphics/shape_info.h
@@ -47,16 +47,17 @@ public:
SI_ROOF = 0x0400,
SI_TRANSL = 0x0800,
SI_EDITOR = 0x1000,
- SI_EXPLODE = 0x2000,
- SI_UNKNOWN46 = 0x4000,
- SI_UNKNOWN47 = 0x8000,
- SI_SELECTABLE= 0x2000,
- SI_CRUSUNK62 = 0x4000,
- SI_CRUSUNK63 = 0x8000,
- SI_TARGETABLE= 0x10000,
- SI_CRUS_NPC = 0x20000,
- SI_CRUSUNK66 = 0x40000,
- SI_CRUSUNK67 = 0x80000
+ // Note: overlapping names for the rest of the bits depending on U8 or Cru.
+ SI_U8_EXPLODE = 0x2000,
+ SI_CRU_SELECTABLE = 0x2000,
+ SI_UNKNOWN46 = 0x4000,
+ SI_CRU_PRELOAD = 0x4000, // we don't need this flag, we preload everything.
+ SI_UNKNOWN47 = 0x8000,
+ SI_CRU_SOUND = 0x8000, // TODO: how is this used?
+ SI_CRU_TARGETABLE = 0x10000,
+ SI_CRU_NPC = 0x20000,
+ SI_CRU_UNK66 = 0x40000,
+ SI_CRU_UNK67 = 0x80000
};
enum SFamily {
@@ -93,8 +94,7 @@ public:
uint32 _x, _y, _z;
uint32 _family;
uint32 _equipType;
- uint32 _animType, _animData;
- uint32 _unknown;
+ uint32 _animType, _animData, _animSpeed;
uint32 _weight, _volume;
WeaponInfo *_weaponInfo;
@@ -141,8 +141,8 @@ public:
inline bool is_editor() const {
return (_flags & SI_EDITOR) != 0;
}
- inline bool is_explode() const {
- return (_flags & SI_EXPLODE) != 0;
+ inline bool is_u8_explode() const {
+ return (_flags & SI_U8_EXPLODE) != 0;
}
bool hasQuantity() const {
@@ -162,7 +162,7 @@ public:
ShapeInfo() :
_flags(0), _x(0), _y(0), _z(0),
_family(0), _equipType(0), _animType(0), _animData(0),
- _unknown(0), _weight(0), _volume(0),
+ _animSpeed(0), _weight(0), _volume(0),
_weaponInfo(nullptr), _armourInfo(nullptr),
_monsterInfo(nullptr), _damageInfo(nullptr) { }
diff --git a/engines/ultima/ultima8/graphics/type_flags.cpp b/engines/ultima/ultima8/graphics/type_flags.cpp
index 039f48cb39..677a2fd344 100644
--- a/engines/ultima/ultima8/graphics/type_flags.cpp
+++ b/engines/ultima/ultima8/graphics/type_flags.cpp
@@ -94,10 +94,10 @@ void TypeFlags::load(Common::SeekableReadStream *rs) {
si._animType = data[4] & 0x0F;
si._animData = data[4] >> 4;
+ si._animSpeed = data[5] & 0x0F;
- si._unknown = data[5] & 0x0F;
if (data[5] & 0x10) si._flags |= ShapeInfo::SI_EDITOR;
- if (data[5] & 0x20) si._flags |= ShapeInfo::SI_EXPLODE;
+ if (data[5] & 0x20) si._flags |= ShapeInfo::SI_U8_EXPLODE;
if (data[5] & 0x40) si._flags |= ShapeInfo::SI_UNKNOWN46;
if (data[5] & 0x80) si._flags |= ShapeInfo::SI_UNKNOWN47;
@@ -105,10 +105,13 @@ void TypeFlags::load(Common::SeekableReadStream *rs) {
si._volume = data[7];
} else if (GAME_IS_CRUSADER) {
+ // Changes from U8 to Crusader:
+ // * SI_OCCL seems to be used more like "target" in Cru
+ // * SI_BAG bit seems to have a different meaning in Cru
+ // (multi-panel?), but we don't use it anyway
+ // * Family/x/y/z are all now 5 bits
+ // * There are more and different flags in the last byte
- // might have to split up remorse/regret at some point
-
- // unchecked
if (data[0] & 0x01) si._flags |= ShapeInfo::SI_FIXED;
if (data[0] & 0x02) si._flags |= ShapeInfo::SI_SOLID;
if (data[0] & 0x04) si._flags |= ShapeInfo::SI_SEA;
@@ -118,7 +121,6 @@ void TypeFlags::load(Common::SeekableReadStream *rs) {
if (data[0] & 0x40) si._flags |= ShapeInfo::SI_DAMAGING;
if (data[0] & 0x80) si._flags |= ShapeInfo::SI_NOISY;
- // unchecked
if (data[1] & 0x01) si._flags |= ShapeInfo::SI_DRAW;
if (data[1] & 0x02) si._flags |= ShapeInfo::SI_IGNORE;
if (data[1] & 0x04) si._flags |= ShapeInfo::SI_ROOF;
@@ -126,36 +128,27 @@ void TypeFlags::load(Common::SeekableReadStream *rs) {
si._family = data[1] >> 4;
si._family += (data[2] & 1) << 4;
- uint32 unk2data = (data[2] >> 1) & 0xF;
+ si._equipType = (data[2] >> 1) & 0xF;
si._x = ((data[3] << 3) | (data[2] >> 5)) & 0x1F;
si._y = (data[3] >> 2) & 0x1F;
si._z = ((data[4] << 1) | (data[3] >> 7)) & 0x1F;
- // Left over bits we're not sure what to do with yet..
- si._unknown = (unk2data << 16) | (((data[4] & 0xF0) << 8) | data[5]);
+ si._animType = data[4] >> 4;
+ si._animData = data[5] & 0x0F;
+ si._animSpeed = data[5] >> 4;
if (data[6] & 0x01) si._flags |= ShapeInfo::SI_EDITOR;
- if (data[6] & 0x02) si._flags |= ShapeInfo::SI_SELECTABLE;
- if (data[6] & 0x04) si._flags |= ShapeInfo::SI_CRUSUNK62;
- if (data[6] & 0x08) si._flags |= ShapeInfo::SI_CRUSUNK63;
- if (data[6] & 0x10) si._flags |= ShapeInfo::SI_TARGETABLE;
- if (data[6] & 0x20) si._flags |= ShapeInfo::SI_CRUS_NPC;
- if (data[6] & 0x40) si._flags |= ShapeInfo::SI_CRUSUNK66;
- if (data[6] & 0x80) si._flags |= ShapeInfo::SI_CRUSUNK67;
+ if (data[6] & 0x02) si._flags |= ShapeInfo::SI_CRU_SELECTABLE;
+ if (data[6] & 0x04) si._flags |= ShapeInfo::SI_CRU_PRELOAD;
+ if (data[6] & 0x08) si._flags |= ShapeInfo::SI_CRU_SOUND;
+ if (data[6] & 0x10) si._flags |= ShapeInfo::SI_CRU_TARGETABLE;
+ if (data[6] & 0x20) si._flags |= ShapeInfo::SI_CRU_NPC;
+ if (data[6] & 0x40) si._flags |= ShapeInfo::SI_CRU_UNK66;
+ if (data[6] & 0x80) si._flags |= ShapeInfo::SI_CRU_UNK67;
si._weight = data[7];
si._volume = data[8];
-
- // FIXME: this is not exactly right, but it is close and at
- // least it animates the main items that need
- // continuously animating
- si._animType = (data[4] & 0xF0) >> 4;
- if (si._animType == 4) {
- // FIXME: Only one object (Shape 360, a small glowing
- // reactor) has this type what should it do?
- si._animType = 1;
- }
} else {
error("unknown game type in type flags");
}
diff --git a/engines/ultima/ultima8/gumps/game_map_gump.cpp b/engines/ultima/ultima8/gumps/game_map_gump.cpp
index ded60fbcd2..29ef2cb382 100644
--- a/engines/ultima/ultima8/gumps/game_map_gump.cpp
+++ b/engines/ultima/ultima8/gumps/game_map_gump.cpp
@@ -125,6 +125,8 @@ void GameMapGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled)
_displayList->BeginDisplayList(surf, lx, ly, lz);
uint32 gametick = Kernel::get_instance()->getFrameNum();
+ if (GAME_IS_CRUSADER)
+ gametick /= 2;
bool paintEditorItems = Ultima8Engine::get_instance()->isPaintEditorItems();
diff --git a/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp b/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
index baf31177c7..de651840e4 100644
--- a/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
+++ b/engines/ultima/ultima8/gumps/shape_viewer_gump.cpp
@@ -143,7 +143,7 @@ void ShapeViewerGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool /*s
uint8 px_r = shape->getPalette()->_palette[rawpx * 3];
uint8 px_g = shape->getPalette()->_palette[rawpx * 3 + 1];
uint8 px_b = shape->getPalette()->_palette[rawpx * 3 + 2];
-
+
sprintf(buf2, "px: (%d/%d, %d/%d): %d (%d, %d, %d)", relx, frame->_xoff, rely, frame->_yoff, rawpx, px_r, px_g, px_b);
rendtext = font->renderText(buf2, remaining);
rendtext->draw(surf, 20, 25);
@@ -151,9 +151,8 @@ void ShapeViewerGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool /*s
}
}
-
}
-
+
{
// Additional shapeinfo (only in main shapes archive)
MainShapeArchive *mainshapes = dynamic_cast<MainShapeArchive *>(_flex);
@@ -167,11 +166,11 @@ void ShapeViewerGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool /*s
if (info) {
sprintf(buf3, "x: %d, y: %d, z: %d\n flags: 0x%04X, family: %d",
info->_x, info->_y, info->_z, info->_flags, info->_family);
- sprintf(buf4, "equip type: %d, unk. flags: 0x%02X\n weight: %d",
- info->_equipType, info->_unknown, info->_weight);
- sprintf(buf5, "vol: %d\n animtype: %d, animdata: %d",
- info->_volume, info->_animType, info->_animData);
- sprintf(buf6, "ShapeInfo: %s\n %s, %s\nUsecode: %s",
+ sprintf(buf4, "equip type: %d, weight: %d, vol: %d",
+ info->_equipType, info->_weight, info->_volume);
+ sprintf(buf5, "anim: type: %d, data: %d, speed: %d",
+ info->_animType, info->_animData, info->_animSpeed);
+ sprintf(buf6, "ShapeInfo: %s\n%s\n%s\nUsecode: %s",
buf3, buf4, buf5, GameData::get_instance()->getMainUsecode()->get_class_name(_curShape));
rendtext = font->renderText(buf6, remaining);
rendtext->draw(surf, 20, _dims.height() - 58);
@@ -187,6 +186,7 @@ bool ShapeViewerGump::OnKeyDown(int key, int mod) {
switch (key) {
case Common::KEYCODE_UP:
+ case Common::KEYCODE_k:
if (delta >= _flex->getCount()) delta = 1;
if (_curShape < delta)
_curShape = _flex->getCount() + _curShape - delta;
@@ -196,6 +196,7 @@ bool ShapeViewerGump::OnKeyDown(int key, int mod) {
_curFrame = 0;
break;
case Common::KEYCODE_DOWN:
+ case Common::KEYCODE_j:
if (delta >= _flex->getCount()) delta = 1;
if (_curShape + delta >= _flex->getCount())
_curShape = _curShape + delta - _flex->getCount();
@@ -204,7 +205,8 @@ bool ShapeViewerGump::OnKeyDown(int key, int mod) {
_curFrame = 0;
shapechanged = true;
break;
- case Common::KEYCODE_LEFT: {
+ case Common::KEYCODE_LEFT:
+ case Common::KEYCODE_h: {
const Shape *shape = _flex->getShape(_curShape);
if (shape && shape->frameCount()) {
if (delta >= shape->frameCount()) delta = 1;
@@ -215,7 +217,8 @@ bool ShapeViewerGump::OnKeyDown(int key, int mod) {
}
}
break;
- case Common::KEYCODE_RIGHT: {
+ case Common::KEYCODE_RIGHT:
+ case Common::KEYCODE_l: {
const Shape *shape = _flex->getShape(_curShape);
if (shape && shape->frameCount()) {
if (delta >= shape->frameCount()) delta = 1;
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 5a280c16bd..74962a590f 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -1585,7 +1585,7 @@ void Item::destroy(bool delnow) {
//
// Item::setupLerp()
//
-// Desc: Setup the lerped info for this _frame
+// Desc: Setup the lerped info for this frame
//
void Item::setupLerp(int32 gametick) {
// Don't need to set us up
@@ -1609,7 +1609,10 @@ void Item::setupLerp(int32 gametick) {
_extendedFlags &= ~EXT_LERP_NOPREV;
// Animate it, if needed
- if ((gametick % 3) == (_objId % 3)) animateItem();
+ const ShapeInfo *info = getShapeInfo();
+ if (info->_animType &&
+ ((gametick % info->_animSpeed) == (_objId % info->_animSpeed)))
+ animateItem();
// Setup the prev values for lerping
if (!no_lerp) _lPrev = _lNext;
@@ -1634,16 +1637,18 @@ void Item::setupLerp(int32 gametick) {
// Animate the item
void Item::animateItem() {
const ShapeInfo *info = getShapeInfo();
- const Shape *shp = getShapeObject();
- if (!info->_animType) return;
+ if (!info->_animType)
+ return;
int anim_data = info->_animData;
- //bool dirty = false;
+ int speed = info->_animSpeed;
- if ((static_cast<int>(_lastSetup) % 6) != (_objId % 6) && info->_animType != 1)
+ if ((static_cast<int>(_lastSetup) % speed * 2) != (_objId % speed * 2) && info->_animType != 1)
return;
+ const Shape *shp = getShapeObject();
+
switch (info->_animType) {
case 2:
// 50 % chance
@@ -1658,23 +1663,21 @@ void Item::animateItem() {
if (anim_data < 2) {
if (shp && _frame == shp->frameCount()) _frame = 0;
} else {
+ // Data represents frame count for the loop
unsigned int num = (_frame - 1) / anim_data;
if (_frame == ((num + 1)*anim_data)) _frame = num * anim_data;
}
- //dirty = true;
break;
case 4:
if (!(getRandom() % anim_data)) break;
_frame ++;
if (shp && _frame == shp->frameCount()) _frame = 0;
- //dirty = true;
break;
case 5:
callUsecodeEvent_anim();
- //dirty = true;
break;
case 6:
@@ -1688,14 +1691,12 @@ void Item::animateItem() {
unsigned int num = (_frame - 1) / anim_data;
if (_frame == ((num + 1)*anim_data)) _frame = num * anim_data + 1;
}
- //dirty = true;
break;
default:
pout << "type " << info->_animType << " data " << anim_data << Std::endl;
break;
}
- //return dirty;
}
@@ -1724,7 +1725,7 @@ void Item::enterFastArea() {
if (!hasFlags(FLG_BROKEN) && GAME_IS_CRUSADER) {
const ShapeInfo *si = getShapeInfo();
- if ((si->_flags & ShapeInfo::SI_TARGETABLE) || (si->_flags & ShapeInfo::SI_OCCL)) {
+ if ((si->_flags & ShapeInfo::SI_CRU_TARGETABLE) || (si->_flags & ShapeInfo::SI_OCCL)) {
World::get_instance()->getCurrentMap()->addTargetItem(this);
}
if (_shape == SNAP_EGG_SHAPE) {
@@ -2044,7 +2045,7 @@ void Item::receiveHitU8(uint16 other, Direction dir, int damage, uint16 type) {
return;
// explosive?
- if (getShapeInfo()->is_explode()) {
+ if (getShapeInfo()->is_u8_explode()) {
explode(0, true); // warning: deletes this
return;
}
@@ -3572,8 +3573,9 @@ uint32 Item::I_getSurfaceWeight(const uint8 *args, unsigned int /*argsize*/) {
uint32 Item::I_isExplosive(const uint8 *args, unsigned int /*argsize*/) {
ARG_ITEM_FROM_PTR(item);
+ assert(GAME_IS_U8); // explode bit has different meaning in Cru.
if (!item) return 0;
- return item->getShapeInfo()->is_explode() ? 1 : 0;
+ return item->getShapeInfo()->is_u8_explode() ? 1 : 0;
}
uint32 Item::I_receiveHit(const uint8 *args, unsigned int /*argsize*/) {
@@ -3680,7 +3682,7 @@ uint32 Item::I_isCrusTypeNPC(const uint8 *args, unsigned int /*argsize*/) {
info = GameData::get_instance()->getMainShapes()->getShapeInfo(sh);
if (!info) return 0;
- if (info->_flags & ShapeInfo::SI_CRUS_NPC)
+ if (info->_flags & ShapeInfo::SI_CRU_NPC)
return 1;
else
return 0;
diff --git a/engines/ultima/ultima8/world/item_selection_process.cpp b/engines/ultima/ultima8/world/item_selection_process.cpp
index e066d7cebe..c875920d44 100644
--- a/engines/ultima/ultima8/world/item_selection_process.cpp
+++ b/engines/ultima/ultima8/world/item_selection_process.cpp
@@ -89,7 +89,7 @@ bool ItemSelectionProcess::selectNextItem() {
if (item->getShape() == 0x4ed || family == ShapeInfo::SF_CRUWEAPON ||
family == ShapeInfo::SF_CRUAMMO || family == ShapeInfo::SF_CRUBOMB ||
family == ShapeInfo::SF_CRUINVITEM ||
- (info && (info->_flags & ShapeInfo::SI_SELECTABLE))) {
+ (info && (info->_flags & ShapeInfo::SI_CRU_SELECTABLE))) {
int32 cx, cy, cz;
item->getCentre(cx, cy, cz);
@@ -137,7 +137,7 @@ void ItemSelectionProcess::useSelectedItem() {
Item *item = getItem(_selectedItem);
if (item) {
const ShapeInfo *info = item->getShapeInfo();
- if (info && (info->_flags & ShapeInfo::SI_SELECTABLE)) {
+ if (info && (info->_flags & ShapeInfo::SI_CRU_SELECTABLE)) {
item->callUsecodeEvent_use();
} else {
MainActor *actor = getMainActor();
More information about the Scummvm-git-logs
mailing list