[Scummvm-git-logs] scummvm master -> 27dab7b18786ee9b67ad2a3a68dae489acc3c8d8
mduggan
mgithub at guarana.org
Fri Jul 3 10:42:56 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:
4471a55cd0 ULTIMA8: Increase usage range in crusader
31bc37affa ULTIMA8: Add simpler container search functions
f79b300cdd ULTIMA8: Reduce reticle debug spam a bit
d0ec49a305 ULTIMA8: Add x/y offset as some crusader gumps use them
4abc2b6fd5 ULTIMA8: Add support for Crusader inventory items
f858c03755 ULTIMA8: Give Crusader avatar correct items on startup
07a43d975a ULTIMA8: Fix null pointer usage in reticle process
9d396d6a1b ULTIMA8: Make crusader inventory gumps work
535867a4e8 ULTIMA8: Improve debug messages
27dab7b187 ULTIMA8: Add ability to cycle items for Crusader
Commit: 4471a55cd0c93cab92958e53265f0c3a6481936e
https://github.com/scummvm/scummvm/commit/4471a55cd0c93cab92958e53265f0c3a6481936e
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Increase usage range in crusader
Changed paths:
engines/ultima/ultima8/gumps/game_map_gump.cpp
diff --git a/engines/ultima/ultima8/gumps/game_map_gump.cpp b/engines/ultima/ultima8/gumps/game_map_gump.cpp
index 7e0ba6ffeb..82423055b4 100644
--- a/engines/ultima/ultima8/gumps/game_map_gump.cpp
+++ b/engines/ultima/ultima8/gumps/game_map_gump.cpp
@@ -394,8 +394,13 @@ void GameMapGump::onMouseDouble(int button, int32 mx, int32 my) {
item->getLocation(xv, yv, zv);
item->dumpInfo();
+ int range = 128; // CONSTANT!
+ if (GAME_IS_CRUSADER) {
+ range = 512;
+ }
+
if (dynamic_cast<Actor *>(item) ||
- avatar->canReach(item, 128)) { // CONSTANT!
+ avatar->canReach(item, range)) {
// call the 'use' event
item->use();
} else {
Commit: 31bc37affa5175a3c2c9c4f7537993cd6b8c88f7
https://github.com/scummvm/scummvm/commit/31bc37affa5175a3c2c9c4f7537993cd6b8c88f7
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Add simpler container search functions
Changed paths:
engines/ultima/ultima8/world/container.cpp
engines/ultima/ultima8/world/container.h
diff --git a/engines/ultima/ultima8/world/container.cpp b/engines/ultima/ultima8/world/container.cpp
index dc14ec6552..f8390f8919 100644
--- a/engines/ultima/ultima8/world/container.cpp
+++ b/engines/ultima/ultima8/world/container.cpp
@@ -296,6 +296,43 @@ void Container::containerSearch(UCList *itemlist, const uint8 *loopscript,
}
}
+Item *Container::getFirstItemWithShape(uint16 shapeno, bool recurse) {
+ Std::list<Item *>::iterator iter;
+ for (iter = _contents.begin(); iter != _contents.end(); ++iter) {
+ if ((*iter)->getShape() == shapeno)
+ return *iter;
+
+ if (recurse) {
+ // recurse into child-containers
+ Container *container = dynamic_cast<Container *>(*iter);
+ if (container) {
+ Item *result = container->getFirstItemWithShape(shapeno, recurse);
+ if (result)
+ return result;
+ }
+ }
+ }
+
+ return nullptr;
+}
+
+void Container::getItemsWithShapeFamily(Std::vector<Item *> &itemlist, uint16 family, bool recurse) {
+ Std::list<Item *>::iterator iter;
+ for (iter = _contents.begin(); iter != _contents.end(); ++iter) {
+ if ((*iter)->getShapeInfo()->_family == family)
+ itemlist.push_back(*iter);
+
+ if (recurse) {
+ // recurse into child-containers
+ Container *container = dynamic_cast<Container *>(*iter);
+ if (container) {
+ container->getItemsWithShapeFamily(itemlist, family, recurse);
+ }
+ }
+ }
+
+}
+
void Container::dumpInfo() const {
Item::dumpInfo();
diff --git a/engines/ultima/ultima8/world/container.h b/engines/ultima/ultima8/world/container.h
index 4255181c04..3f26dae10d 100644
--- a/engines/ultima/ultima8/world/container.h
+++ b/engines/ultima/ultima8/world/container.h
@@ -86,6 +86,16 @@ public:
void containerSearch(UCList *itemlist, const uint8 *loopscript,
uint32 scriptsize, bool recurse) const;
+ //! A simpler search of the container which just gets the
+ //! first item with a given shape number, optionally recursively.
+ //! \return The first item with that shape, or nullptr if nothing found.
+ Item *getFirstItemWithShape(uint16 shapeno, bool recurse);
+
+ //! A simpler search of the container which just gets the
+ //! items with a given shape family, optionally recursively.
+ //! \return The first item with that shape, or nullptr if nothing found.
+ void getItemsWithShapeFamily(Std::vector<Item *> &itemlist, uint16 family, bool recurse);
+
//! Get the weight of the container and its contents
//! \return weight
uint32 getTotalWeight() const override;
Commit: f79b300cdd86dfbe994979f1e2e9c5ac8217209e
https://github.com/scummvm/scummvm/commit/f79b300cdd86dfbe994979f1e2e9c5ac8217209e
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Reduce reticle debug spam a bit
Changed paths:
engines/ultima/ultima8/world/target_reticle_process.cpp
diff --git a/engines/ultima/ultima8/world/target_reticle_process.cpp b/engines/ultima/ultima8/world/target_reticle_process.cpp
index 09f3b0d199..a3696acf07 100644
--- a/engines/ultima/ultima8/world/target_reticle_process.cpp
+++ b/engines/ultima/ultima8/world/target_reticle_process.cpp
@@ -95,8 +95,8 @@ bool TargetReticleProcess::findTargetItem() {
_lastTargetDir = dir;
changed = true;
} else if (!item) {
- debug("New reticle target: NONE");
if (_lastTargetItem) {
+ debug("New reticle target: NONE");
Item *lastItem = getItem(_lastTargetItem);
if (lastItem)
lastItem->clearExtFlag(Item::EXT_TARGET);
@@ -165,6 +165,12 @@ void TargetReticleProcess::itemMoved(Item *item) {
void TargetReticleProcess::clearSprite() {
_reticleSpriteProcess = 0;
+ if (_lastTargetItem) {
+ Item *item = getItem(_lastTargetItem);
+ if (item) {
+ item->clearExtFlag(Item::EXT_TARGET);
+ }
+ }
_lastTargetItem = 0;
_lastTargetDir = 0x10;
}
Commit: d0ec49a305dd76698f97bdb291ce2f88ba44080a
https://github.com/scummvm/scummvm/commit/d0ec49a305dd76698f97bdb291ce2f88ba44080a
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Add x/y offset as some crusader gumps use them
Changed paths:
engines/ultima/ultima8/gumps/gump.cpp
diff --git a/engines/ultima/ultima8/gumps/gump.cpp b/engines/ultima/ultima8/gumps/gump.cpp
index 0ee9dd5d53..7db6e3c310 100644
--- a/engines/ultima/ultima8/gumps/gump.cpp
+++ b/engines/ultima/ultima8/gumps/gump.cpp
@@ -92,6 +92,8 @@ void Gump::UpdateDimsFromShape() {
assert(sf);
_dims.w = sf->_width;
_dims.h = sf->_height;
+ _dims.x = -sf->_xoff;
+ _dims.y = -sf->_yoff;
}
void Gump::CreateNotifier() {
Commit: 4abc2b6fd5f93d87b11e7a81ec29e2398e3e7880
https://github.com/scummvm/scummvm/commit/4abc2b6fd5f93d87b11e7a81ec29e2398e3e7880
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Add support for Crusader inventory items
Changed paths:
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
engines/ultima/ultima8/usecode/remorse_intrinsics.h
engines/ultima/ultima8/world/actors/main_actor.cpp
engines/ultima/ultima8/world/actors/main_actor.h
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 53f251527c..7efddb0849 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -125,7 +125,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 Item::I_getDirFromTo16(x1, y1, x2, y2)",
"byte Actor::I_getSomeFlagProbablyCrouch(Item *)",
"int16 Actor::I_doAnim(12 bytes)", // v. similar code to U8
- "byte I_probablyPickUpItem_037(4 bytes)", // same coff as 0B8
+ "byte MainActor::I_addItemCru(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)",
@@ -262,7 +262,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"int16 Item::I_equip(6 bytes)",
"void Ultima8Engine::I_clrAlertActive(void)",
"int16 Ultima8Engine::I_getAvatarInStasis(void)",
- "byte I_probablyPickUpItem_0B8(4 bytes)", // same coff as 037
+ "byte MainActor::I_addItemCru(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)", // TODO: check usecode.. code is weird, something with an imaginary chequered wall shape? (0x31A)
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index 64321df270..ec935dd093 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -93,7 +93,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_getDirFromTo16,
0, // TODO: Actor::I_getSomeFlagProbablyCrouch(Actor *)
Actor::I_doAnim, // void Intrinsic036(12 bytes)
- 0, // int Intrinsic037(4 bytes) (probably pick up)
+ MainActor::I_addItemCru, // int Intrinsic037(4 bytes)
AudioProcess::I_stopSFXCru, // takes Item *, sndno (from disasm)
Actor::I_isDead, // int Intrinsic039(4 bytes)
AudioProcess::I_isSFXPlayingForObject,
@@ -230,7 +230,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_equip, // void Intrinsic0B5(6 bytes)
World::I_clrAlertActive, // void Intrinsic0B6(void)
Ultima8Engine::I_getAvatarInStasis, // void Intrinsic0B7(void)
- 0, // int Intrinsic0B8(4 bytes)
+ MainActor::I_addItemCru, // int Intrinsic0B8(4 bytes)
Actor::I_getLastAnimSet, // void Intrinsic0B9(4 bytes)
Item::I_setQuality,
0, // int Intrinsic0BB(8 bytes)
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index 13e6b73d79..badeef6ad0 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -53,7 +53,8 @@ namespace Ultima8 {
DEFINE_RUNTIME_CLASSTYPE_CODE(MainActor)
MainActor::MainActor() : _justTeleported(false), _accumStr(0), _accumDex(0),
- _accumInt(0), _cruBatteryType(ChemicalBattery), _keycards(0) {
+ _accumInt(0), _cruBatteryType(ChemicalBattery), _keycards(0),
+ _activeWeapon(0), _activeInvItem(0) {
}
MainActor::~MainActor() {
@@ -74,7 +75,6 @@ GravityProcess *MainActor::ensureGravityProcess() {
}
bool MainActor::CanAddItem(Item *item, bool checkwghtvol) {
- const unsigned int backpack_shape = 529; //!! *cough* constant
if (!Actor::CanAddItem(item, checkwghtvol)) return false;
if (item->getParent() == _objId) return true; // already in here
@@ -82,19 +82,26 @@ bool MainActor::CanAddItem(Item *item, bool checkwghtvol) {
// now check 'equipment slots'
// we can have one item of each equipment type, plus one backpack
- uint32 equiptype = item->getShapeInfo()->_equipType;
- bool backpack = (item->getShape() == backpack_shape);
+ if (GAME_IS_U8) {
+ const unsigned int backpack_shape = 529; //!! *cough* constant
+ uint32 equiptype = item->getShapeInfo()->_equipType;
+ bool backpack = (item->getShape() == backpack_shape);
- // valid item type?
- if (equiptype == ShapeInfo::SE_NONE && !backpack) return false;
+ // valid item type?
+ if (equiptype == ShapeInfo::SE_NONE && !backpack) return false;
- Std::list<Item *>::iterator iter;
- for (iter = _contents.begin(); iter != _contents.end(); ++iter) {
- uint32 cet = (*iter)->getShapeInfo()->_equipType;
- bool cbackpack = ((*iter)->getShape() == backpack_shape);
+ Std::list<Item *>::iterator iter;
+ for (iter = _contents.begin(); iter != _contents.end(); ++iter) {
+ uint32 cet = (*iter)->getShapeInfo()->_equipType;
+ bool cbackpack = ((*iter)->getShape() == backpack_shape);
- // already have an item with the same equiptype
- if (cet == equiptype || (cbackpack && backpack)) return false;
+ // already have an item with the same equiptype
+ if (cet == equiptype || (cbackpack && backpack)) return false;
+ }
+ } else if (GAME_IS_CRUSADER) {
+ // TODO: Enforce the number of slots by family here (weapon / ammo / other)
+ // For now just enforce no limit.
+ return true;
}
return true;
@@ -111,6 +118,192 @@ bool MainActor::addItem(Item *item, bool checkwghtvol) {
return true;
}
+int16 MainActor::addItemCru(Item *item, bool showtoast) {
+ // This code is a little ugly, it's a somewhat close
+ // re-implementation of the original and could do
+ // with some cleanup.
+
+ if (!item || !item->getShape())
+ return 0;
+
+ int shapeno = item->getShape();
+ int x, y, z;
+ getLocation(x, y, z);
+
+ if (shapeno == 0x4ed) {
+ Item *credits = getFirstItemWithShape(shapeno, true);
+ if (credits) {
+ uint16 q = item->getQuality();
+ uint32 newq = credits->getQuality() + q;
+ if (newq > 64000)
+ newq = 64000;
+ credits->setQuality(newq);
+ credits->callUsecodeEvent_combine();
+ if (showtoast) {
+ warning("TODO: show toast for added credits %d", q);
+ }
+ item->destroy();
+ } else {
+ item->setFrame(0);
+ item->moveToContainer(this);
+ if (!_activeInvItem)
+ _activeInvItem = item->getObjId();
+ if (showtoast) {
+ warning("TODO: show toast for new credits %d", item->getQuality());
+ }
+ }
+ return 1;
+ }
+
+ switch (static_cast<ShapeInfo::SFamily>(item->getShapeInfo()->_family)) {
+ case ShapeInfo::SF_CRUWEAPON: { // 0xa
+ Item *weapon = getFirstItemWithShape(shapeno, true);
+ if (!weapon) {
+ // New weapon. Add it.
+ const WeaponInfo *winfo = item->getShapeInfo()->_weaponInfo;
+ assert(winfo);
+ if (winfo->_ammoType == 0) {
+ item->setQuality(0);
+ item->callUsecodeEvent_combine();
+ } else {
+ warning("TODO: Get default count for ammo type %d", winfo->_ammoType);
+ item->setQuality(100);
+ }
+ item->setLocation(x, y, z);
+ item->moveToContainer(this);
+ if (!_activeWeapon)
+ _activeWeapon = item->getObjId();
+ warning("TODO: Set new weapon as active weapon if there is none");
+ if (showtoast)
+ warning("TODO: Show toast for new weapon %d", shapeno);
+ }
+ break;
+ }
+ case ShapeInfo::SF_CRUAMMO: { // 0xb
+ Item *ammo = getFirstItemWithShape(shapeno, true);
+ if (!ammo) {
+ // don't have this ammo yet, add it
+ item->setQuality(1);
+ item->callUsecodeEvent_combine();
+ item->moveToContainer(this);
+ if (showtoast)
+ warning("TODO: Show toast for new ammo %d", shapeno);
+ return 1;
+ } else {
+ // already have this, add some ammo.
+ uint16 q = ammo->getQuality();
+ if (q < 0x14) {
+ ammo->setQuality(q + 1);
+ ammo->callUsecodeEvent_combine();
+ if (showtoast)
+ warning("TODO: Show toast for combined ammo %d (%d)", shapeno, q + 1);
+ item->destroy();
+ return 1;
+ }
+ }
+ break;
+ }
+ case ShapeInfo::SF_CRUBOMB: // 0xc
+ case ShapeInfo::SF_CRUINVITEM: // 0xd
+ if (shapeno == 0x111) {
+ addKeycard(item->getQuality() & 0xff);
+ if (showtoast) {
+ warning("TODO: show toast for added keycard %d", item->getQuality() & 0xff);
+ }
+ item->destroy();
+ return 1;
+ } else if ((shapeno == 0x3a2) || (shapeno == 0x3a3) || (shapeno == 0x3a4)) {
+ // Batteries
+ if (showtoast) {
+ warning("TODO: show toast for added battery %d", shapeno);
+ }
+ item->destroy();
+ int plusenergy = 0;
+ CruBatteryType oldbattery = _cruBatteryType;
+ if (shapeno == 0x3a2) {
+ if (oldbattery == NoBattery) {
+ setBatteryType(ChemicalBattery);
+ } else {
+ plusenergy = 0x9c4;
+ }
+ } else if (shapeno == 0x3a4) {
+ if (oldbattery < FusionBattery) {
+ setBatteryType(FusionBattery);
+ } else {
+ plusenergy = 5000;
+ }
+ } else if (shapeno == 0x3a3) {
+ if (oldbattery < FissionBattery) {
+ setBatteryType(FissionBattery);
+ } else {
+ plusenergy = 10000;
+ }
+ }
+ if (plusenergy) {
+ int newenergy = getMana() + plusenergy;
+ if (newenergy > getMaxEnergy())
+ newenergy = getMaxEnergy();
+ setMana(newenergy);
+ }
+ return 1;
+ } else {
+ Item *existing = getFirstItemWithShape(shapeno, true);
+ if (!existing) {
+ if ((shapeno == 0x52e) || (shapeno == 0x52f) || (shapeno == 0x530)) {
+ warning("TODO: Properly handle giving avatar a shield 0x%x", shapeno);
+ return 0;
+ } else {
+ item->setFrame(0);
+ item->setQuality(1);
+ item->callUsecodeEvent_combine();
+ bool added = item->moveToContainer(this);
+ if (showtoast) {
+ warning("TODO: show toast new item %d (%s)",
+ shapeno, added ? "added" : "failed");
+ }
+ if (!_activeInvItem)
+ _activeInvItem = item->getObjId();
+ return 1;
+ }
+ } else {
+ // Already have this item..
+ if ((shapeno == 0x52e) || (shapeno == 0x52f) || (shapeno == 0x530)) {
+ // shields, already have one, destroy the new one.
+ item->destroy();
+ return 1;
+ } else if (shapeno == 0x560) {
+ uint16 q = existing->getQuality();
+ if (q < 0x14) {
+ existing->setQuality(q + 1);
+ existing->callUsecodeEvent_combine();
+ if (showtoast) {
+ warning("TODO: show toast for combined cru spider q=%d", q + 1);
+ }
+ item->destroy();
+ return 1;
+ }
+ } else {
+ uint16 q = existing->getQuality();
+ if (q < 10) {
+ existing->setQuality(q + 1);
+ existing->callUsecodeEvent_combine();
+ if (showtoast) {
+ warning("TODO: show toast for combined other item %d q=%d", shapeno, q + 1);
+ }
+ item->destroy();
+ return 1;
+ }
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
void MainActor::teleport(int mapNum_, int32 x_, int32 y_, int32 z_) {
World *world = World::get_instance();
@@ -405,13 +598,19 @@ int16 MainActor::getMaxEnergy() {
}
}
-bool MainActor::hasKeycard(int num) {
+bool MainActor::hasKeycard(int num) const {
if (num > 31)
return 0;
return _keycards & (1 << num);
}
+void MainActor::addKeycard(int bitno) {
+ if (bitno > 31 || bitno < 0)
+ return;
+ _keycards |= (1 << bitno);
+}
+
void MainActor::saveData(Common::WriteStream *ws) {
Actor::saveData(ws);
uint8 jt = _justTeleported ? 1 : 0;
@@ -423,6 +622,8 @@ void MainActor::saveData(Common::WriteStream *ws) {
if (GAME_IS_CRUSADER) {
ws->writeByte(static_cast<byte>(_cruBatteryType));
ws->writeUint32LE(_keycards);
+ ws->writeUint16LE(_activeWeapon);
+ ws->writeUint16LE(_activeInvItem);
}
uint8 namelength = static_cast<uint8>(_name.size());
@@ -443,6 +644,8 @@ bool MainActor::loadData(Common::ReadStream *rs, uint32 version) {
if (GAME_IS_CRUSADER) {
_cruBatteryType = static_cast<CruBatteryType>(rs->readByte());
_keycards = rs->readUint32LE();
+ _activeWeapon = rs->readUint16LE();
+ _activeInvItem = rs->readUint16LE();
}
uint8 namelength = rs->readByte();
@@ -529,7 +732,7 @@ uint32 MainActor::I_getMaxEnergy(const uint8 *args,
unsigned int /*argsize*/) {
ARG_ACTOR_FROM_PTR(actor);
MainActor *av = getMainActor();
- if (actor != av) {
+ if (!av || actor != av) {
return 0;
}
return av->getMaxEnergy();
@@ -539,31 +742,43 @@ uint32 MainActor::I_hasKeycard(const uint8 *args,
unsigned int /*argsize*/) {
ARG_UINT16(num);
MainActor *av = getMainActor();
+ if (!av)
+ return 0;
return av->hasKeycard(num);
}
uint32 MainActor::I_clrKeycards(const uint8 *args,
unsigned int /*argsize*/) {
MainActor *av = getMainActor();
+ if (!av)
+ return 0;
av->clrKeycards();
return 0;
}
+uint32 MainActor::I_addItemCru(const uint8 *args,
+ unsigned int /*argsize*/) {
+ MainActor *av = getMainActor();
+ ARG_ITEM_FROM_ID(item);
+ ARG_UINT16(showtoast);
+
+ if (!av || !item)
+ return 0;
+
+ if (av->addItemCru(item, showtoast != 0))
+ return 1;
+
+ return 0;
+}
+
void MainActor::useInventoryItem(uint32 shapenum) {
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
pout << "Can't use item: avatarInStasis" << Std::endl;
return;
}
- LOOPSCRIPT(script, LS_SHAPE_EQUAL(shapenum));
- UCList uclist(2);
- this->containerSearch(&uclist, script, sizeof(script), true);
- if (uclist.getSize() < 1)
- return;
-
- uint16 oId = uclist.getuint16(0);
- Item *item = getItem(oId);
- item->callUsecodeEvent_use();
-
+ Item *item = this->getFirstItemWithShape(shapenum, true);
+ if (item)
+ item->callUsecodeEvent_use();
}
} // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/actors/main_actor.h b/engines/ultima/ultima8/world/actors/main_actor.h
index 057588650a..eb00ccde64 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.h
+++ b/engines/ultima/ultima8/world/actors/main_actor.h
@@ -47,6 +47,10 @@ public:
bool CanAddItem(Item *item, bool checkwghtvol = false) override;
bool addItem(Item *item, bool checkwghtvol = false) override;
+ //! Add item to avatar's inventory, but with some extra logic to do things like combine
+ //! ammo and credits, use batteries, etc.
+ int16 addItemCru(Item *item, bool showtoast);
+
//! teleport to the given location on the given map
void teleport(int mapNum_, int32 x_, int32 y_, int32 z_) override;
@@ -99,12 +103,29 @@ public:
int16 getMaxEnergy();
- bool hasKeycard(int num);
+ CruBatteryType getBatteryType() const {
+ return _cruBatteryType;
+ }
+ void setBatteryType(CruBatteryType newbattery) {
+ _cruBatteryType = newbattery;
+ setMana(getMaxEnergy());
+ }
+
+ bool hasKeycard(int num) const;
+ void addKeycard(int bitno);
void clrKeycards() {
_keycards = 0;
}
+ uint16 getActiveWeapon() const {
+ return _activeWeapon;
+ }
+
+ uint16 getActiveInvItem() const {
+ return _activeInvItem;
+ }
+
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
@@ -120,6 +141,7 @@ public:
INTRINSIC(I_getMaxEnergy);
INTRINSIC(I_hasKeycard);
INTRINSIC(I_clrKeycards);
+ INTRINSIC(I_addItemCru);
void getWeaponOverlay(const WeaponOverlayFrame *&frame_, uint32 &shape_);
@@ -135,8 +157,11 @@ protected:
uint32 _keycards;
CruBatteryType _cruBatteryType;
+ uint16 _activeWeapon;
+ uint16 _activeInvItem;
Std::string _name;
+
};
} // End of namespace Ultima8
Commit: f858c03755557f1e4b539f62abff6908c265915c
https://github.com/scummvm/scummvm/commit/f858c03755557f1e4b539f62abff6908c265915c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Give Crusader avatar correct items on startup
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 3cdf424deb..bcc943e1d8 100644
--- a/engines/ultima/ultima8/games/start_crusader_process.cpp
+++ b/engines/ultima/ultima8/games/start_crusader_process.cpp
@@ -30,6 +30,7 @@
#include "ultima/ultima8/world/current_map.h"
#include "ultima/ultima8/world/egg.h"
#include "ultima/ultima8/world/camera_process.h"
+#include "ultima/ultima8/world/actors/main_actor.h"
#include "ultima/ultima8/world/world.h"
#include "ultima/ultima8/ultima8.h"
#include "ultima/ultima8/kernel/kernel.h"
@@ -88,13 +89,15 @@ void StartCrusaderProcess::run() {
//UCList uclist(2);
if (!_skipStart) {
+ // TODO:
+ // * Give avatar item 0x4d4 and item 0x598
// TODO: Find the first MISS1EGG egg like in U8 - should teleport in
- // Game starts a teleport process to Egg 0x1e:
- // Item 9115 (class TeleportEgg, shape 404, 1, (60656,59312,16) q:99, m:0, n:0, f: 0x2000, ef:0x3 shapeinfo f:1009, fam:8, et:0)
+ //Kernel::get_instance()->addProcess(new TeleportToEggProcess(1, 0x1e));
+
/*
- LOOPSCRIPT(script, LS_AND(LS_SHAPE_EQUAL1(73), LS_Q_EQUAL(36)));
+ LOOPSCRIPT(script, LS_AND(LS_SHAPE_EQUAL1(0x90D), LS_Q_EQUAL(36)));
currentmap->areaSearch(&uclist, script, sizeof(script),
- 0, 256, false, 16188, 7500);
+ 0, 256, false, 16188, 7500);
if (uclist.getSize() < 1) {
perr << "Unable to find FIRST egg!" << Std::endl;
return;
@@ -109,9 +112,17 @@ void StartCrusaderProcess::run() {
egg->hatch();
*/
+ MainActor *avatar = getMainActor();
+ int mapnum = avatar->getMapNum();
+ Item *datalink = ItemFactory::createItem(0x4d4, 0, 0, 0, 0, mapnum, 0, true);
+ avatar->addItemCru(datalink, false);
+ 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();
}
Commit: 07a43d975a4443869cbf9d377f9840d638c259af
https://github.com/scummvm/scummvm/commit/07a43d975a4443869cbf9d377f9840d638c259af
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Fix null pointer usage in reticle process
Changed paths:
engines/ultima/ultima8/world/target_reticle_process.cpp
diff --git a/engines/ultima/ultima8/world/target_reticle_process.cpp b/engines/ultima/ultima8/world/target_reticle_process.cpp
index a3696acf07..4103e82760 100644
--- a/engines/ultima/ultima8/world/target_reticle_process.cpp
+++ b/engines/ultima/ultima8/world/target_reticle_process.cpp
@@ -150,16 +150,13 @@ void TargetReticleProcess::itemMoved(Item *item) {
SpriteProcess *spriteproc = dynamic_cast<SpriteProcess *>(Kernel::get_instance()->getProcess(_reticleSpriteProcess));
- // TODO: If the item moved outside the direction we're targeting,
- // the process should be terminated.
-
if (spriteproc) {
if (actordir != _lastTargetDir || dirtoitem != _lastTargetDir) {
spriteproc->terminate();
clearSprite();
+ } else {
+ spriteproc->move(x, y, z);
}
- } else {
- spriteproc->move(x, y, z);
}
}
Commit: 9d396d6a1b61203ac2963ee9d70cab0a14286a6b
https://github.com/scummvm/scummvm/commit/9d396d6a1b61203ac2963ee9d70cab0a14286a6b
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Make crusader inventory gumps work
Changed paths:
engines/ultima/ultima8/graphics/type_flags.cpp
engines/ultima/ultima8/gumps/cru_inventory_gump.cpp
engines/ultima/ultima8/gumps/cru_inventory_gump.h
engines/ultima/ultima8/gumps/cru_weapon_gump.cpp
engines/ultima/ultima8/gumps/cru_weapon_gump.h
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 d550ac0232..e485e4f961 100644
--- a/engines/ultima/ultima8/graphics/type_flags.cpp
+++ b/engines/ultima/ultima8/graphics/type_flags.cpp
@@ -241,15 +241,20 @@ void TypeFlags::loadWeaponInfo() {
// Crusader-specific fields:
if (config->get(k + "/ammo_type", val))
- wi->_ammoType = static_cast<uint8>(val);
+ wi->_ammoType = static_cast<uint16>(val);
else
wi->_ammoType = 0;
if (config->get(k + "/sound", val))
- wi->_sound = static_cast<uint8>(val);
+ wi->_sound = static_cast<uint16>(val);
else
wi->_sound = 0;
+ if (config->get(k + "/display_frame", val))
+ wi->_displayFrame = static_cast<uint16>(val);
+ else
+ wi->_displayFrame = 0;
+
assert(wi->_shape < _shapeInfo.size());
_shapeInfo[wi->_shape]._weaponInfo = wi;
}
diff --git a/engines/ultima/ultima8/gumps/cru_inventory_gump.cpp b/engines/ultima/ultima8/gumps/cru_inventory_gump.cpp
index f5ebe5577a..2c4e146915 100644
--- a/engines/ultima/ultima8/gumps/cru_inventory_gump.cpp
+++ b/engines/ultima/ultima8/gumps/cru_inventory_gump.cpp
@@ -36,15 +36,16 @@
namespace Ultima {
namespace Ultima8 {
-static const int INVENTORY_GUMP_SHAPE = 3;
+static const int INVENTORY_GUMP_SHAPE = 5;
DEFINE_RUNTIME_CLASSTYPE_CODE(CruInventoryGump)
-CruInventoryGump::CruInventoryGump() : CruStatGump(), _inventoryShape(nullptr) {
+CruInventoryGump::CruInventoryGump() : CruStatGump(), _inventoryShape(nullptr),
+ _inventoryItemGump(nullptr) {
}
CruInventoryGump::CruInventoryGump(Shape *shape, int x)
- : CruStatGump(shape, x), _inventoryShape(nullptr) {
+ : CruStatGump(shape, x), _inventoryShape(nullptr), _inventoryItemGump(nullptr) {
_frameNum = 0;
}
@@ -65,20 +66,68 @@ void CruInventoryGump::InitGump(Gump *newparent, bool take_focus) {
warning("failed to init stat gump: no inventory shape");
return;
}
+ _inventoryItemGump = new Gump();
+ _inventoryItemGump->InitGump(this, false);
+ // we'll set the shape for this gump later.
}
-void CruInventoryGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
- CruStatGump::PaintThis(surf, lerp_factor, scaled);
+// TODO: This is a bit of a hack.. should be configured
+// in the weapon ini file.
+static uint16 getDisplayFrameForShape(uint16 shapeno) {
+ switch (shapeno) {
+ case 0x351:
+ return 0x0;
+ case 0x4D4:
+ return 0x1;
+ case 0x52D:
+ return 0x2;
+ case 0x52E:
+ return 0x3;
+ case 0x582:
+ return 0x19;
+ case 0x52F:
+ return 0x5;
+ case 0x55F:
+ return 0x18;
+ case 0x530:
+ return 0x7;
+ case 0x3A2:
+ return 0x16;
+ case 0x3A3:
+ return 0x15;
+ case 0x3A4:
+ return 0x17;
+ default:
+ warning("No inventory gump frame for shape %d", shapeno);
+ return 0;
+ }
+}
+void CruInventoryGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
const MainActor *a = getMainActor();
if (!a) {
// avatar gone??
return;
}
- uint16 weapon = a->getDamageType(); // ?? TODO: Where do we store item weapon?
- /*const ShapeFrame *frame = */_inventoryShape->getFrame(weapon);
- // TODO: Paint the current selected item
+ uint16 activeitem = a->getActiveInvItem();
+ if (!activeitem) {
+ _inventoryItemGump->SetShape(0, 0);
+ } else {
+ Item *item = getItem(activeitem);
+ if (!item) {
+ _inventoryItemGump->SetShape(0, 0);
+ } else {
+ uint16 frame = getDisplayFrameForShape(item->getShape());
+ _inventoryItemGump->SetShape(_inventoryShape, frame);
+ _inventoryItemGump->UpdateDimsFromShape();
+ _inventoryItemGump->setRelativePosition(CENTER);
+ // TODO: Add text for count (from q)
+ }
+ }
+
+ // Now that the shape is configured, we can paint.
+ CruStatGump::PaintThis(surf, lerp_factor, scaled);
}
void CruInventoryGump::saveData(Common::WriteStream *ws) {
diff --git a/engines/ultima/ultima8/gumps/cru_inventory_gump.h b/engines/ultima/ultima8/gumps/cru_inventory_gump.h
index 674f464c08..9e64574dc5 100644
--- a/engines/ultima/ultima8/gumps/cru_inventory_gump.h
+++ b/engines/ultima/ultima8/gumps/cru_inventory_gump.h
@@ -50,7 +50,8 @@ public:
void saveData(Common::WriteStream *ws) override;
private:
- const Shape *_inventoryShape;
+ Shape *_inventoryShape;
+ Gump *_inventoryItemGump;
};
} // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/gumps/cru_weapon_gump.cpp b/engines/ultima/ultima8/gumps/cru_weapon_gump.cpp
index bb15a66c6f..a38e339309 100644
--- a/engines/ultima/ultima8/gumps/cru_weapon_gump.cpp
+++ b/engines/ultima/ultima8/gumps/cru_weapon_gump.cpp
@@ -40,12 +40,13 @@ static const int WEAPON_GUMP_SHAPE = 3;
DEFINE_RUNTIME_CLASSTYPE_CODE(CruWeaponGump)
-CruWeaponGump::CruWeaponGump() : CruStatGump(), _weaponShape(nullptr) {
+CruWeaponGump::CruWeaponGump() : CruStatGump(), _weaponShape(nullptr),
+ _weaponGump(nullptr) {
}
CruWeaponGump::CruWeaponGump(Shape *shape, int x)
- : CruStatGump(shape, x), _weaponShape(nullptr) {
+ : CruStatGump(shape, x), _weaponShape(nullptr), _weaponGump(nullptr) {
_frameNum = 0;
}
@@ -66,20 +67,40 @@ void CruWeaponGump::InitGump(Gump *newparent, bool take_focus) {
warning("failed to init stat gump: no weapon shape");
return;
}
+
+ _weaponGump = new Gump();
+ // We will fill out the shape to paint for this later.
+ _weaponGump->InitGump(this, false);
+
}
void CruWeaponGump::PaintThis(RenderSurface *surf, int32 lerp_factor, bool scaled) {
- CruStatGump::PaintThis(surf, lerp_factor, scaled);
-
const MainActor *a = getMainActor();
if (!a) {
// avatar gone??
return;
}
- uint16 weapon = a->getDamageType(); // ?? TODO: Where do we store current weapon?
- /*const ShapeFrame *frame = */_weaponShape->getFrame(weapon);
- // TODO: Paint the current weapon
+ uint16 active = a->getActiveWeapon();
+ if (!active) {
+ _weaponGump->SetShape(0, 0);
+ } else {
+ Item *item = getItem(active);
+ if (!item) {
+ _weaponGump->SetShape(0, 0);
+ } else {
+ WeaponInfo *weaponinfo = item->getShapeInfo()->_weaponInfo;
+ uint16 frameno = 0;
+ if (weaponinfo) {
+ frameno = weaponinfo->_displayFrame;
+ }
+ _weaponGump->SetShape(_weaponShape, frameno);
+ _weaponGump->UpdateDimsFromShape();
+ _weaponGump->setRelativePosition(CENTER);
+ }
+ }
+
+ CruStatGump::PaintThis(surf, lerp_factor, scaled);
}
void CruWeaponGump::saveData(Common::WriteStream *ws) {
diff --git a/engines/ultima/ultima8/gumps/cru_weapon_gump.h b/engines/ultima/ultima8/gumps/cru_weapon_gump.h
index 69b8833d8e..eeb1db6090 100644
--- a/engines/ultima/ultima8/gumps/cru_weapon_gump.h
+++ b/engines/ultima/ultima8/gumps/cru_weapon_gump.h
@@ -50,7 +50,8 @@ public:
void saveData(Common::WriteStream *ws) override;
private:
- const Shape *_weaponShape;
+ Shape *_weaponShape;
+ Gump *_weaponGump;
};
} // End of namespace Ultima8
diff --git a/engines/ultima/ultima8/world/weapon_info.h b/engines/ultima/ultima8/world/weapon_info.h
index ced62755c9..b4c69aed42 100644
--- a/engines/ultima/ultima8/world/weapon_info.h
+++ b/engines/ultima/ultima8/world/weapon_info.h
@@ -42,8 +42,9 @@ struct WeaponInfo {
int _treasureChance;
// Crusader-specific fields:
- uint16 _sound;
- uint16 _ammoType;
+ uint16 _sound; //!< The sound this weapon makes when fired
+ uint16 _ammoType; //!< The type of ammo it uses
+ uint16 _displayFrame; //!< The frame to use in the inventory gump
enum DmgType {
DMG_NORMAL = 0x0001,
Commit: 535867a4e8a86ccefd82732dfbd2410ce831c769
https://github.com/scummvm/scummvm/commit/535867a4e8a86ccefd82732dfbd2410ce831c769
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T16:21:54+09:00
Commit Message:
ULTIMA8: Improve debug messages
Changed paths:
engines/ultima/ultima8/usecode/uc_machine.cpp
diff --git a/engines/ultima/ultima8/usecode/uc_machine.cpp b/engines/ultima/ultima8/usecode/uc_machine.cpp
index 0363c9c21b..44f205384e 100644
--- a/engines/ultima/ultima8/usecode/uc_machine.cpp
+++ b/engines/ultima/ultima8/usecode/uc_machine.cpp
@@ -1743,7 +1743,7 @@ void UCMachine::execProcess(UCProcess *p) {
ui16b, recurse);
} else {
// return error or return empty list?
- perr << "Warning: invalid item passed to area search"
+ perr << "Warning: invalid item " << ui16a << " passed to area search"
<< Std::endl;
}
break;
@@ -1771,7 +1771,7 @@ void UCMachine::execProcess(UCProcess *p) {
scriptsize, recurse);
} else {
// return error or return empty list?
- perr << "Warning: invalid container passed to "
+ perr << "Warning: invalid container "<< ui16b << " passed to "
<< "container search" << Std::endl;
}
break;
Commit: 27dab7b18786ee9b67ad2a3a68dae489acc3c8d8
https://github.com/scummvm/scummvm/commit/27dab7b18786ee9b67ad2a3a68dae489acc3c8d8
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-03T19:40:39+09:00
Commit Message:
ULTIMA8: Add ability to cycle items for Crusader
Changed paths:
engines/ultima/ultima8/meta_engine.cpp
engines/ultima/ultima8/meta_engine.h
engines/ultima/ultima8/misc/debugger.cpp
engines/ultima/ultima8/misc/debugger.h
engines/ultima/ultima8/ultima8.cpp
engines/ultima/ultima8/world/actors/main_actor.cpp
engines/ultima/ultima8/world/actors/main_actor.h
diff --git a/engines/ultima/ultima8/meta_engine.cpp b/engines/ultima/ultima8/meta_engine.cpp
index 45ddf50e64..9b13ccd01c 100644
--- a/engines/ultima/ultima8/meta_engine.cpp
+++ b/engines/ultima/ultima8/meta_engine.cpp
@@ -50,6 +50,7 @@ static const KeybindingRecord KEYS[] = {
{ ACTION_MINIMAP, "MINIMAP", "Toggle Minimap", "MiniMapGump::toggle", nullptr, "m", "JOY_LEFT_TRIGGER" },
{ ACTION_RECALL, "RECALL", "Use Recall", "MainActor::useRecall", nullptr, "r", nullptr },
{ ACTION_INVENTORY, "INVENTORY", "Inventory", "MainActor::useInventory", nullptr, "z", "JOY_LEFT_SHOULDER" },
+ { ACTION_NEXT_WEAPON, "NEXT_WEAPON", "Next Crusader Weapon", "MainActor::nextWeapon", nullptr, "w", nullptr },
{ ACTION_MENU, "MENU", "Game Menu", "MenuGump::showMenu", nullptr, "ESCAPE", "JOY_Y" },
{ ACTION_CLOSE_GUMPS, "CLOSE_GUMPS", "Close Gumps", "GUIApp::closeItemGumps", nullptr, "BACKSPACE", nullptr },
{ ACTION_HIGHLIGHT_ITEMS, "HIGHLIGHT_ITEMS", "Show Highlight Items", "GameMapGump::toggleHighlightItems",
diff --git a/engines/ultima/ultima8/meta_engine.h b/engines/ultima/ultima8/meta_engine.h
index 21d21f6fce..ca00fac08c 100644
--- a/engines/ultima/ultima8/meta_engine.h
+++ b/engines/ultima/ultima8/meta_engine.h
@@ -30,9 +30,9 @@ namespace Ultima8 {
enum KeybindingAction {
ACTION_QUICKSAVE, ACTION_SAVE, ACTION_LOAD, ACTION_BEDROLL, ACTION_COMBAT, ACTION_BACKPACK,
- ACTION_KEYRING, ACTION_MINIMAP, ACTION_RECALL, ACTION_INVENTORY, ACTION_MENU,
- ACTION_CLOSE_GUMPS, ACTION_HIGHLIGHT_ITEMS, ACTION_TOGGLE_TOUCHING, ACTION_JUMP,
- ACTION_TURN_LEFT, ACTION_TURN_RIGHT, ACTION_MOVE_FORWARD, ACTION_MOVE_BACK,
+ ACTION_KEYRING, ACTION_MINIMAP, ACTION_RECALL, ACTION_INVENTORY, ACTION_NEXT_WEAPON,
+ ACTION_MENU, ACTION_CLOSE_GUMPS, ACTION_HIGHLIGHT_ITEMS, ACTION_TOGGLE_TOUCHING,
+ ACTION_JUMP, ACTION_TURN_LEFT, ACTION_TURN_RIGHT, ACTION_MOVE_FORWARD, ACTION_MOVE_BACK,
ACTION_MOVE_UP, ACTION_MOVE_DOWN, ACTION_MOVE_LEFT, ACTION_MOVE_RIGHT,
ACTION_MOVE_RUN, ACTION_MOVE_STEP,
diff --git a/engines/ultima/ultima8/misc/debugger.cpp b/engines/ultima/ultima8/misc/debugger.cpp
index 82100d1c2d..7665ed7973 100644
--- a/engines/ultima/ultima8/misc/debugger.cpp
+++ b/engines/ultima/ultima8/misc/debugger.cpp
@@ -36,6 +36,7 @@
#include "ultima/ultima8/gumps/shape_viewer_gump.h"
#include "ultima/ultima8/gumps/menu_gump.h"
#include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/kernel/core_app.h"
#include "ultima/ultima8/kernel/object_manager.h"
#include "ultima/ultima8/misc/id_man.h"
#include "ultima/ultima8/misc/util.h"
@@ -139,6 +140,7 @@ Debugger::Debugger() : Shared::Debugger() {
registerCmd("MainActor::useRecall", WRAP_METHOD(Debugger, cmdUseRecall));
registerCmd("MainActor::useBedroll", WRAP_METHOD(Debugger, cmdUseBedroll));
registerCmd("MainActor::useKeyring", WRAP_METHOD(Debugger, cmdUseKeyring));
+ registerCmd("MainActor::nextWeapon", WRAP_METHOD(Debugger, cmdNextWeapon));
registerCmd("MainActor::toggleCombat", WRAP_METHOD(Debugger, cmdToggleCombat));
registerCmd("ObjectManager::objectTypes", WRAP_METHOD(Debugger, cmdObjectTypes));
@@ -1083,9 +1085,23 @@ bool Debugger::cmdUseBackpack(int argc, const char **argv) {
return false;
}
MainActor *av = getMainActor();
- Item *backpack = getItem(av->getEquip(7));
- if (backpack)
- backpack->callUsecodeEvent_use();
+ if (GAME_IS_U8) {
+ Item *backpack = getItem(av->getEquip(7));
+ if (backpack)
+ backpack->callUsecodeEvent_use();
+ } else {
+ av->nextInvItem();
+ }
+ return false;
+}
+
+bool Debugger::cmdNextWeapon(int argc, const char **argv) {
+ if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
+ debugPrintf("Can't change weapon: avatarInStasis\n");
+ return false;
+ }
+ MainActor *av = getMainActor();
+ av->nextWeapon();
return false;
}
diff --git a/engines/ultima/ultima8/misc/debugger.h b/engines/ultima/ultima8/misc/debugger.h
index d8ca15a7e9..d202bbab5d 100644
--- a/engines/ultima/ultima8/misc/debugger.h
+++ b/engines/ultima/ultima8/misc/debugger.h
@@ -214,6 +214,7 @@ private:
bool cmdUseRecall(int argc, const char **argv);
bool cmdUseBedroll(int argc, const char **argv);
bool cmdUseKeyring(int argc, const char **argv);
+ bool cmdNextWeapon(int argc, const char **argv);
bool cmdToggleCombat(int argc, const char **argv);
// Object Manager
diff --git a/engines/ultima/ultima8/ultima8.cpp b/engines/ultima/ultima8/ultima8.cpp
index 5f85340efa..364781c734 100644
--- a/engines/ultima/ultima8/ultima8.cpp
+++ b/engines/ultima/ultima8/ultima8.cpp
@@ -142,7 +142,7 @@ Ultima8Engine::Ultima8Engine(OSystem *syst, const Ultima::UltimaGameDescription
_kernel(nullptr), _objectManager(nullptr), _mouse(nullptr), _ucMachine(nullptr),
_screen(nullptr), _fontManager(nullptr), _paletteManager(nullptr), _gameData(nullptr),
_world(nullptr), _desktopGump(nullptr), _gameMapGump(nullptr), _avatarMoverProcess(nullptr),
- _frameSkip(false), _frameLimit(true), _interpolate(true), _animationRate(100),
+ _frameSkip(false), _frameLimit(true), _interpolate(true), _animationRate(10),
_avatarInStasis(false), _paintEditorItems(false), _inversion(0), _painting(false),
_showTouching(false), _timeOffset(0), _hasCheated(false), _cheatsEnabled(false),
_ttfOverrides(false), _audioMixer(0), _scalerGump(nullptr),
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index badeef6ad0..5201470b71 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -611,6 +611,34 @@ void MainActor::addKeycard(int bitno) {
_keycards |= (1 << bitno);
}
+static uint16 getIdOfNextItemInList(const Std::vector<Item *> &items, uint16 current) {
+ const int n = items.size();
+ if (n <= 1)
+ return current;
+
+ int i;
+ for (i = 0; i < n; i++) {
+ if (items[i]->getObjId() == current) {
+ i++;
+ break;
+ }
+ }
+ return items[i % n]->getObjId();
+}
+
+void MainActor::nextWeapon() {
+ Std::vector<Item *> weapons;
+ getItemsWithShapeFamily(weapons, ShapeInfo::SF_CRUWEAPON, true);
+ _activeWeapon = getIdOfNextItemInList(weapons, _activeWeapon);
+}
+
+void MainActor::nextInvItem() {
+ Std::vector<Item *> items;
+ getItemsWithShapeFamily(items, ShapeInfo::SF_CRUINVITEM, true);
+ _activeInvItem = getIdOfNextItemInList(items, _activeInvItem);
+}
+
+
void MainActor::saveData(Common::WriteStream *ws) {
Actor::saveData(ws);
uint8 jt = _justTeleported ? 1 : 0;
diff --git a/engines/ultima/ultima8/world/actors/main_actor.h b/engines/ultima/ultima8/world/actors/main_actor.h
index eb00ccde64..6a96378065 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.h
+++ b/engines/ultima/ultima8/world/actors/main_actor.h
@@ -126,6 +126,12 @@ public:
return _activeInvItem;
}
+ //!< Swap to the next active weapon (in Crusader)
+ void nextWeapon();
+
+ //!< Swap to the next inventory item (in Crusader)
+ void nextInvItem();
+
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
More information about the Scummvm-git-logs
mailing list