[Scummvm-git-logs] scummvm master -> 8ee6e1ce854b006fa01009014e122ec6cc0ae5e8
mduggan
mgithub at guarana.org
Mon Nov 16 23:49:43 UTC 2020
This automated email contains information about 11 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
95273340d2 ULTIMA8: Fix some coverity issues
4c308804bf ULTIMA8: Pause surrender proc outside fast area
e0e7823100 ULTIMA8: Add intrinsic for playing crusader cutscene
8dfc5f64fc ULTIMA8: Pause music by default while playing AVIs
ebc1902f26 ULTIMA8: Avoid a potential null ptr deref
83b16362b8 ULTIMA8: Some improved animation flag support
a732d1de70 ULTIMA8: Fix small error in combat.dat decoding
584069c426 ULTIMA8: Small cleanups in heal/charge processes
bc24f8db3b ULTIMA8: Play correct selection failed noise in Regret
c9cba70a28 ULTIMA8: Add weapon info field for default ammo count
8ee6e1ce85 ULTIMA8: Remove manual trigger of mission1 egg
Commit: 95273340d2cd4a522bb4149e40704ceb5737bc7d
https://github.com/scummvm/scummvm/commit/95273340d2cd4a522bb4149e40704ceb5737bc7d
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:43:55+09:00
Commit Message:
ULTIMA8: Fix some coverity issues
Changed paths:
engines/ultima/ultima8/world/actors/attack_process.cpp
diff --git a/engines/ultima/ultima8/world/actors/attack_process.cpp b/engines/ultima/ultima8/world/actors/attack_process.cpp
index 322b009d9f..2a2fc464d3 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -75,12 +75,12 @@ static bool World_FinishedAvatarMoveTimeout() {
static inline int32 randomOf(int32 max) {
- return getRandom() % max;
+ return (max > 0 ? getRandom() % max : 0);
}
AttackProcess::AttackProcess() : Process(), _block(0), _target(1), _tactic(0), _tacticDat(nullptr),
_tacticDatReadStream(nullptr), _tacticDatStartOffset(0), _soundNo(-1), _playedStartSound(false),
-_npcInitialDir(dir_invalid), _field57(0), _field59(0), _field7f(false), _field96(false),
+_npcInitialDir(dir_invalid), _field57(0), _field59(0), _field7f(false), _field96(false), _field97(false),
_isActivity9orB(false), _isActivityAorB(false), _timer3set(false), _timer2set(false),
_doubleDelay(false), _wpnField8(1), _wpnBasedTimeout(0), _difficultyBasedTimeout(0), _timer2(0),
_timer3(0), _timer4(0), _timer5(0), _soundTimestamp(0), _fireTimestamp(0) {
@@ -91,7 +91,7 @@ _timer3(0), _timer4(0), _timer5(0), _soundTimestamp(0), _fireTimestamp(0) {
AttackProcess::AttackProcess(Actor *actor) : _block(0), _target(1), _tactic(0), _tacticDat(nullptr),
_tacticDatReadStream(nullptr), _tacticDatStartOffset(0), _soundNo(-1), _playedStartSound(false),
-_field57(0), _field59(0), _field7f(false), _field96(false), _isActivity9orB(false),
+_field57(0), _field59(0), _field7f(false), _field96(false), _field97(false), _isActivity9orB(false),
_isActivityAorB(false), _timer3set(false), _timer2set(false), _doubleDelay(false), _wpnField8(1),
_wpnBasedTimeout(0), _difficultyBasedTimeout(0), _timer2(0), _timer3(0), _timer4(0), _timer5(0),
_soundTimestamp(0), _fireTimestamp(0) {
@@ -465,7 +465,10 @@ void AttackProcess::run() {
{
uint16 offset = readNextWordRaw();
uint16 val = getAttackData(offset);
- setAttackData(opcode, val / readNextWordWithData());
+ uint16 divisor = readNextWordWithData();
+ if (!divisor)
+ divisor = 1; // shouldn't happen in real data, but just to be sure..
+ setAttackData(opcode, val / divisor);
return;
}
case 0xb4:
Commit: 4c308804bf8f6cb45110f6def93907d7db100add
https://github.com/scummvm/scummvm/commit/4c308804bf8f6cb45110f6def93907d7db100add
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:43:55+09:00
Commit Message:
ULTIMA8: Pause surrender proc outside fast area
Changed paths:
engines/ultima/ultima8/world/actors/surrender_process.cpp
diff --git a/engines/ultima/ultima8/world/actors/surrender_process.cpp b/engines/ultima/ultima8/world/actors/surrender_process.cpp
index d5a4291803..3d316e34e8 100644
--- a/engines/ultima/ultima8/world/actors/surrender_process.cpp
+++ b/engines/ultima/ultima8/world/actors/surrender_process.cpp
@@ -68,6 +68,10 @@ void SurrenderProcess::run() {
return;
}
+ // do nothing while we are not in the fast area
+ if (!a->hasFlags(Item::FLG_FASTAREA))
+ return;
+
int animating = Kernel::get_instance()->getNumProcesses(_itemNum, ActorAnimProcess::ACTOR_ANIM_PROC_TYPE);
if (animating) {
// already busy.
Commit: e0e78231000150af226afdaf3d61b189066f8862
https://github.com/scummvm/scummvm/commit/e0e78231000150af226afdaf3d61b189066f8862
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:43:55+09:00
Commit Message:
ULTIMA8: Add intrinsic for playing crusader cutscene
Changed paths:
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
engines/ultima/ultima8/gumps/movie_gump.cpp
engines/ultima/ultima8/gumps/movie_gump.h
engines/ultima/ultima8/usecode/remorse_intrinsics.h
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 71bab6143b..ca50c3e7c3 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -264,7 +264,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
// 00D0
"int16 Item::I_use(Item *)", // same coff as 080, 0D5
"void AudioProcess:I_stopAllSFX(void)", // based on disasm.
- "void I_playFlic0D2(int *item,char *flicname,word sizex,word sizey)", // play flic
+ "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_playSFX(2 bytes)", // same coff as 0AA. Based on disasm.
"int16 Item::I_use(Item *)", // same coff as 080, 0D0
diff --git a/engines/ultima/ultima8/gumps/movie_gump.cpp b/engines/ultima/ultima8/gumps/movie_gump.cpp
index 314552fb89..9457704fe9 100644
--- a/engines/ultima/ultima8/gumps/movie_gump.cpp
+++ b/engines/ultima/ultima8/gumps/movie_gump.cpp
@@ -191,5 +191,36 @@ uint32 MovieGump::I_playMovieOverlay(const uint8 *args,
return 0;
}
+uint32 MovieGump::I_playMovieCutscene(const uint8 *args, unsigned int /*argsize*/) {
+ ARG_ITEM_FROM_PTR(item);
+ ARG_STRING(name);
+ ARG_UINT16(x);
+ ARG_UINT16(y);
+
+ FileSystem *filesys = FileSystem::get_instance();
+ if (item) {
+ const Std::string filename = Std::string::format("@game/flics/%s.avi", name.c_str());
+ Common::SeekableReadStream *rs = filesys->ReadFile(filename);
+ if (!rs) {
+ // Try with a "0" in the name
+ const Std::string adjustedfn = Std::string::format("@game/flics/0%s.avi", name.c_str());
+ rs = filesys->ReadFile(adjustedfn);
+ if (!rs) {
+ warning("I_playMovieCutscene: movie %s not found", name.c_str());
+ return 0;
+ }
+ }
+
+ // TODO: Support playback with gap lines for the CRT effect
+ Gump *gump = new MovieGump(x * 3, y * 3, rs, false);
+ gump->InitGump(nullptr, true);
+ gump->setRelativePosition(CENTER);
+ }
+
+ return 0;
+
+}
+
+
} // End of namespace Ultima8
} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/gumps/movie_gump.h b/engines/ultima/ultima8/gumps/movie_gump.h
index c1fa2b39ec..43cf138f37 100644
--- a/engines/ultima/ultima8/gumps/movie_gump.h
+++ b/engines/ultima/ultima8/gumps/movie_gump.h
@@ -60,6 +60,7 @@ public:
void saveData(Common::WriteStream *ws) override;
INTRINSIC(I_playMovieOverlay);
+ INTRINSIC(I_playMovieCutscene);
protected:
MoviePlayer *_player;
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index 15138e0218..2a03054c04 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -258,7 +258,7 @@ Intrinsic RemorseIntrinsics[] = {
// 0x0D0
Item::I_use, // void Intrinsic0D0(4 bytes)
AudioProcess::I_stopAllSFX,
- 0, // void I_playFlic(int *item,char *flicname,word sizex,word sizey) // play flic
+ MovieGump::I_playMovieCutscene, // void I_playFlic(int *item,char *flicname,word sizex,word sizey) // play flic
0, // void Intrinsic0D3(void)
AudioProcess::I_playSFX, // void Intrinsic0D4(2 bytes)
Item::I_use, // void Intrinsic0D5(4 bytes)
Commit: 8dfc5f64fccbf0ee10db8c8ed756210f344c425c
https://github.com/scummvm/scummvm/commit/8dfc5f64fccbf0ee10db8c8ed756210f344c425c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:43:55+09:00
Commit Message:
ULTIMA8: Pause music by default while playing AVIs
Changed paths:
engines/ultima/ultima8/audio/music_process.h
engines/ultima/ultima8/audio/remorse_music_process.cpp
engines/ultima/ultima8/audio/remorse_music_process.h
engines/ultima/ultima8/audio/u8_music_process.cpp
engines/ultima/ultima8/audio/u8_music_process.h
engines/ultima/ultima8/graphics/avi_player.cpp
engines/ultima/ultima8/graphics/avi_player.h
engines/ultima/ultima8/gumps/movie_gump.cpp
diff --git a/engines/ultima/ultima8/audio/music_process.h b/engines/ultima/ultima8/audio/music_process.h
index b938fefe7e..76d0736028 100644
--- a/engines/ultima/ultima8/audio/music_process.h
+++ b/engines/ultima/ultima8/audio/music_process.h
@@ -72,6 +72,14 @@ public:
//! Bring back the track state from before it was put on hold
virtual void restoreTrackState() = 0;
+ //! Is a track currently playing?
+ virtual bool isPlaying() = 0;
+
+ //! Pause the currently playing track
+ virtual void pauseMusic() = 0;
+ //! Resume the current track after pausing
+ virtual void unpauseMusic() = 0;
+
INTRINSIC(I_playMusic);
INTRINSIC(I_stopMusic);
INTRINSIC(I_pauseMusic);
diff --git a/engines/ultima/ultima8/audio/remorse_music_process.cpp b/engines/ultima/ultima8/audio/remorse_music_process.cpp
index d082e0e660..aeb39a4dcc 100644
--- a/engines/ultima/ultima8/audio/remorse_music_process.cpp
+++ b/engines/ultima/ultima8/audio/remorse_music_process.cpp
@@ -155,6 +155,7 @@ void RemorseMusicProcess::playMusic_internal(int track) {
mixer->stopHandle(_soundHandle);
_soundHandle = Audio::SoundHandle();
+ _currentTrack = track;
if (track > 0) {
// TODO: It's a bit ugly having this here. Should be in GameData.
@@ -202,5 +203,26 @@ bool RemorseMusicProcess::loadData(Common::ReadStream *rs, uint32 version) {
return true;
}
+bool RemorseMusicProcess::isPlaying() {
+ Audio::Mixer *mixer = Ultima8Engine::get_instance()->_mixer;
+ return _currentTrack != 0 && mixer && mixer->isSoundHandleActive(_soundHandle);
+}
+
+void RemorseMusicProcess::pauseMusic() {
+ Audio::Mixer *mixer = Ultima8Engine::get_instance()->_mixer;
+ assert(mixer);
+ if (mixer->isSoundHandleActive(_soundHandle))
+ mixer->pauseHandle(_soundHandle, true);
+}
+
+void RemorseMusicProcess::unpauseMusic() {
+ Audio::Mixer *mixer = Ultima8Engine::get_instance()->_mixer;
+ assert(mixer);
+ if (mixer->isSoundHandleActive(_soundHandle))
+ mixer->pauseHandle(_soundHandle, false);
+}
+
+
+
} // End of namespace Ultima8
} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/audio/remorse_music_process.h b/engines/ultima/ultima8/audio/remorse_music_process.h
index 601a49bdd4..d8ea95cb8b 100644
--- a/engines/ultima/ultima8/audio/remorse_music_process.h
+++ b/engines/ultima/ultima8/audio/remorse_music_process.h
@@ -82,6 +82,14 @@ public:
//! Bring back the track state from before it was put on hold
void restoreTrackState() override;
+ //! Is a track currently playing?
+ bool isPlaying() override;
+
+ //! Pause the currently playing track
+ void pauseMusic() override;
+ //! Resume the current track after pausing
+ void unpauseMusic() override;
+
void run() override;
bool loadData(Common::ReadStream *rs, uint32 version);
diff --git a/engines/ultima/ultima8/audio/u8_music_process.cpp b/engines/ultima/ultima8/audio/u8_music_process.cpp
index 8b8b4e08c0..d76ad3be54 100644
--- a/engines/ultima/ultima8/audio/u8_music_process.cpp
+++ b/engines/ultima/ultima8/audio/u8_music_process.cpp
@@ -285,5 +285,20 @@ bool U8MusicProcess::loadData(Common::ReadStream *rs, uint32 version) {
return true;
}
+bool U8MusicProcess::isPlaying() {
+ return _currentTrack != 0;
+}
+
+void U8MusicProcess::pauseMusic() {
+ // probably no real use for this?
+ warning("TODO: U8MusicProcess::pauseMusic Implement me.");
+}
+
+void U8MusicProcess::unpauseMusic() {
+ // probably no real use for this?
+ warning("TODO: U8MusicProcess::unpauseMusic Implement me.");
+}
+
+
} // End of namespace Ultima8
} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/audio/u8_music_process.h b/engines/ultima/ultima8/audio/u8_music_process.h
index 5946f0e105..f4ddd0d8b7 100644
--- a/engines/ultima/ultima8/audio/u8_music_process.h
+++ b/engines/ultima/ultima8/audio/u8_music_process.h
@@ -113,6 +113,14 @@ public:
void setTrackState(const TrackState &state);
+ //! Is a track currently playing?
+ bool isPlaying() override;
+
+ //! Pause the currently playing track
+ void pauseMusic() override;
+ //! Resume the current track after pausing
+ void unpauseMusic() override;
+
void run() override;
bool loadData(Common::ReadStream *rs, uint32 version);
diff --git a/engines/ultima/ultima8/graphics/avi_player.cpp b/engines/ultima/ultima8/graphics/avi_player.cpp
index 5f55deb2a6..80596ec8e8 100644
--- a/engines/ultima/ultima8/graphics/avi_player.cpp
+++ b/engines/ultima/ultima8/graphics/avi_player.cpp
@@ -20,6 +20,7 @@
*
*/
+#include "ultima/ultima8/audio/music_process.h"
#include "ultima/ultima8/misc/pent_include.h"
#include "ultima/ultima8/graphics/avi_player.h"
#include "ultima/ultima8/graphics/render_surface.h"
@@ -35,7 +36,7 @@ namespace Ultima8 {
AVIPlayer::AVIPlayer(Common::SeekableReadStream *rs, int width, int height, const byte *overridePal)
: MoviePlayer(), _playing(false), _width(width), _height(height),
- _doubleSize(false), _overridePal(overridePal) {
+ _doubleSize(false), _pausedMusic(false), _overridePal(overridePal) {
_decoder = new Video::AVIDecoder();
_decoder->loadStream(rs);
uint32 vidWidth = _decoder->getWidth();
@@ -54,11 +55,23 @@ AVIPlayer::~AVIPlayer() {
}
void AVIPlayer::start() {
+ MusicProcess *music = MusicProcess::get_instance();
+ if (music && music->isPlaying()) {
+ music->pauseMusic();
+ _pausedMusic = true;
+ }
+
_playing = true;
_decoder->start();
}
void AVIPlayer::stop() {
+ MusicProcess *music = MusicProcess::get_instance();
+ if (music && _pausedMusic) {
+ music->unpauseMusic();
+ _pausedMusic = false;
+ }
+
_playing = false;
_decoder->stop();
}
diff --git a/engines/ultima/ultima8/graphics/avi_player.h b/engines/ultima/ultima8/graphics/avi_player.h
index 0c73d864e8..6a090b90ae 100644
--- a/engines/ultima/ultima8/graphics/avi_player.h
+++ b/engines/ultima/ultima8/graphics/avi_player.h
@@ -61,6 +61,7 @@ private:
uint32 _yoff;
bool _doubleSize;
const byte *_overridePal;
+ bool _pausedMusic;
};
diff --git a/engines/ultima/ultima8/gumps/movie_gump.cpp b/engines/ultima/ultima8/gumps/movie_gump.cpp
index 9457704fe9..01c1745dd1 100644
--- a/engines/ultima/ultima8/gumps/movie_gump.cpp
+++ b/engines/ultima/ultima8/gumps/movie_gump.cpp
@@ -77,6 +77,8 @@ void MovieGump::InitGump(Gump *newparent, bool take_focus) {
void MovieGump::Close(bool no_del) {
Mouse::get_instance()->popMouseCursor();
+ _player->stop();
+
ModalGump::Close(no_del);
}
Commit: ebc1902f26ae41d40edf8366ff2886262aa2b0bb
https://github.com/scummvm/scummvm/commit/ebc1902f26ae41d40edf8366ff2886262aa2b0bb
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:43:55+09:00
Commit Message:
ULTIMA8: Avoid a potential null ptr deref
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 10a8c9f8da..d254949519 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -69,7 +69,7 @@ uint32 AnimDat::getActionNumberForSequence(Animation::Sequence action, const Act
bool isavatar = (actor && actor->getShape() == 1);
if (isavatar && actor->getActiveWeapon()) {
const Item *wpn = getItem(actor->getActiveWeapon());
- const ShapeInfo *shapeinfo = wpn->getShapeInfo();
+ const ShapeInfo *shapeinfo = (wpn ? wpn->getShapeInfo() : nullptr);
const WeaponInfo *wpninfo = (shapeinfo ? shapeinfo->_weaponInfo : nullptr);
smallwpn = (wpninfo && wpninfo->_small);
altfire = (wpninfo && (wpninfo->_overlayShape == 0x36e || wpninfo->_overlayShape == 0x33b));
Commit: 83b16362b86b506b4c6e43991b5187c94c2dacf2
https://github.com/scummvm/scummvm/commit/83b16362b86b506b4c6e43991b5187c94c2dacf2
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:43:55+09:00
Commit Message:
ULTIMA8: Some improved animation flag support
Changed paths:
engines/ultima/ultima8/graphics/anim_dat.cpp
engines/ultima/ultima8/world/actors/actor.cpp
engines/ultima/ultima8/world/actors/actor.h
engines/ultima/ultima8/world/actors/actor_anim_process.cpp
engines/ultima/ultima8/world/actors/anim_action.h
engines/ultima/ultima8/world/actors/animation.h
diff --git a/engines/ultima/ultima8/graphics/anim_dat.cpp b/engines/ultima/ultima8/graphics/anim_dat.cpp
index d254949519..1fc728f0e7 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -181,10 +181,14 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
a->_actions[action]->_action = action;
rs->seek(actionoffset);
+ // byte 0: action size
uint32 actionsize = rs->readByte();
a->_actions[action]->_size = actionsize;
+ // byte 1: flags low byte
a->_actions[action]->_flags = rs->readByte();
+ // byte 2: frame repeat
a->_actions[action]->_frameRepeat = rs->readByte();
+ // byte 3: flags high byte
a->_actions[action]->_flags |= rs->readByte() << 8;
unsigned int dirCount = 8;
@@ -192,6 +196,14 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
(a->_actions[action]->_flags & AnimAction::AAF_CRUS_16DIRS)) {
dirCount = 16;
}
+
+ /*
+ if (a->_actions[action]->_flags & AnimAction::AAF_UNKFLAGS) {
+ warning("AnimFlags: shape %d action %d has unknown flags %04X", shape, action,
+ a->_actions[action]->_flags & AnimAction::AAF_UNKFLAGS);
+ }
+ */
+
a->_actions[action]->_dirCount = dirCount;
for (unsigned int dir = 0; dir < dirCount; dir++) {
@@ -207,13 +219,11 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
f._deltaDir = rs->readSByte();
f._flags = rs->readByte();
f._flags += (x & 0xF8) << 8;
- f._unk1 = 0;
- f._unk2 = 0;
} else if (GAME_IS_CRUSADER) {
// byte 0: low byte of frame
f._frame = rs->readByte();
- // byte 1: low nibble part of frame
- uint8 x = rs->readByte();
+ // byte 1: low nibble is high part of frame, high nibble is flags (used later)
+ const uint8 x = rs->readByte();
f._frame += (x & 0xF) << 8;
// byte 2: delta z
f._deltaZ = rs->readByte();
@@ -221,11 +231,20 @@ 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 TODO: Ensure "flipped" flag is mapped correctly
f._flags = rs->readByte();
f._flags += (x & 0xF0) << 8;
- // byte 6, 7: unknown
- f._unk2 = rs->readSint16LE();
+ // 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);
+ }*/
}
a->_actions[action]->_frames[dir].push_back(f);
}
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 1caa6cc757..1f36c6385d 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -908,6 +908,59 @@ void Actor::receiveHitCru(uint16 other, Direction dir, int damage, uint16 damage
}
}
+void Actor::tookHitCru() {
+ Animation::Sequence lastanim = getLastAnim();
+ if ((lastanim == Animation::unknownAnim30) || (lastanim == Animation::startRunWithLargeWeapon)) {
+ //uint16 controllednpc = World::get_instance()->getControlledNPCNum();
+ bool canseecontrolled = true; //this->canSee(controllednpc);
+ if (canseecontrolled) {
+ if (getRandom() % 4)
+ setActivity(5);
+ else
+ setActivity(10);
+ }
+ } else {
+ uint32 shape = getShape();
+ if (shape != 0x576) { // 0x576 = flaming guy
+ if (shape < 0x577) {
+ if (shape == 0x385 || shape == 0x4e6) {
+ explode(2, 0);
+ clearFlag(FLG_IN_NPC_LIST);
+ clearFlag(FLG_GUMP_OPEN);
+ }
+ return;
+ }
+ if (shape != 0x596) {
+ return;
+ }
+ }
+
+ bool violence = true; // Game::I_isViolenceEnabled
+ if (!violence)
+ return;
+
+ static const uint16 FEMALE_SCREAMS[] = {0xb, 0xa};
+ static const uint16 MALE_SCREAMS[] = {0x65, 0x66, 0x67};
+ int nsounds;
+ const uint16 *sounds;
+ if (hasExtFlags(EXT_FEMALE)) {
+ nsounds = ARRAYSIZE(FEMALE_SCREAMS);
+ sounds = FEMALE_SCREAMS;
+ } else {
+ nsounds = ARRAYSIZE(MALE_SCREAMS);
+ sounds = MALE_SCREAMS;
+ }
+ AudioProcess *audio = AudioProcess::get_instance();
+ if (!audio)
+ return;
+ for (int i = 0; i < nsounds; i++) {
+ if (audio->isSFXPlayingForObject(sounds[i], _objId))
+ return;
+ }
+ audio->playSFX(sounds[getRandom() % nsounds], 0x80, _objId, 1);
+ }
+}
+
void Actor::receiveHitU8(uint16 other, Direction dir, int damage, uint16 damage_type) {
if (isDead())
return; // already dead, so don't bother
diff --git a/engines/ultima/ultima8/world/actors/actor.h b/engines/ultima/ultima8/world/actors/actor.h
index 2d69f44847..eb9e1f56ef 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -280,6 +280,9 @@ public:
bool activeWeaponIsSmall() const;
+ // A cru-specific behavior - mostly make "ugh" noises, or explode for some robots.
+ void tookHitCru();
+
ENABLE_RUNTIME_CLASSTYPE()
INTRINSIC(I_isNPC);
diff --git a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
index 9e4a0ad59a..49258ea8c2 100644
--- a/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
+++ b/engines/ultima/ultima8/world/actors/actor_anim_process.cpp
@@ -260,11 +260,15 @@ void ActorAnimProcess::run() {
if (audioproc) audioproc->playSFX(curframe->_sfx, 0x60, _itemNum, 0);
}
- if (curframe && (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();
+ if (curframe) {
+ 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) {
+ a->tookHitCru();
+ }
}
diff --git a/engines/ultima/ultima8/world/actors/anim_action.h b/engines/ultima/ultima8/world/actors/anim_action.h
index 676a1a30c4..967e0ea8bd 100644
--- a/engines/ultima/ultima8/world/actors/anim_action.h
+++ b/engines/ultima/ultima8/world/actors/anim_action.h
@@ -36,16 +36,19 @@ struct AnimFrame {
int _deltaZ;
int _deltaDir;
int _sfx;
- uint16 _unk1;
- uint16 _unk2;
uint32 _flags;
enum AnimFrameFlags {
- AFF_UNK1 = 0x0001,
- AFF_ONGROUND = 0x0002,
- AFF_FLIPPED = 0x0020,
- AFF_SPECIAL = 0x0800,
- AFF_USECODE = 0x4000
+ 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_UNKNOWN = 0xF0E0B01C,
+ //AFF_FIRE = 0x0F1F00C0
};
inline bool is_flipped() const {
@@ -117,7 +120,8 @@ public:
AAF_LOOPING2 = 0x0010, // CHECKME: guessing at this flag
AAF_HANGING = 0x0080,
AAF_CRUS_16DIRS = 0x4000, // Crusader
- AAF_DESTROYACTOR = 0x8000 // destroy actor after animation finishes
+ AAF_DESTROYACTOR = 0x8000, // destroy actor after animation finishes
+ AAF_UNKFLAGS = 0x3F60
};
private:
diff --git a/engines/ultima/ultima8/world/actors/animation.h b/engines/ultima/ultima8/world/actors/animation.h
index 628b43d02d..9b9ba3feb7 100644
--- a/engines/ultima/ultima8/world/actors/animation.h
+++ b/engines/ultima/ultima8/world/actors/animation.h
@@ -102,6 +102,7 @@ enum Sequence {
kneelAndFire = 26,
slideLeft = 28,
slideRight = 29,
+ unknownAnim30 = 30,
startRunWithLargeWeapon = 31,
teleportIn = 32,
teleportOut = 33,
Commit: a732d1de700f18b73871b45ace8d15ba7c4144b2
https://github.com/scummvm/scummvm/commit/a732d1de700f18b73871b45ace8d15ba7c4144b2
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:47:57+09:00
Commit Message:
ULTIMA8: Fix small error in combat.dat decoding
Changed paths:
engines/ultima/ultima8/world/actors/attack_process.cpp
diff --git a/engines/ultima/ultima8/world/actors/attack_process.cpp b/engines/ultima/ultima8/world/actors/attack_process.cpp
index 2a2fc464d3..83871801af 100644
--- a/engines/ultima/ultima8/world/actors/attack_process.cpp
+++ b/engines/ultima/ultima8/world/actors/attack_process.cpp
@@ -468,7 +468,7 @@ void AttackProcess::run() {
uint16 divisor = readNextWordWithData();
if (!divisor)
divisor = 1; // shouldn't happen in real data, but just to be sure..
- setAttackData(opcode, val / divisor);
+ setAttackData(offset, val / divisor);
return;
}
case 0xb4:
Commit: 584069c42642b8843753866c4bf2b6750b171a99
https://github.com/scummvm/scummvm/commit/584069c42642b8843753866c4bf2b6750b171a99
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:48:05+09:00
Commit Message:
ULTIMA8: Small cleanups in heal/charge processes
Changed paths:
engines/ultima/ultima8/world/actors/battery_charger_process.cpp
engines/ultima/ultima8/world/actors/cru_healer_process.cpp
diff --git a/engines/ultima/ultima8/world/actors/battery_charger_process.cpp b/engines/ultima/ultima8/world/actors/battery_charger_process.cpp
index 45da4260dc..be096080b3 100644
--- a/engines/ultima/ultima8/world/actors/battery_charger_process.cpp
+++ b/engines/ultima/ultima8/world/actors/battery_charger_process.cpp
@@ -25,6 +25,7 @@
#include "ultima/ultima8/world/actors/main_actor.h"
#include "ultima/ultima8/kernel/kernel.h"
#include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/world/world.h"
#include "ultima/ultima8/audio/audio_process.h"
#include "common/util.h"
@@ -35,9 +36,12 @@ namespace Ultima8 {
// p_dynamic_cast stuff
DEFINE_RUNTIME_CLASSTYPE_CODE(BatteryChargerProcess)
+// These SFX IDs are the same in both No Regret and No Remorse.
+static const uint16 CHARGE_START_SFX = 0xa4;
+static const uint16 CHARGE_GOING_SFX = 0x10b;
+
BatteryChargerProcess::BatteryChargerProcess() : Process() {
- // TODO: This should be the "current" avatar (if controlling a robot etc)
- MainActor *avatar = getMainActor();
+ MainActor *avatar = dynamic_cast<MainActor *>(getActor(World::get_instance()->getControlledNPCNum()));
if (!avatar) {
_itemNum = 0;
_targetMaxEnergy = 0;
@@ -46,27 +50,26 @@ BatteryChargerProcess::BatteryChargerProcess() : Process() {
_targetMaxEnergy = avatar->getMaxEnergy();
AudioProcess *audio = AudioProcess::get_instance();
if (audio) {
- audio->playSFX(0xa4, 0x80, _itemNum, 1, false);
+ audio->playSFX(CHARGE_START_SFX, 0x80, _itemNum, 1, false);
}
}
_type = 0x254; // CONSTANT!
}
void BatteryChargerProcess::run() {
- // TODO: This should be the "current" avatar (if controlling a robot etc)
- MainActor *avatar = getMainActor();
+ MainActor *avatar = dynamic_cast<MainActor *>(getActor(World::get_instance()->getControlledNPCNum()));
AudioProcess *audio = AudioProcess::get_instance();
if (!avatar || avatar->isDead() || avatar->getMana() >= _targetMaxEnergy) {
- // dead or finished healing
+ // dead or finished healing or switched to robot
terminate();
if (audio)
- audio->stopSFX(0xa4, _itemNum);
+ audio->stopSFX(CHARGE_START_SFX, _itemNum);
return;
}
- if (!audio->isSFXPlayingForObject(0x10b, _itemNum))
- audio->playSFX(0x10b, 0x80, _itemNum, 1);
+ if (!audio->isSFXPlayingForObject(CHARGE_GOING_SFX, _itemNum))
+ audio->playSFX(CHARGE_GOING_SFX, 0x80, _itemNum, 1);
uint16 newEnergy = avatar->getMana() + 25;
if (newEnergy > _targetMaxEnergy)
diff --git a/engines/ultima/ultima8/world/actors/cru_healer_process.cpp b/engines/ultima/ultima8/world/actors/cru_healer_process.cpp
index fdb9ddaca7..6c451b1726 100644
--- a/engines/ultima/ultima8/world/actors/cru_healer_process.cpp
+++ b/engines/ultima/ultima8/world/actors/cru_healer_process.cpp
@@ -25,6 +25,7 @@
#include "ultima/ultima8/world/actors/main_actor.h"
#include "ultima/ultima8/kernel/kernel.h"
#include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/world/world.h"
#include "ultima/ultima8/ultima8.h"
#include "ultima/ultima8/audio/audio_process.h"
@@ -33,12 +34,16 @@
namespace Ultima {
namespace Ultima8 {
+
+// These SFX IDs are the same in both No Regret and No Remorse.
+static const uint16 HEAL_START_SFX = 0xdb;
+static const uint16 HEAL_GOING_SFX = 0xba;
+
// p_dynamic_cast stuff
DEFINE_RUNTIME_CLASSTYPE_CODE(CruHealerProcess)
CruHealerProcess::CruHealerProcess() : Process() {
- // TODO: This should be the "current" avatar (if controlling a robot etc)
- MainActor *avatar = getMainActor();
+ MainActor *avatar = dynamic_cast<MainActor *>(getActor(World::get_instance()->getControlledNPCNum()));
if (!avatar) {
_itemNum = 0;
_targetMaxHP = 0;
@@ -48,7 +53,7 @@ CruHealerProcess::CruHealerProcess() : Process() {
AudioProcess *audio = AudioProcess::get_instance();
if (audio) {
// Sound num is the same in both No Remorse and No Regret
- audio->playSFX(0xdb, 0x80, _itemNum, 1, false);
+ audio->playSFX(HEAL_START_SFX, 0x80, _itemNum, 1, false);
}
}
Ultima8Engine::get_instance()->setAvatarInStasis(true);
@@ -56,8 +61,7 @@ CruHealerProcess::CruHealerProcess() : Process() {
}
void CruHealerProcess::run() {
- // TODO: This should be the "current" avatar (if controlling a robot etc)
- MainActor *avatar = getMainActor();
+ MainActor *avatar = dynamic_cast<MainActor *>(getActor(World::get_instance()->getControlledNPCNum()));
AudioProcess *audio = AudioProcess::get_instance();
if (!avatar || avatar->isDead() || avatar->getHP() >= _targetMaxHP) {
@@ -66,13 +70,13 @@ void CruHealerProcess::run() {
}
// dead or finished healing
if (audio)
- audio->stopSFX(0xdb, _itemNum);
+ audio->stopSFX(HEAL_START_SFX, _itemNum);
terminate();
return;
}
- if (audio && !audio->isSFXPlayingForObject(0xba, _itemNum))
- audio->playSFX(0xba, 0x80, _itemNum, 1);
+ if (audio && !audio->isSFXPlayingForObject(HEAL_GOING_SFX, _itemNum))
+ audio->playSFX(HEAL_GOING_SFX, 0x80, _itemNum, 1);
uint16 newHP = avatar->getHP() + 1;
if (newHP > _targetMaxHP)
Commit: bc24f8db3b0cceb595a9793020248883ca75fd8f
https://github.com/scummvm/scummvm/commit/bc24f8db3b0cceb595a9793020248883ca75fd8f
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:48:05+09:00
Commit Message:
ULTIMA8: Play correct selection failed noise in Regret
Changed paths:
engines/ultima/ultima8/world/item_selection_process.cpp
diff --git a/engines/ultima/ultima8/world/item_selection_process.cpp b/engines/ultima/ultima8/world/item_selection_process.cpp
index 2856d80c8d..e066d7cebe 100644
--- a/engines/ultima/ultima8/world/item_selection_process.cpp
+++ b/engines/ultima/ultima8/world/item_selection_process.cpp
@@ -24,6 +24,7 @@
#include "ultima/ultima8/games/game_data.h"
#include "ultima/ultima8/audio/audio_process.h"
+#include "ultima/ultima8/kernel/core_app.h"
#include "ultima/ultima8/kernel/kernel.h"
#include "ultima/ultima8/world/actors/main_actor.h"
#include "ultima/ultima8/world/item_selection_process.h"
@@ -42,7 +43,8 @@ namespace Ultima8 {
ItemSelectionProcess *ItemSelectionProcess::_instance = nullptr;
static const uint32 SELECTOR_SHAPE = 0x5a3;
-static const uint16 SELECTION_FAILED_SOUND = 0xb0;
+static const uint16 SELECT_FAILED_SFX_REMORSE = 0xb0;
+static const uint16 SELECT_FAILED_SFX_REGRET = 0x1a7;
// p_dynamic_cast stuff
DEFINE_RUNTIME_CLASSTYPE_CODE(ItemSelectionProcess)
@@ -102,7 +104,9 @@ bool ItemSelectionProcess::selectNextItem() {
AudioProcess *audio = AudioProcess::get_instance();
assert(audio);
// Play the "beeboop" selection failed sound.
- audio->playSFX(SELECTION_FAILED_SOUND, 0x10, 0, 1);
+ uint16 sfxno = GAME_IS_REGRET ? SELECT_FAILED_SFX_REGRET : SELECT_FAILED_SFX_REMORSE;
+ if (!audio->isSFXPlaying(sfxno))
+ audio->playSFX(sfxno, 0x10, 0, 1);
clearSelection();
return false;
}
Commit: c9cba70a28a96a4e69a02bc64c6e7ce70ead1ac1
https://github.com/scummvm/scummvm/commit/c9cba70a28a96a4e69a02bc64c6e7ce70ead1ac1
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:48:05+09:00
Commit Message:
ULTIMA8: Add weapon info field for default ammo count
Changed paths:
engines/ultima/ultima8/graphics/type_flags.cpp
engines/ultima/ultima8/world/item_factory.cpp
engines/ultima/ultima8/world/weapon_info.h
diff --git a/engines/ultima/ultima8/graphics/type_flags.cpp b/engines/ultima/ultima8/graphics/type_flags.cpp
index 6916a647a0..039f48cb39 100644
--- a/engines/ultima/ultima8/graphics/type_flags.cpp
+++ b/engines/ultima/ultima8/graphics/type_flags.cpp
@@ -267,6 +267,9 @@ void TypeFlags::loadWeaponInfo() {
else
wi->_small = 0;
+ // TODO: get from real data.
+ wi->_defaultAmmo = 37;
+
// TODO: this should be 1, 2, or 3 depending on weapon.
// It's used in the AttackProcess
wi->_field8 = 1;
diff --git a/engines/ultima/ultima8/world/item_factory.cpp b/engines/ultima/ultima8/world/item_factory.cpp
index 7a11f7897d..c2fc0c7319 100644
--- a/engines/ultima/ultima8/world/item_factory.cpp
+++ b/engines/ultima/ultima8/world/item_factory.cpp
@@ -107,6 +107,14 @@ Item *ItemFactory::createItem(uint32 shape, uint32 frame, uint16 quality,
if (info->_damageInfo && info->_damageInfo->takesDamage()) {
item->setDamagePoints(info->_damageInfo->damagePoints());
}
+ if (info->_family == ShapeInfo::SF_CRUWEAPON && info->_weaponInfo &&
+ info->_weaponInfo->_defaultAmmo) {
+ item->setQuality(info->_weaponInfo->_defaultAmmo);
+ }
+ if (info->_family == ShapeInfo::SF_CRUAMMO ||
+ info->_family == ShapeInfo::SF_CRUBOMB) {
+ item->setQuality(1);
+ }
}
}
diff --git a/engines/ultima/ultima8/world/weapon_info.h b/engines/ultima/ultima8/world/weapon_info.h
index a69220358d..985e23ab8a 100644
--- a/engines/ultima/ultima8/world/weapon_info.h
+++ b/engines/ultima/ultima8/world/weapon_info.h
@@ -48,6 +48,7 @@ struct WeaponInfo {
uint16 _displayGumpShape; //! The gump shape to use for inventory display (3,4,5)
uint16 _displayGumpFrame; //!< The frame to use in the inventory gump
uint8 _small; //! A flag whether or not the weapon is "small" (changes the animations used)
+ uint16 _defaultAmmo; //! Count of ammo the weapon starts with
uint8 _field8; //! Not totally sure, used like "cycle time" in Attack Process
enum DmgType {
Commit: 8ee6e1ce854b006fa01009014e122ec6cc0ae5e8
https://github.com/scummvm/scummvm/commit/8ee6e1ce854b006fa01009014e122ec6cc0ae5e8
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-11-17T08:48:34+09:00
Commit Message:
ULTIMA8: Remove manual trigger of mission1 egg
This works automatically now that the unkegg offsets are fixed.
Changed paths:
engines/ultima/ultima8/games/start_crusader_process.cpp
diff --git a/engines/ultima/ultima8/games/start_crusader_process.cpp b/engines/ultima/ultima8/games/start_crusader_process.cpp
index 4d3c51c42d..02433e2fae 100644
--- a/engines/ultima/ultima8/games/start_crusader_process.cpp
+++ b/engines/ultima/ultima8/games/start_crusader_process.cpp
@@ -102,13 +102,6 @@ void StartCrusaderProcess::run() {
Item *smiley = ItemFactory::createItem(0x598, 0, 0, 0, 0, mapnum, 0, true);
smiley->moveToContainer(avatar);
- // TODO: How is this created in the game??
- Egg *miss1egg = new Egg();
- miss1egg->setShape(2317);
- miss1egg->setMapNum(mapnum);
- miss1egg->assignObjId();
- miss1egg->callUsecodeEvent_hatch();
-
avatar->setDir(dir_east);
} else if (GAME_IS_REGRET) {
// TODO: Give the appropriate startup objects to the avatar
More information about the Scummvm-git-logs
mailing list