[Scummvm-git-logs] scummvm master -> 535e55a03e2c98816f5036fb5130ad63490eed3e
mduggan
mgithub at guarana.org
Fri Jun 19 08:15:56 UTC 2020
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
535e55a03e ULTIMA8: More crusader support
Commit: 535e55a03e2c98816f5036fb5130ad63490eed3e
https://github.com/scummvm/scummvm/commit/535e55a03e2c98816f5036fb5130ad63490eed3e
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-06-19T17:14:23+09:00
Commit Message:
ULTIMA8: More crusader support
Changed paths:
engines/ultima/ultima8/audio/audio_process.cpp
engines/ultima/ultima8/audio/remorse_music_process.cpp
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
engines/ultima/ultima8/ultima8.cpp
engines/ultima/ultima8/ultima8.h
engines/ultima/ultima8/usecode/remorse_intrinsics.h
engines/ultima/ultima8/world/actors/main_actor.cpp
engines/ultima/ultima8/world/actors/main_actor.h
engines/ultima/ultima8/world/camera_process.cpp
engines/ultima/ultima8/world/camera_process.h
engines/ultima/ultima8/world/item.cpp
engines/ultima/ultima8/world/item.h
diff --git a/engines/ultima/ultima8/audio/audio_process.cpp b/engines/ultima/ultima8/audio/audio_process.cpp
index c1b1e44e0f..e7abecb78e 100644
--- a/engines/ultima/ultima8/audio/audio_process.cpp
+++ b/engines/ultima/ultima8/audio/audio_process.cpp
@@ -554,7 +554,7 @@ uint32 AudioProcess::I_playAmbientSFXCru(const uint8 *args, unsigned int argsize
} else {
AudioProcess *ap = AudioProcess::get_instance();
if (ap)
- ap->playSFX(sfxNum, 0x10, item->getObjId(), -1, true);
+ ap->playSFX(sfxNum, 0x10, 1, -1, true);
else
warning("I_playAmbientSFXCru Error: No AudioProcess");
}
diff --git a/engines/ultima/ultima8/audio/remorse_music_process.cpp b/engines/ultima/ultima8/audio/remorse_music_process.cpp
index 9383a35729..0b50865cbb 100644
--- a/engines/ultima/ultima8/audio/remorse_music_process.cpp
+++ b/engines/ultima/ultima8/audio/remorse_music_process.cpp
@@ -34,6 +34,8 @@ namespace Ultima {
namespace Ultima8 {
static const int MAX_TRACK = 20;
+
+// TODO: Ensure this is the right order for the uses of this from Usecode.
static const char *TRACK_FILE_NAMES[] = {
nullptr,
"cred",
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 973a554734..88380e1863 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -67,18 +67,18 @@ private:
// By convention, last pushed argument goes first on the list.
const char* const ConvertUsecodeCrusader::_intrinsics[] = {
// 0000
- "byte Ultima8Engine::I_getAlertActive(void)",
+ "byte World::I_getAlertActive(void)",
"int16 Item::I_getFrame(Item *)",
"void Item::I_setFrame(Item *, frame)",
"int16 Item::I_getMapArray(Item *)", // See TRIGGER::ordinal21 - stored in a variable 'mapNum'
"int16 Item::I_getStatus(Item *)",
"void Item::I_orStatus(Item *, uint16 flags)",
- "int16 Intrinsic006(6 bytes)", // same coff as 0B5
+ "int16 Item::I_equip(6 bytes)", // same coff as 0B5 - TODO: confirm this
"byte Item::I_isOnScreen(Item *)", // called for gattling guns and camera
"byte Actor::I_isNPC(Item *)", // proably - actually checks is itemno < 256?
"byte Item::I_getZ(Item *)",
"void Item::I_destroy(Item *)", // probably? often called after creating a replacement object and setting it to the same position (eg, LUGGAGE::gotHit)
- "int16 Actor::I_GetNPCDataField0x63_00B(Actor *)", // could be getNPCNum? Called from ANDROID::calledFromAnim, goes to NPCDEATH
+ "int16 Actor::I_GetNPCDataField0x63_00B(Actor *)", // Maybe get HP? Called from ANDROID::calledFromAnim, goes to NPCDEATH
"void I_NPCsetSomething_00C(int)",
"byte Item::I_getDirToItem(Item *, itemno)", // based on disasm
"int16 Actor::I_NPCSomething00E(Actor *, int, int)",
@@ -86,7 +86,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
// 0010
"int16 Item::I_getQLo(Item *)", // same as 02B based on same coff as 02B, 066, 084, 0A1, 0AE, 0D9, 0EA
"int16 Actor::I_getMap(4 bytes)", // based on disasm.
- "void Intrinsic012(2 bytes)",
+ "void MusicProcess:I_playMusic(int trackno)",
"int16 Item::I_getX(Item *)",
"int16 Item::I_getY(Item *)",
"void AudioProcess::I_playSFXCru(Item *, uint16 sfxnum)",
@@ -95,10 +95,10 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 UCMachine::I_rndRange(uint16 x, uint16 y)", // // probably.. always called with 2 constants, then result often compared to some number between
"byte Item::I_legalCreateAtCoords(Item *, int16 shapeno, int16 frame, int16 x, int16 y, int16 z)", // probably, see usage in DOOR2::ordinal37
"void Item::I_andStatus(Item *, uint16 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. Always associated with a bitwise-not or bitmask
- "int16 Intrinsic01B(void)",
+ "int16 I_getTargetNPCNumMaybe(void)",
"byte Actor::I_getDir(4 bytes)", // based on disasm. same coff as 112, 121
"int16 Actor::I_getLastAnimSet(4 bytes)", // based on disasm. part of same coff set 01D, 05A, 0B9, 0D7, 0E4, 124
- "int16 Intrinsic01E(16 bytes)",
+ "int16 Actor::I_maybeFire(Actor *, x, y, z, byte, int, byte)", // TODO: investigate more
"byte Item::I_create(Item *, uint16 shapenum, uint16 framenum)", // probably - used in MISS1EGG referencing keycards and NPCDEATH in creating blood spills
// 0020
"void Item::I_popToCoords(Item *, uint16 x, uint16 y, uint16 z)", // set coords, used after creating blood spills in NPCDEATH
@@ -116,16 +116,16 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"byte Item::I_inFastArea(Item *)",
"void Item::I_setQHi(Item *, uint16 qhi)", // probably setQHi, see usage in FREE::ordinal2E where object position is copied
"byte I_legalMoveToPoint(Item *, Point *, int16 force)", // based on disasm
- "byte Intrinsic02F(10 bytes)",
+ "byte Intrinsic02F(int, int, shapeno, Point *)", // no idea what this does..
// 0030
"void Item::I_pop(Item *)", // same code as U8
"void Item::I_andStatus(Item *, uint16 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
"void Item::I_receiveHit(Item *, other, dir, damage, damagetype)", // based on disasm
"byte Actor::I_isBusy(4 bytes)", // same code as U8
"int16 Item::I_getDirFromTo16(x1, y1, x2, y2)",
- "byte Actor::I_getSomeFlagMaybeCrouch(Item *)",
+ "byte Actor::I_getSomeFlagProbablyCrouch(Item *)",
"int16 Actor::I_doAnim(12 bytes)", // v. similar code to U8
- "byte Intrinsic037(4 bytes)", // same coff as 0B8
+ "byte I_probablyPickUpItem_037(4 bytes)", // same coff as 0B8
"void AudioProcess::I_stopSFXCru(Item *, int16 sndno)",
"byte Actor::I_isDead(Item *)", // same coff as 122, 12E
"byte AudioProcess::I_isSFXPlayingForObject(Item *, int16 unk)",
@@ -137,7 +137,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
// 0040
"void CameraProcess::I_moveTo(x, y, z)",
"void CameraProcess::I_setCenterOn(objid)",
- "byte Intrinsic042(6 bytes)",
+ "byte Intrinsic042(Item *, otheritem)", // Something about whether item1 can see item2?
"void AudioProcess::I_playSFXCru(Item *, soundno)", // TODO: Work out how this is different from Int015 - to a first approximation they are quite similar.
"byte Item::I_IsOn(Item *, uint16 itemno)", // part of same coff set 044, 046, 048, 04A, 04C, 04E, 0A5, 0BC, 0C5, 0DC, 0F1, 0FA, 12C
"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
@@ -153,12 +153,12 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"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
// 0050
"int16 I_GetNPCDataField0x2_050(Actor *)",
- "void I_NPCSomething_051(Actor *)",
- "void Intrinsic052(6 bytes)",
- "void I_SetNPCDataField0x8_053(Actor *, int)",
- "void I_SetNPCDataField0xA_054(Actor *, int)",
+ "void I_NPCSomething_051(Actor *)", // TODO: check usecode to understand this.
+ "void I_SetNPCDataField0x6_052(Actor *, int)", // TODO: check usecode to understand this.
+ "void I_SetNPCDataField0x8_053(Actor *, int)", // TODO: check usecode to understand this.
+ "void I_SetNPCDataField0xA_054(Actor *, int)", // TODO: check usecode to understand this.
"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
- "void Intrinsic056(2 bytes)",
+ "void Intrinsic056(int itemno)", // Maybe set new target? TODO: check usecode to understand this.
"int16 Item::I_getSOMETHING_57(Item *)",
"byte Item::Item::I_isCentreOn(Item *, uint16 other)",
"void Item::I_setFrame(Item *, frame)", // based on same coff as 002
@@ -171,7 +171,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
// 0060
"void Actor::I_setDead(4 bytes)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
"void Actor::I_create(8 bytes)",
- "void Intrinsic062(void)",
+ "void CameraProcess::I_somethingAboutCameraUpdate(void)",
"void Actor::I_teleport(12 bytes)", // based on disasm same as U8
"void Item::I_getFootpad(Item *, uint *, uint *, uint *)", // based on disasm. same coff as 12D
"byte Item::I_isInNPC(Item *)", // based on disasm - following parent containers, is one of them an NPC
@@ -194,11 +194,11 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"void Ultima8Engine::I_clrAvatarInStasis(void)",
"void AudioProcess::I_stopSFX(Item *)",
"int16 PaletteFaderProcess::I_fadeToBlack(void)", // fade to black, no args (40 frames)
- "void Intrinsic078(void)",
+ "void MainActor::I_clrKeycards(void)",
"int16 MainActor::I_teleportToEgg(int, int, int)",
"int16 PaletteFaderProcess::I_fadeFromBlack(void)", // from black, no arg (40 frames)
"void Actor::I_clrImmortal(Actor *)", // same coff as 130
- "int16 I_GetNPCDataField0_07C(Actor *)",
+ "int16 Actir::I_getHp(Actor *)", // TODO: double-check whether field 0 of NPC data is HP or *max* HP.
"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
"int16 Item::I_getQuality(Item *)", // based on disassembly
"void Item::I_setQuality(Item *, int)", // based on disassembly. same coff as 0BA, 125
@@ -209,28 +209,28 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"void Actor::I_setMana(Actor *, int)",
"int16 Item::I_getQLo(Item *)", // same as 02B based on same coff set 010, 02B, 066, 084, 0A1, 0AE, 0D9, 0EA
"void Actor::I_setImmortal(Actor *)",
- "int16 Intrinsic086(void)",
- "int16 Intrinsic087(void)",
+ "int16 CameraProcess::I_getCameraX(void)",
+ "int16 CameraProcess::I_getCameraY(void)",
"void Item::I_setMapArray(Item *, uint16 maparray)", // based on decompile - sets same value as read by getmaparray .. see VALUEBOX:ordinal20
"int16 Item::I_getNpcNum(Item *)", // part of same coff set 067, 06D, 089, 08E, 0AD, 0F8, 100, 102, 105, 107, 109, 10B, 10D, 10F, 111, 115, 11C, 123, 129
- "void Intrinsic08A(12 bytes)",
+ "void Intrinsic08A(12 bytes)", // TODO: No idea here.. something about hurling? look at the usecode.
"int16 Item::I_enterFastArea(Item *)", // based on disasm, v similar to U8
"void Item::I_doSomethingAndSetStatusFlag0x8000(Item *)", // same coff as 119, 12A
"int16 Item::I_hurl(Item *,8 bytes)", // part of same coff set 028, 08D, 0BD, 0C0, 0C2, 0C8, 0F7, 0F9, 118, 11D
"int16 Item::I_getNPCNum(Item *)", // part of same coff set 067, 06D, 089, 08E, 0AD, 0F8, 100, 102, 105, 107, 109, 10B, 10D, 10F, 111, 115, 11C, 123, 129
"void PaletteFaderProcess::I_setPalToAllBlack(void)",
// 0090
- "void Intrinsic090(void)",
+ "void MusicProcess::I_musicStop(void)",
"void I_setSomeMovieGlobal(void)", // sets some global (cleared by 93)
"void I_playFlic092(char *)", // same coff as 0A9
- "void I_clearSomeMovieGlobal(void)", // clears som global (set by 91)
- "void Intrinsic094(void)",
- "byte Intrinsic095(void)", // get global - something about keyboard (by disasm)
+ "void I_clearSomeMovieGlobal(void)", // clears some global (set by 91)
+ "void Game::I_playCredits(void)",
+ "byte Kernel::I_getCurrentKeyDown(void)", // get global - something about keyboard (by disasm)
"int16 MainActor::I_teleportToEgg(int, int)", // a bit different to the U8 one - uses main actor map by default.
- "void Intrinsic097(void)",
- "void I_resetVargasHealthTo500(void)",
+ "void PaletteFaderProcess:I_setScreenGreyscale(void)", // TODO: Implement this - converts all colors to their Y values on each channel.
+ "void I_resetVargasHealthTo500(void)", // TODO: look how this is used in disasm and usecode .. seems weird.
"void Item::I_andStatus(Item *, uint16 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
- "void PaletteFaderProcess::I_stopFadesAndResetToGamePal(void)",
+ "void PaletteFaderProcess::I_stopFadesAndResetToGamePal(void)", // TODO: Implement this.
"int16 PaletteFaderProcess::I_fadeFromBlack(nsteps)",
"int16 PaletteFaderProcess::I_fadeFromBlackWithParam(nsteps, unk)", // TODO: what's the param?
"int16 PaletteFaderProcess::I_fadeToBlack(nsteps)",
@@ -262,10 +262,10 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 Item::I_equip(6 bytes)",
"void Ultima8Engine::I_clrAlertActive(void)",
"int16 I_GetNPCGlobal0x7e24_0B7(void)",
- "byte Intrinsic0B8(4 bytes)", // same coff as 037
+ "byte I_probablyPickUpItem_0B8(4 bytes)", // same coff as 037
"int16 Actor::I_getLastAnimSet(4 bytes)", // part of same coff set 01D, 05A, 0B9, 0D7, 0E4, 124
"void Item::I_setQuality(Item *, int)", // same coff as 07F, 125
- "byte Intrinsic0BB(8 bytes)",
+ "byte Intrinsic0BB(8 bytes)", // TODO: check usecode.. code is weird, something with an imaginary chequered wall shape? (0x31A)
"byte Item::I_isOn(Item *, itemno)", // part of same coff set 044, 046, 048, 04A, 04C, 04E, 0A5, 0BC, 0C5, 0DC, 0F1, 0FA, 12C
"int16 Item::I_hurl(Item *,8 bytes)", // part of same coff set 028, 08D, 0BD, 0C0, 0C2, 0C8, 0F7, 0F9, 118, 11D
"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
@@ -275,30 +275,30 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"void Item::I_andStatus(Item *, uint16 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_hurl(Item *,8 bytes)", // part of same coff set 028, 08D, 0BD, 0C0, 0C2, 0C8, 0F7, 0F9, 118, 11D
"void Item::I_andStatus(Item *, uint16 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 Intrinsic0C4(2 bytes)",
+ "int16 I_showKeypadGump_0C4(int unk)", // TODO: what's the parameter?
"byte Item::I_isOn(Item *, itemno)", // part of same coff set 044, 046, 048, 04A, 04C, 04E, 0A5, 0BC, 0C5, 0DC, 0F1, 0FA, 12C
"void SpriteProcess::I_createSprite(word, word, word, word, uword, uword, ubyte)",
"byte Item::I_getDirFromItem(Item *, itemno)", // same disasm as U8
"int16 Item::I_hurl(Item *,8 bytes)", // part of same coff set 028, 08D, 0BD, 0C0, 0C2, 0C8, 0F7, 0F9, 118, 11D
"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
"byte Actor::I_addHp(Actor *, int)",
- "void Intrinsic0CB(2 bytes)",
+ "void I_createMapJumpProcess(int16 mapnum)", // TODO: Implement me
"byte Actor::I_GetNPCDataField0x59Flag3_0CC(Actor *)",
"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
"int16 Game::I_isReleaseBuild(void)", // whether the string "GAME COMPILE=1" has the 1. Might be interesting to see what this does..
- "void Item::setQAndCallSomething(Item *, int16 q)", // based on disassembly
+ "void Item::I_setQAndCombine(Item *, int16 q)", // based on disassembly
// 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 Intrinsic0D3()",
+ "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
- "byte Intrinsic0D6(void)",
+ "byte CameraProcess::I_getCameraZ(void)",
"int16 Actor::I_getLastAnimSet(4 bytes)", // part of same coff set 01D, 05A, 0B9, 0D7, 0E4, 124
"void Actor::I_setDead(4 bytes)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
"int16 Item::I_getQLo(Item *)", // same as 02B based on same coff set 010, 02B, 066, 084, 0A1, 0AE, 0D9, 0EA
- "void Intrinsic0DA_Fade(void)", // something about fades
+ "void PaletteFaderProcess::I_setPalToAllGrey(void)", // sets all colors to 0x3F3F3F
"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
"byte Item::I_isOn(Item *, itemno)", // part of same coff set 044, 046, 048, 04A, 04C, 04E, 0A5, 0BC, 0C5, 0DC, 0F1, 0FA, 12C
"int16 Actor::I_GetNPCDataField0x4_0DD(Actor *)",
@@ -310,7 +310,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 Actor::I_GetNPCDataField0x8_0E2(Actor *)",
"int16 Actor::I_GetNPCDataField0xa_0E3(Actor *)",
"int16 Actor::I_getLastAnimSet(4 bytes)", // part of same coff set 01D, 05A, 0B9, 0D7, 0E4, 124
- "void Actor::I_NPCSomething0E5(Actor *, uint16)",
+ "void Actor::I_attackProbably(Actor *, uint16 target)", // TODO: game checks 0x59 flag 3 first.. what is that?
"void Actor::I_SetNPCDataField0x63_0E6(Actor *, int)",
"void Actor::I_setDead(4 bytes)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
"int16 Item::I_cast(6 bytes)",
@@ -319,8 +319,8 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 I_GetQOfAvatarInventoryItem0x4ed_0EB(void)",
"void Item::I_popToEnd(Item*, int)", // similar code to U8
"void Item::I_popToContainer(Item*, int)", // same code as U8
- "void Intrinsic0EE(void)",
- "int16 Intrinsic0EF(4 bytes not Item *)",
+ "void BatteryChargerProcess::I_create(void)",
+ "int16 Kernel::I_getNumProcesses(int, int)", // same code as U8
// 00F0
"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
"byte Item::I_isOn(Item *, itemno)", // part of same coff set 044, 046, 048, 04A, 04C, 04E, 0A5, 0BC, 0C5, 0DC, 0F1, 0FA, 12C
@@ -335,7 +335,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"byte Item::I_isOn(Item *, itemno)", // part of same coff set 044, 046, 048, 04A, 04C, 04E, 0A5, 0BC, 0C5, 0DC, 0F1, 0FA, 12C
"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 Item::I_andStatus(Item *, uint16 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
- "byte I_SomethingAboutGlobal7e2f_0FD(int)",
+ "byte MainActor::I_hasKeycard(int)",
"void I_displayText_0FE(char *)",
"int16 UCMachine::I_numToStr(int16 num)", // same as 113 based on same coff set 0FF, 113, 126
// 0100
@@ -362,7 +362,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 UCMachine::I_numToStr(int16 num)", // based on VMAIL::func0A example usage
"void Item::I_andStatus(Item *, uint16 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_getNPCNum(Item *)", // part of same coff set 067, 06D, 089, 08E, 0AD, 0F8, 100, 102, 105, 107, 109, 10B, 10D, 10F, 111, 115, 11C, 123, 129
- "byte Intrinsic116(14 bytes)",
+ "byte Intrinsic116(14 bytes)", // something like distance-to?
"void Item::I_andStatus(Item *, uint16 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_hurl(Item *,8 bytes)", // part of same coff set 028, 08D, 0BD, 0C0, 0C2, 0C8, 0F7, 0F9, 118, 11D
"void Item::I_doSomethingAndSetStatusFlag0x8000(Item *)", // same coff as 08C, 12A
@@ -394,7 +394,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)",
+ "void Intrinsic134(2 bytes)", // something to do with Wezzy/Weasel? Only called from WEA_BOOT::func0A
"void Actor::I_setDead(Actor *)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
"void UNUSEDInt136()",
"void UNUSEDInt137()"
diff --git a/engines/ultima/ultima8/ultima8.cpp b/engines/ultima/ultima8/ultima8.cpp
index 7cf44a7046..f677707dc0 100644
--- a/engines/ultima/ultima8/ultima8.cpp
+++ b/engines/ultima/ultima8/ultima8.cpp
@@ -139,7 +139,7 @@ Ultima8Engine::Ultima8Engine(OSystem *syst, const Ultima::UltimaGameDescription
_avatarInStasis(false), _paintEditorItems(false), _inversion(0), _painting(false),
_showTouching(false), _timeOffset(0), _hasCheated(false), _cheatsEnabled(false),
_ttfOverrides(false), _audioMixer(0), _scalerGump(nullptr),
- _inverterGump(nullptr), _lerpFactor(256), _inBetweenFrame(false), _alertActive(false),
+ _inverterGump(nullptr), _lerpFactor(256), _inBetweenFrame(false),
_unkCrusaderFlag(false) {
_application = this;
}
@@ -1410,11 +1410,6 @@ uint32 Ultima8Engine::I_getTimeInGameHours(const uint8 * /*args*/,
return get_instance()->getGameTimeInSeconds() / 900;
}
-uint32 Ultima8Engine::I_getAlertActive(const uint8 * /*args*/,
- unsigned int /*argsize*/) {
- return get_instance()->isAlertActive() ? 1 : 0;
-}
-
uint32 Ultima8Engine::I_getUnkCrusaderFlag(const uint8 * /*args*/,
unsigned int /*argsize*/) {
return get_instance()->isUnkCrusaderFlag() ? 1 : 0;
diff --git a/engines/ultima/ultima8/ultima8.h b/engines/ultima/ultima8/ultima8.h
index 8f95972e4e..5f0b6008c8 100644
--- a/engines/ultima/ultima8/ultima8.h
+++ b/engines/ultima/ultima8/ultima8.h
@@ -121,7 +121,6 @@ private:
bool _hasCheated;
bool _cheatsEnabled;
unsigned int _inversion;
- bool _alertActive; //!< is intruder alert active (Crusader)
bool _unkCrusaderFlag; //!< not sure what this is but it's only used in usecode for crusader, so just keep track of it..
private:
/**
@@ -226,7 +225,6 @@ public:
INTRINSIC(I_clrUnkCrusaderFlag);
INTRINSIC(I_makeAvatarACheater);
INTRINSIC(I_closeItemGumps);
- INTRINSIC(I_getAlertActive); // for Crusader
void setAvatarInStasis(bool stat) {
_avatarInStasis = stat;
@@ -250,13 +248,6 @@ public:
_showTouching = !_showTouching;
}
- bool isAlertActive() const {
- return _alertActive;
- }
- void setAlertActive(bool active) {
- _alertActive = active;
- }
-
bool isUnkCrusaderFlag() const {
return _unkCrusaderFlag;
}
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index cc040134ae..6a5fb159de 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -41,20 +41,20 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_getMapArray, // See TRIGGER::ordinal21 - stored in a variable 'mapNum'
Item::I_getStatus,
Item::I_orStatus,
- Item::I_equip, // void Intrinsic006(6 bytes)
+ Item::I_equip, // void Intrinsic006(6 bytes) - TODO: confirm this
Item::I_isOnScreen, //
Actor::I_isNPC, // byte Intrinsic008(Item *)
Item::I_getZ, // byte Intrinsic009(Item *)
Item::I_destroy, // void Intrinsic00A(Item *)
- 0, // something with npcdata void Intrinsic00B(4 bytes)
+ 0, // get something npcdata, maybe HP void Intrinsic00B(4 bytes)
0, // void Intrinsic00C(2 bytes)
Item::I_getDirToItem, // byte Intrinsic00D(6 bytes)
0, // int Intrinsic00E(8 bytes)
- 0, // based on TESTFLIC, appears to be I_playVideo(item*, char *vidname, int16 sizex, int16 sizey)
+ 0, // TODO: I_playVideo(item, vidname, int16 sizex, int16 sizey)
// 0x010
Item::I_getQLo, // Based on having same coff as 02B
Actor::I_getMap, // int Intrinsic011(4 bytes)
- 0, // void Intrinsic012(2 bytes)
+ MusicProcess::I_playMusic, // void Intrinsic012(2 bytes) TODO: Make sure the track list order is right (I don't think it is..)
Item::I_getX, //int Intrinsic013(4 bytes)
Item::I_getY, //int Intrinsic014(4 bytes)
AudioProcess::I_playSFXCru,
@@ -79,7 +79,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_getClosestDirectionInRange, // int Intrinsic027(14 bytes)
Item::I_hurl, // int Intrinsic028(12 bytes)
UCMachine::I_true, // TODO: This is actually game difficulty level. Make an intrinsic for that once it's implemented (for now return 1, easiest difficulty).
- AudioProcess::I_playAmbientSFXCru, // Confirmed!
+ AudioProcess::I_playAmbientSFXCru,
Item::I_getQLo, // int16 Intrinsic02B(4 bytes)
Item::I_inFastArea, // byte Intrinsic02C(4 bytes) // based on disassembly - checks for flag 0x2000
Item::I_setQHi,
@@ -91,9 +91,9 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_receiveHit, // void Intrinsic032(12 bytes)
Actor::I_isBusy, // int Intrinsic033(4 bytes)
Item::I_getDirFromTo16,
- 0, // int Intrinsic035(4 bytes)
+ 0, // TODO: Actor::I_getSomeFlagProbablyCrouch(Actor *)
Actor::I_doAnim, // void Intrinsic036(12 bytes)
- 0, // int Intrinsic037(4 bytes)
+ 0, // int Intrinsic037(4 bytes) (probably pick up)
AudioProcess::I_stopSFXCru, // takes Item *, sndno (from disasm)
Actor::I_isDead, // int Intrinsic039(4 bytes)
AudioProcess::I_isSFXPlayingForObject,
@@ -162,11 +162,11 @@ Intrinsic RemorseIntrinsics[] = {
Ultima8Engine::I_clrAvatarInStasis,
AudioProcess::I_stopSFXCru, // takes Item *, from disasm
PaletteFaderProcess::I_fadeToBlack, // void Intrinsic077(void)
- 0, // void Intrinsic078(void)
+ MainActor::I_clrKeycards, // void Intrinsic078(void)
MainActor::I_teleportToEgg, // different than U8's? void Intrinsic079(6 bytes)
PaletteFaderProcess::I_fadeFromBlack, // void Intrinsic07A(void)
Actor::I_clrImmortal, // based on disasm
- 0, // void Intrinsic07C(4 bytes) // I_getQIfSomething, see disassembly
+ Actor::I_getHp, // void Intrinsic07C(4 bytes)
Actor::I_setActivity, // void Intrinsic07D(6 bytes)
Item::I_getQuality,
Item::I_setQuality,
@@ -177,8 +177,8 @@ Intrinsic RemorseIntrinsics[] = {
Actor::I_setMana, //
Item::I_getQLo, // based on same coff set as 02B
Actor::I_setImmortal, // void Intrinsic085(4 bytes)
- 0, // void Intrinsic086(void)
- 0, // void Intrinsic087(void)
+ CameraProcess::I_getCameraX, // void Intrinsic086(void)
+ CameraProcess::I_getCameraY, // void Intrinsic087(void)
Item::I_setMapArray,
Item::I_getNpcNum, // based on same coff as 102 (-> variable name in TRIGGER::ordinal21)
0, // void Intrinsic08A(12 bytes)
@@ -188,15 +188,15 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_getNpcNum, // based on same coff as 102 (-> variable name in TRIGGER::ordinal21)
0, // TODO: PaletteFaderProcess::I_setPalToAllBlack
// 0x090
- 0, // void Intrinsic090(void)
+ MusicProcess::I_musicStop, // void Intrinsic090(void)
0, // void Intrinsic091(void)
- 0, // I_playFlic(char *)? void Intrinsic092(void)
+ 0, // TODO: I_playFlic(char *)? void Intrinsic092(void)
0, // void Intrinsic093(void)
- Game::I_playCredits,
- 0, // int Intrinsic095(void) // get global - something about keyboard (by disasm)
+ Game::I_playCredits, // TODO: Implement this
+ 0, // TODO: Kernel::I_getCurrentKeyDown
MainActor::I_teleportToEgg, // void Intrinsic096(4 bytes)
- 0, // void Intrinsic097(void)
- 0, // void Intrinsic098(void)
+ 0, // TODO: PaletteFaderProcess:I_setScreenGreyscale(void) (converts all colors to their Y values on each channel)
+ 0, // void Intrinsic098(void) // TODO: reset vargas health to 500.. weird.
Item::I_andStatus, // void Intrinsic099(6 bytes)
0, // TODO: PaletteFaderProcess::I_stopFadesAndResetToGamePal(void),
PaletteFaderProcess::I_fadeFromBlack, // fade to game pal with number of steps
@@ -243,30 +243,30 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_andStatus, // void Intrinsic0C1(6 bytes)
Item::I_hurl, // void Intrinsic0C2(12 bytes)
Item::I_andStatus, // void Intrinsic0C3(6 bytes)
- 0, // void Intrinsic0C4(2 bytes)
+ 0, // void Intrinsic0C4(2 bytes) // TODO: Implement keypad gump (gump shape 10 for the border, shape 11 frames for the buttons.)
Item::I_isOn,
SpriteProcess::I_createSprite, // void Intrinsic0C6(14 bytes)
Item::I_getDirFromItem, // int Intrinsic0C7(6 bytes)
Item::I_hurl, // void Intrinsic0C8(12 bytes)
Item::I_getQHi, // based on same coff set as 026
Actor::I_setHp, // int Intrinsic0CA(6 bytes)
- 0, // void Intrinsic0CB(2 bytes)
+ 0, // 0CB void I_createMapJumpProcess(int16 mapnum)", // TODO: Implement me
0, // int Intrinsic0CC(4 bytes)
Actor::I_setActivity, // void Intrinsic0CD(6 bytes)
UCMachine::I_true, // whether the string "GAME COMPILE=1" has the 1. Might be interesting to see how this changes the game.. for now just set to true.
- 0, // void Intrinsic0CF(6 bytes)
+ Item::I_setQAndCombine, // void Intrinsic0CF(6 bytes)
// 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
- 0, // UNUSEDInt00D3()
+ 0, // void Intrinsic0D3(void)
AudioProcess::I_playSFX, // void Intrinsic0D4(2 bytes)
Item::I_use, // void Intrinsic0D5(4 bytes)
- 0, // int Intrinsic0D6(void)
+ CameraProcess::I_getCameraZ, // int Intrinsic0D6(void)
Actor::I_getLastAnimSet, // void Intrinsic0D7(4 bytes)
Actor::I_setDead,
Item::I_getQLo, // based on same coff set as 02B
- 0, // void Intrinsic0DA(void)
+ 0, // TODO: PaletteFaderProcess::I_setPalToAllGrey // sets all colors to 0x3F3F3F
Actor::I_setActivity, // void Intrinsic0DB(6 bytes)
Item::I_isOn,
0, // void Intrinsic0DD(4 bytes)
@@ -287,8 +287,8 @@ Intrinsic RemorseIntrinsics[] = {
0, // void Intrinsic0EB(void)
Item::I_popToEnd,
Item::I_popToContainer,
- 0, // void Intrinsic0EE(void)
- 0, // void Intrinsic0EF(4 bytes)
+ 0, // TODO: Implement BatteryChargerProcess::I_create
+ Kernel::I_getNumProcesses, // void Intrinsic0EF(4 bytes)
// 0x0F0
Item::I_getQHi, // based on same coff set as 026
Item::I_isOn,
@@ -303,7 +303,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_isOn,
Item::I_getQHi, // based on same coff set as 026
Item::I_andStatus, // void Intrinsic0FC(6 bytes)
- 0, // int Intrinsic0FD(2 bytes)
+ MainActor::I_hasKeycard, // int Intrinsic0FD(2 bytes)
0, // void Intrinsic0FE(4 bytes)
UCMachine::I_numToStr, // same as 113 based on same coff set 0FF, 113, 126
// 0x100
@@ -330,7 +330,7 @@ Intrinsic RemorseIntrinsics[] = {
UCMachine::I_numToStr, // see VMAIL::func0A for example usage
Item::I_andStatus, // void Intrinsic114(6 bytes)
Item::I_getNpcNum, // based on same coff as 102 (-> variable name in TRIGGER::ordinal21)
- 0, // ? Item::I_getTypeFlag, byte Intrinsic116(14 bytes)
+ 0, // byte Intrinsic116(14 bytes)
Item::I_andStatus, // void Intrinsic117(6 bytes)
Item::I_hurl, // int16 Intrinsic118(12 bytes)
Item::I_doSomethingAndSetUnkCruFlag, // void Intrinsic119(4 bytes)
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index 87a0a227d6..13e6b73d79 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -53,7 +53,7 @@ namespace Ultima8 {
DEFINE_RUNTIME_CLASSTYPE_CODE(MainActor)
MainActor::MainActor() : _justTeleported(false), _accumStr(0), _accumDex(0),
- _accumInt(0), _cruBatteryType(ChemicalBattery) {
+ _accumInt(0), _cruBatteryType(ChemicalBattery), _keycards(0) {
}
MainActor::~MainActor() {
@@ -405,6 +405,13 @@ int16 MainActor::getMaxEnergy() {
}
}
+bool MainActor::hasKeycard(int num) {
+ if (num > 31)
+ return 0;
+
+ return _keycards & (1 << num);
+}
+
void MainActor::saveData(Common::WriteStream *ws) {
Actor::saveData(ws);
uint8 jt = _justTeleported ? 1 : 0;
@@ -412,6 +419,12 @@ void MainActor::saveData(Common::WriteStream *ws) {
ws->writeUint32LE(_accumStr);
ws->writeUint32LE(_accumDex);
ws->writeUint32LE(_accumInt);
+
+ if (GAME_IS_CRUSADER) {
+ ws->writeByte(static_cast<byte>(_cruBatteryType));
+ ws->writeUint32LE(_keycards);
+ }
+
uint8 namelength = static_cast<uint8>(_name.size());
ws->writeByte(namelength);
for (unsigned int i = 0; i < namelength; ++i)
@@ -427,6 +440,11 @@ bool MainActor::loadData(Common::ReadStream *rs, uint32 version) {
_accumDex = static_cast<int32>(rs->readUint32LE());
_accumInt = static_cast<int32>(rs->readUint32LE());
+ if (GAME_IS_CRUSADER) {
+ _cruBatteryType = static_cast<CruBatteryType>(rs->readByte());
+ _keycards = rs->readUint32LE();
+ }
+
uint8 namelength = rs->readByte();
_name.resize(namelength);
for (unsigned int i = 0; i < namelength; ++i)
@@ -517,6 +535,20 @@ uint32 MainActor::I_getMaxEnergy(const uint8 *args,
return av->getMaxEnergy();
}
+uint32 MainActor::I_hasKeycard(const uint8 *args,
+ unsigned int /*argsize*/) {
+ ARG_UINT16(num);
+ MainActor *av = getMainActor();
+ return av->hasKeycard(num);
+}
+
+uint32 MainActor::I_clrKeycards(const uint8 *args,
+ unsigned int /*argsize*/) {
+ MainActor *av = getMainActor();
+ av->clrKeycards();
+ return 0;
+}
+
void MainActor::useInventoryItem(uint32 shapenum) {
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
pout << "Can't use item: avatarInStasis" << Std::endl;
diff --git a/engines/ultima/ultima8/world/actors/main_actor.h b/engines/ultima/ultima8/world/actors/main_actor.h
index ccc91a91c9..057588650a 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.h
+++ b/engines/ultima/ultima8/world/actors/main_actor.h
@@ -99,6 +99,12 @@ public:
int16 getMaxEnergy();
+ bool hasKeycard(int num);
+
+ void clrKeycards() {
+ _keycards = 0;
+ }
+
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
@@ -112,6 +118,8 @@ public:
INTRINSIC(I_setAvatarInCombat);
INTRINSIC(I_isAvatarInCombat);
INTRINSIC(I_getMaxEnergy);
+ INTRINSIC(I_hasKeycard);
+ INTRINSIC(I_clrKeycards);
void getWeaponOverlay(const WeaponOverlayFrame *&frame_, uint32 &shape_);
@@ -125,6 +133,7 @@ protected:
int _accumDex;
int _accumInt;
+ uint32 _keycards;
CruBatteryType _cruBatteryType;
Std::string _name;
diff --git a/engines/ultima/ultima8/world/camera_process.cpp b/engines/ultima/ultima8/world/camera_process.cpp
index c24f7a7db0..eabe2b55cd 100644
--- a/engines/ultima/ultima8/world/camera_process.cpp
+++ b/engines/ultima/ultima8/world/camera_process.cpp
@@ -163,22 +163,33 @@ void CameraProcess::run() {
}
void CameraProcess::ItemMoved() {
- if (_itemNum) {
- Item *item = getItem(_itemNum);
+ if (!_itemNum)
+ return;
- // We only update for now if lerping has been disabled
- if (item && item->hasExtFlags(Item::EXT_LERP_NOPREV)) {
- item->getLocation(_ex, _ey, _ez);
- _sx = _ex;
- _sy = _ey;
- _sz = _ez += 20;
+ Item *item = getItem(_itemNum);
- World::get_instance()->getCurrentMap()->updateFastArea(_sx, _sy, _sz, _ex, _ey, _ez);
- }
+ // We only update for now if lerping has been disabled
+ if (!item || !item->hasExtFlags(Item::EXT_LERP_NOPREV))
+ return;
+
+ int32 ix, iy, iz;
+ item->getLocation(ix, iy, iz);
+
+ int32 maxdist = MAX(MAX(abs(_ex - iz), abs(_ey - iy)), abs(_ez - iz));
+
+ if (GAME_IS_U8 || (GAME_IS_CRUSADER && maxdist > 0x40)) {
+ _sx = _ex = ix;
+ _sy = _ey = iy;
+ _ez = iz;
+ _sz = _ez += 20;
+ World::get_instance()->getCurrentMap()->updateFastArea(_sx, _sy, _sz, _ex, _ey, _ez);
}
}
void CameraProcess::GetLerped(int32 &x, int32 &y, int32 &z, int32 factor, bool noupdate) {
+ // TODO: For Crusader, only update the camera position if the
+ // distance to the target object passes a threshold.
+
if (_time == 0) {
if (!noupdate) {
@@ -364,5 +375,25 @@ uint32 CameraProcess::I_stopQuake(const uint8 * /*args*/, unsigned int /*argsize
return 0;
}
+uint32 CameraProcess::I_getCameraX(const uint8 *args, unsigned int argsize) {
+ int32 x, y, z;
+ assert(GAME_IS_CRUSADER);
+ GetCameraLocation(x, y, z);
+ return x / 2;
+}
+
+uint32 CameraProcess::I_getCameraY(const uint8 *args, unsigned int argsize) {
+ int32 x, y, z;
+ assert(GAME_IS_CRUSADER);
+ GetCameraLocation(x, y, z);
+ return y / 2;
+}
+
+uint32 CameraProcess::I_getCameraZ(const uint8 *args, unsigned int argsize) {
+ int32 x, y, z;
+ GetCameraLocation(x, y, z);
+ return z;
+}
+
} // End of namespace Ultima8
} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/camera_process.h b/engines/ultima/ultima8/world/camera_process.h
index 4b0c6a20f4..9beade0caa 100644
--- a/engines/ultima/ultima8/world/camera_process.h
+++ b/engines/ultima/ultima8/world/camera_process.h
@@ -66,6 +66,9 @@ public:
INTRINSIC(I_scrollTo);
INTRINSIC(I_startQuake);
INTRINSIC(I_stopQuake);
+ INTRINSIC(I_getCameraX);
+ INTRINSIC(I_getCameraY);
+ INTRINSIC(I_getCameraZ);
static void GetCameraLocation(int32 &x, int32 &y, int32 &z);
static CameraProcess *GetCameraProcess() {
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 1c71243410..87f010a3a8 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -2260,6 +2260,17 @@ uint32 Item::I_setQuantity(const uint8 *args, unsigned int /*argsize*/) {
return 0;
}
+uint32 Item::I_setQAndCombine(const uint8 *args, unsigned int /*argsize*/) {
+ ARG_ITEM_FROM_PTR(item);
+ ARG_UINT16(q);
+ if (!item) return 0;
+
+ item->setQuality(q);
+ item->callUsecodeEvent_combine();
+
+ return 0;
+}
+
uint32 Item::I_getFamily(const uint8 *args, unsigned int /*argsize*/) {
ARG_ITEM_FROM_PTR(item);
if (!item) return 0;
diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index 10186809cf..fc543e2912 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -488,6 +488,7 @@ public:
INTRINSIC(I_setQLo);
INTRINSIC(I_setQuality);
INTRINSIC(I_setQuantity);
+ INTRINSIC(I_setQAndCombine);
INTRINSIC(I_getFamily);
INTRINSIC(I_getTypeFlag);
INTRINSIC(I_getStatus);
More information about the Scummvm-git-logs
mailing list