[Scummvm-git-logs] scummvm master -> 5b7d73240740a48b1d6441a8c54f738236a11c02
mduggan
mgithub at guarana.org
Wed Jul 8 08:03:34 UTC 2020
This automated email contains information about 8 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
656c57f4ac ULTIMA8: Put in a small hack for crusader elevators
2751b79c35 ULTIMA8: Add functions to pause/resume palette cycle
a34fb53da6 ULTIMA8: Disable some unneeded debug messages
2a1138407f ULTIMA8: Halve frame repeat on crusader to make it feel better
630c63ae09 ULTIMA8: Add use item hotkeys for crusader
3ecc3ae046 ULTIMA8: Add red crosshairs in Crusader
9704171836 ULTIMA8: Implement Crusader GuardProcess (WIP)
5b7d732407 ULTIMA8: Support a few more crusader intrinsics
Commit: 656c57f4ac4e0d62dd7998bdb544a4b3cf396c80
https://github.com/scummvm/scummvm/commit/656c57f4ac4e0d62dd7998bdb544a4b3cf396c80
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Put in a small hack for crusader elevators
Changed paths:
engines/ultima/ultima8/world/actors/animation_tracker.cpp
diff --git a/engines/ultima/ultima8/world/actors/animation_tracker.cpp b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
index 58be2c4579..d5982078e5 100644
--- a/engines/ultima/ultima8/world/actors/animation_tracker.cpp
+++ b/engines/ultima/ultima8/world/actors/animation_tracker.cpp
@@ -343,6 +343,14 @@ bool AnimationTracker::step() {
// It shouldn't be necessary in that case, and may provide a
// worthwhile speed-up.
if ((f._flags & AnimFrame::AFF_ONGROUND) && zd > 8) {
+ if (GAME_IS_CRUSADER && !targetok && support) {
+ // Possibly trying to step onto an elevator platform which stops at a z slightly
+ // above the floor. Re-scan with a small adjustment.
+ // This is a bit of a temporary hack to make navigation possible.. it "hurls"
+ // the avatar sometimes, so it needs fixing properly.
+ tz += 2;
+ }
+
targetok = cm->scanForValidPosition(tx, ty, tz, a, _dir,
true, tx, ty, tz);
Commit: 2751b79c3579bbb6277aece18a1eedef7aa2a3b8
https://github.com/scummvm/scummvm/commit/2751b79c3579bbb6277aece18a1eedef7aa2a3b8
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Add functions to pause/resume palette cycle
Changed paths:
engines/ultima/ultima8/graphics/cycle_process.h
diff --git a/engines/ultima/ultima8/graphics/cycle_process.h b/engines/ultima/ultima8/graphics/cycle_process.h
index 64e7a05137..7f847a5804 100644
--- a/engines/ultima/ultima8/graphics/cycle_process.h
+++ b/engines/ultima/ultima8/graphics/cycle_process.h
@@ -46,6 +46,14 @@ public:
static CycleProcess *get_instance();
+ void pauseCycle() {
+ _running = 0;
+ }
+
+ void resumeCycle() {
+ _running = 1;
+ }
+
bool loadData(Common::ReadStream *rs, uint32 version);
void saveData(Common::WriteStream *ws) override;
};
Commit: a34fb53da671bf3139ff8f804d738035c9792921
https://github.com/scummvm/scummvm/commit/a34fb53da671bf3139ff8f804d738035c9792921
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Disable some unneeded debug messages
Changed paths:
engines/ultima/ultima8/world/item.cpp
engines/ultima/ultima8/world/map.cpp
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 051dfb5300..c9d29dc17c 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -2747,7 +2747,7 @@ uint32 Item::I_push(const uint8 *args, unsigned int /*argsize*/) {
if (!item)
return 0;
- #if 1
+ #if 0
perr << "Pushing item to ethereal void: " << item->getShape() << "," << item->getFrame() << Std::endl;
#endif
diff --git a/engines/ultima/ultima8/world/map.cpp b/engines/ultima/ultima8/world/map.cpp
index deeb884224..e20651287f 100644
--- a/engines/ultima/ultima8/world/map.cpp
+++ b/engines/ultima/ultima8/world/map.cpp
@@ -263,10 +263,6 @@ void Map::loadFixedFormatObjects(Std::list<Item *> &itemlist,
if (info->_family > 10) {
//warning("Created fixed item unknown family %d, shape (%d, %d) at (%d, %d, %d)", info->_family, shape, frame, x, y, z);
}
- if (shape == 0x90D) {
- warning("Created MISS1EGG item unknown family %d, shape (%d, %d) at (%d, %d, %d) q:%d", info->_family, shape, frame, x, y, z, quality);
-
- }
}
item->setLocation(x, y, z);
Commit: 2a1138407f41bb8c42ac6189e54b2ca334ec4c60
https://github.com/scummvm/scummvm/commit/2a1138407f41bb8c42ac6189e54b2ca334ec4c60
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Halve frame repeat on crusader to make it feel better
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 2c97bda6df..2e780647a1 100644
--- a/engines/ultima/ultima8/graphics/anim_dat.cpp
+++ b/engines/ultima/ultima8/graphics/anim_dat.cpp
@@ -117,8 +117,14 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
_anims.resize(2048);
unsigned int actioncount = 64;
- if (GAME_IS_CRUSADER)
+ unsigned int frame_repeat_factor = 1;
+
+ if (GAME_IS_CRUSADER) {
actioncount = 256;
+ // TODO: this is based on making the game "feel" right, not disassembly.
+ // Should confirm if this is the right way to do it.
+ frame_repeat_factor = 2;
+ }
for (unsigned int shape = 0; shape < _anims.size(); shape++) {
rs->seek(4 * shape);
@@ -152,7 +158,7 @@ void AnimDat::load(Common::SeekableReadStream *rs) {
uint32 actionsize = rs->readByte();
a->_actions[action]->_size = actionsize;
a->_actions[action]->_flags = rs->readByte();
- a->_actions[action]->_frameRepeat = rs->readByte();
+ a->_actions[action]->_frameRepeat = rs->readByte() / frame_repeat_factor;
a->_actions[action]->_flags |= rs->readByte() << 8;
unsigned int dirCount = 8;
Commit: 630c63ae0910f7e41299ef2f2b685b9035638305
https://github.com/scummvm/scummvm/commit/630c63ae0910f7e41299ef2f2b685b9035638305
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Add use item hotkeys 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/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 9b13ccd01c..86bc186388 100644
--- a/engines/ultima/ultima8/meta_engine.cpp
+++ b/engines/ultima/ultima8/meta_engine.cpp
@@ -51,6 +51,9 @@ static const KeybindingRecord KEYS[] = {
{ 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_USE_INVENTORY, "USE_INVENTORY", "Use Cru. Inventroy Item", "MainActor::useInventoryItem", nullptr, "u", nullptr },
+ { ACTION_SELECT_ITEMS, "SELECT_ITEM", "Selete Cru. Item", "MainActor::startSelection", nullptr, "s", nullptr },
+ { ACTION_USE_MEDIKIT, "USE_MEDIKIT", "Use Medical Kit", "MainActor::useMedikit", nullptr, "M", 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 ca00fac08c..b54364ec65 100644
--- a/engines/ultima/ultima8/meta_engine.h
+++ b/engines/ultima/ultima8/meta_engine.h
@@ -31,6 +31,7 @@ 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_NEXT_WEAPON,
+ ACTION_USE_INVENTORY, ACTION_USE_MEDIKIT, ACTION_SELECT_ITEMS,
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,
diff --git a/engines/ultima/ultima8/misc/debugger.cpp b/engines/ultima/ultima8/misc/debugger.cpp
index 7665ed7973..954232b9e3 100644
--- a/engines/ultima/ultima8/misc/debugger.cpp
+++ b/engines/ultima/ultima8/misc/debugger.cpp
@@ -141,6 +141,8 @@ Debugger::Debugger() : Shared::Debugger() {
registerCmd("MainActor::useBedroll", WRAP_METHOD(Debugger, cmdUseBedroll));
registerCmd("MainActor::useKeyring", WRAP_METHOD(Debugger, cmdUseKeyring));
registerCmd("MainActor::nextWeapon", WRAP_METHOD(Debugger, cmdNextWeapon));
+ registerCmd("MainActor::useInventoryItem", WRAP_METHOD(Debugger, cmdUseInventoryItem));
+ registerCmd("MainActor::useMedikit", WRAP_METHOD(Debugger, cmdUseMedikit));
registerCmd("MainActor::toggleCombat", WRAP_METHOD(Debugger, cmdToggleCombat));
registerCmd("ObjectManager::objectTypes", WRAP_METHOD(Debugger, cmdObjectTypes));
@@ -1105,6 +1107,32 @@ bool Debugger::cmdNextWeapon(int argc, const char **argv) {
return false;
}
+bool Debugger::cmdUseInventoryItem(int argc, const char **argv) {
+ if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
+ debugPrintf("Can't use active inventory item: avatarInStasis\n");
+ return false;
+ }
+ MainActor *av = getMainActor();
+ ObjId activeitemid = av->getActiveInvItem();
+ if (activeitemid) {
+ Item *item = getItem(activeitemid);
+ if (item) {
+ av->useInventoryItem(item);
+ }
+ }
+ return false;
+}
+
+bool Debugger::cmdUseMedikit(int argc, const char **argv) {
+ if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
+ debugPrintf("Can't use medikit: avatarInStasis\n");
+ return false;
+ }
+ MainActor *av = getMainActor();
+ av->useInventoryItem(0x351);
+ return false;
+}
+
bool Debugger::cmdUseInventory(int argc, const char **argv) {
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
debugPrintf("Can't use inventory: avatarInStasis\n");
diff --git a/engines/ultima/ultima8/misc/debugger.h b/engines/ultima/ultima8/misc/debugger.h
index d202bbab5d..b7c4e962e4 100644
--- a/engines/ultima/ultima8/misc/debugger.h
+++ b/engines/ultima/ultima8/misc/debugger.h
@@ -216,6 +216,8 @@ private:
bool cmdUseKeyring(int argc, const char **argv);
bool cmdNextWeapon(int argc, const char **argv);
bool cmdToggleCombat(int argc, const char **argv);
+ bool cmdUseInventoryItem(int argc, const char **argv);
+ bool cmdUseMedikit(int argc, const char **argv);
// Object Manager
bool cmdObjectTypes(int argc, const char **argv);
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index f170fab4be..e75a2a904b 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -563,7 +563,12 @@ void MainActor::getWeaponOverlay(const WeaponOverlayFrame *&frame_, uint32 &shap
if (!isInCombat() && _lastAnim != Animation::unreadyWeapon) return;
- ObjId weaponid = getEquip(ShapeInfo::SE_WEAPON);
+ ObjId weaponid;
+ if (GAME_IS_U8)
+ weaponid = getEquip(ShapeInfo::SE_WEAPON);
+ else
+ weaponid = getActiveWeapon();
+
Item *weapon = getItem(weaponid);
if (!weapon) return;
@@ -610,8 +615,10 @@ void MainActor::addKeycard(int bitno) {
static uint16 getIdOfNextItemInList(const Std::vector<Item *> &items, uint16 current) {
const int n = items.size();
- if (n <= 1)
- return current;
+ if (n == 0)
+ return 0;
+ if (n == 1)
+ return items[0]->getObjId();
int i;
for (i = 0; i < n; i++) {
@@ -797,13 +804,38 @@ uint32 MainActor::I_addItemCru(const uint8 *args,
}
void MainActor::useInventoryItem(uint32 shapenum) {
+ Item *item = getFirstItemWithShape(shapenum, true);
+ useInventoryItem(item);
+}
+
+void MainActor::useInventoryItem(Item *item) {
+ if (!item)
+ return;
if (Ultima8Engine::get_instance()->isAvatarInStasis()) {
pout << "Can't use item: avatarInStasis" << Std::endl;
return;
}
- Item *item = this->getFirstItemWithShape(shapenum, true);
- if (item)
- item->callUsecodeEvent_use();
+ const int32 shapenum = item->getShape();
+ if (shapenum == 0x4ed && GAME_IS_CRUSADER) {
+ // Do nothing for Credits
+ return;
+ }
+ item->callUsecodeEvent_use();
+
+ if (GAME_IS_CRUSADER && (shapenum != 0x4d4 && shapenum != 0x52d &&
+ shapenum != 0x530 && shapenum != 0x52f &&
+ shapenum != 0x52e)) {
+ uint16 q = item->getQuality();
+ item->setQuality(q - 1);
+ item->callUsecodeEvent_combine();
+ q = item->getQuality();
+ if (q == 0) {
+ const ObjId id = item->getObjId();
+ item->destroy();
+ if (id == _activeInvItem)
+ nextInvItem();
+ }
+ }
}
} // 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 6a96378065..98bfd99b38 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.h
+++ b/engines/ultima/ultima8/world/actors/main_actor.h
@@ -154,6 +154,7 @@ public:
protected:
void useInventoryItem(uint32 shapenum);
+ void useInventoryItem(Item *item);
bool _justTeleported;
Commit: 3ecc3ae04647126bb223e759e1be461930301404
https://github.com/scummvm/scummvm/commit/3ecc3ae04647126bb223e759e1be461930301404
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Add red crosshairs in Crusader
Changed paths:
A engines/ultima/ultima8/world/crosshair_process.cpp
A engines/ultima/ultima8/world/crosshair_process.h
engines/ultima/module.mk
engines/ultima/ultima8/ultima8.cpp
diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index b112de5542..5cb8889aef 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -526,6 +526,7 @@ MODULE_OBJS := \
ultima8/world/camera_process.o \
ultima8/world/container.o \
ultima8/world/create_item_process.o \
+ ultima8/world/crosshair_process.o \
ultima8/world/current_map.o \
ultima8/world/destroy_item_process.o \
ultima8/world/egg.o \
diff --git a/engines/ultima/ultima8/ultima8.cpp b/engines/ultima/ultima8/ultima8.cpp
index acd40725fa..1ec9fb3a88 100644
--- a/engines/ultima/ultima8/ultima8.cpp
+++ b/engines/ultima/ultima8/ultima8.cpp
@@ -93,6 +93,7 @@
#include "ultima/ultima8/world/item_factory.h"
#include "ultima/ultima8/world/split_item_process.h"
#include "ultima/ultima8/world/target_reticle_process.h"
+#include "ultima/ultima8/world/crosshair_process.h"
#include "ultima/ultima8/world/actors/pathfinder_process.h"
#include "ultima/ultima8/world/actors/avatar_mover_process.h"
#include "ultima/ultima8/world/actors/resurrection_process.h"
@@ -422,16 +423,18 @@ void Ultima8Engine::shutdownGame(bool reloading) {
_desktopGump->InitGump(0);
_desktopGump->MakeFocus();
- debugN(MM_INFO, "Creating _scalerGump...\n");
- _scalerGump = new ScalerGump(0, 0, dims.w, dims.h);
- _scalerGump->InitGump(0);
+ if (GAME_IS_U8) {
+ debugN(MM_INFO, "Creating _scalerGump...\n");
+ _scalerGump = new ScalerGump(0, 0, dims.w, dims.h);
+ _scalerGump->InitGump(0);
- Rect scaled_dims;
- _scalerGump->GetDims(scaled_dims);
+ Rect scaled_dims;
+ _scalerGump->GetDims(scaled_dims);
- debugN(MM_INFO, "Creating Inverter...\n");
- _inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
- _inverterGump->InitGump(0);
+ debugN(MM_INFO, "Creating Inverter...\n");
+ _inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
+ _inverterGump->InitGump(0);
+ }
}
}
@@ -655,14 +658,16 @@ void Ultima8Engine::GraphicSysInit() {
_desktopGump->InitGump(0);
_desktopGump->MakeFocus();
- _scalerGump = new ScalerGump(0, 0, width, height);
- _scalerGump->InitGump(0);
+ if (GAME_IS_U8) {
+ _scalerGump = new ScalerGump(0, 0, width, height);
+ _scalerGump->InitGump(0);
- Rect scaled_dims;
- _scalerGump->GetDims(scaled_dims);
+ Rect scaled_dims;
+ _scalerGump->GetDims(scaled_dims);
- _inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
- _inverterGump->InitGump(0);
+ _inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
+ _inverterGump->InitGump(0);
+ }
_screen = new_screen;
@@ -1047,28 +1052,35 @@ void Ultima8Engine::setupCoreGumps() {
_desktopGump->InitGump(0);
_desktopGump->MakeFocus();
- debugN(MM_INFO, "Creating _scalerGump...\n");
- _scalerGump = new ScalerGump(0, 0, dims.w, dims.h);
- _scalerGump->InitGump(0);
+ if (GAME_IS_U8) {
+ debugN(MM_INFO, "Creating _scalerGump...\n");
+ _scalerGump = new ScalerGump(0, 0, dims.w, dims.h);
+ _scalerGump->InitGump(0);
+
+ Rect scaled_dims;
+ _scalerGump->GetDims(scaled_dims);
- Rect scaled_dims;
- _scalerGump->GetDims(scaled_dims);
+ debugN(MM_INFO, "Creating Inverter...\n");
+ _inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
+ _inverterGump->InitGump(0);
- debugN(MM_INFO, "Creating Inverter...\n");
- _inverterGump = new InverterGump(0, 0, scaled_dims.w, scaled_dims.h);
- _inverterGump->InitGump(0);
+ debugN(MM_INFO, "Creating GameMapGump...\n");
+ _gameMapGump = new GameMapGump(0, 0, scaled_dims.w, scaled_dims.h);
+ _gameMapGump->InitGump(0);
+ } else {
+ _gameMapGump = new GameMapGump(0, 0, dims.w, dims.h);
+ _gameMapGump->InitGump(0);
+ }
- debugN(MM_INFO, "Creating GameMapGump...\n");
- _gameMapGump = new GameMapGump(0, 0, scaled_dims.w, scaled_dims.h);
- _gameMapGump->InitGump(0);
// TODO: clean this up
- assert(_desktopGump->getObjId() == 256);
- assert(_scalerGump->getObjId() == 257);
- assert(_inverterGump->getObjId() == 258);
- assert(_gameMapGump->getObjId() == 259);
-
+ if (GAME_IS_U8) {
+ assert(_desktopGump->getObjId() == 256);
+ assert(_scalerGump->getObjId() == 257);
+ assert(_inverterGump->getObjId() == 258);
+ assert(_gameMapGump->getObjId() == 259);
+ }
for (uint16 i = 261; i < 384; ++i)
_objectManager->reserveObjId(i);
@@ -1116,6 +1128,7 @@ bool Ultima8Engine::newGame(int saveSlot) {
if (GAME_IS_CRUSADER) {
_kernel->addProcess(new TargetReticleProcess());
+ _kernel->addProcess(new CrosshairProcess());
_kernel->addProcess(new CycleProcess());
}
@@ -1311,18 +1324,20 @@ void Ultima8Engine::addGump(Gump *gump) {
//(_ttfOverrides && (dynamic_cast<BarkGump *>(gump) ||
// dynamic_cast<AskGump *>(gump)))
) {
- // pout << "adding to desktopgump: "; gump->dumpInfo();
_desktopGump->AddChild(gump);
} else if (dynamic_cast<GameMapGump *>(gump)) {
- // pout << "adding to invertergump: "; gump->dumpInfo();
- _inverterGump->AddChild(gump);
+ if (GAME_IS_U8)
+ _inverterGump->AddChild(gump);
+ else
+ _desktopGump->AddChild(gump);
} else if (dynamic_cast<InverterGump *>(gump)) {
- // pout << "adding to _scalerGump: "; gump->dumpInfo();
_scalerGump->AddChild(gump);
} else if (dynamic_cast<DesktopGump *>(gump)) {
} else {
- // pout << "adding to _scalerGump: "; gump->dumpInfo();
- _scalerGump->AddChild(gump);
+ if (GAME_IS_U8)
+ _scalerGump->AddChild(gump);
+ else
+ _desktopGump->AddChild(gump);
}
}
diff --git a/engines/ultima/ultima8/world/crosshair_process.cpp b/engines/ultima/ultima8/world/crosshair_process.cpp
new file mode 100644
index 0000000000..13c6878ce9
--- /dev/null
+++ b/engines/ultima/ultima8/world/crosshair_process.cpp
@@ -0,0 +1,96 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima8/misc/pent_include.h"
+
+#include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/world/actors/main_actor.h"
+#include "ultima/ultima8/world/crosshair_process.h"
+#include "ultima/ultima8/world/item.h"
+#include "ultima/ultima8/world/world.h"
+#include "ultima/ultima8/world/item_factory.h"
+#include "ultima/ultima8/world/get_object.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+// p_dynamic_cast stuff
+DEFINE_RUNTIME_CLASSTYPE_CODE(CrosshairProcess)
+
+const uint32 CROSSHAIR_SHAPE = 0x4CC;
+const float CROSSHAIR_DIST = 400.0;
+
+CrosshairProcess::CrosshairProcess() : Process() {
+}
+
+void CrosshairProcess::run() {
+ Kernel *kernel = Kernel::get_instance();
+ assert(kernel);
+ MainActor *mainactor = getMainActor();
+ int32 cx, cy, cz, ax, ay, az;
+ mainactor->getCentre(cx, cy, cz);
+ mainactor->getFootpadWorld(ax, ay, az);
+ // TODO: Make a fine adjustment for avatar height (eg, when crouching)
+ // for now just put it at 3/4 avatar height which is about right.
+ cz += az / 4;
+ // TODO: Get the fine angle of the avatar once that is implemented.
+ uint16 dir = (mainactor->getDir() + 2) % 8;
+ // Dir is 0~7, convert to 0~15/8*pi
+ float angle = (3.14 * dir / 4.0);
+ float xoff = CROSSHAIR_DIST * cos(angle);
+ float yoff = CROSSHAIR_DIST * sin(angle);
+ cx -= static_cast<int32>(xoff);
+ cy -= static_cast<int32>(yoff);
+
+ if (mainactor->isInCombat()) {
+ Item *item;
+ if (_itemNum) {
+ item = getItem(_itemNum);
+ } else {
+ // Create a new sprite
+ item = ItemFactory::createItem(CROSSHAIR_SHAPE, 0, 0, Item::FLG_DISPOSABLE,
+ 0, 0, Item::EXT_SPRITE, true);
+ setItemNum(item->getObjId());
+ }
+ assert(item);
+ item->move(cx, cy, cz);
+ } else {
+ if (_itemNum) {
+ Item *item = getItem(_itemNum);
+ assert(item);
+ item->destroy();
+ _itemNum = 0;
+ }
+ }
+
+}
+
+void CrosshairProcess::saveData(Common::WriteStream *ws) {
+ Process::saveData(ws);
+}
+
+bool CrosshairProcess::loadData(Common::ReadStream *rs, uint32 version) {
+ return Process::loadData(rs, version);
+}
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/crosshair_process.h b/engines/ultima/ultima8/world/crosshair_process.h
new file mode 100644
index 0000000000..d06ef09b41
--- /dev/null
+++ b/engines/ultima/ultima8/world/crosshair_process.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ULTIMA8_WORLD_CROSSHAIRPROCESS_H
+#define ULTIMA8_WORLD_CROSSHAIRPROCESS_H
+
+#include "ultima/ultima8/kernel/process.h"
+#include "ultima/ultima8/misc/p_dynamic_cast.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+/**
+ * A process to update the location of the small red crosshairs in Crusader.
+ * The crosshairs are just based on avatar angle and don't move with the
+ * environment, which makes them simpler than the dynamic target reticle.
+ */
+class CrosshairProcess : public Process {
+public:
+ CrosshairProcess();
+
+ // p_dynamic_cast stuff
+ ENABLE_RUNTIME_CLASSTYPE()
+
+ void run() override;
+
+ bool loadData(Common::ReadStream *rs, uint32 version);
+ void saveData(Common::WriteStream *ws) override;
+};
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
+
+#endif
Commit: 97041718365b273b65c5f99b6685eef5486c9943
https://github.com/scummvm/scummvm/commit/97041718365b273b65c5f99b6685eef5486c9943
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Implement Crusader GuardProcess (WIP)
Changed paths:
A engines/ultima/ultima8/world/actors/guard_process.cpp
A engines/ultima/ultima8/world/actors/guard_process.h
engines/ultima/module.mk
diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index 5cb8889aef..a262910e97 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -563,6 +563,7 @@ MODULE_OBJS := \
ultima8/world/actors/combat_dat.o \
ultima8/world/actors/combat_process.o \
ultima8/world/actors/grant_peace_process.o \
+ ultima8/world/actors/guard_process.o \
ultima8/world/actors/heal_process.o \
ultima8/world/actors/loiter_process.o \
ultima8/world/actors/main_actor.o \
diff --git a/engines/ultima/ultima8/world/actors/guard_process.cpp b/engines/ultima/ultima8/world/actors/guard_process.cpp
new file mode 100644
index 0000000000..6ab51b2962
--- /dev/null
+++ b/engines/ultima/ultima8/world/actors/guard_process.cpp
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "ultima/ultima8/misc/pent_include.h"
+#include "ultima/ultima8/world/actors/guard_process.h"
+#include "ultima/ultima8/world/actors/actor.h"
+#include "ultima/ultima8/world/actors/main_actor.h"
+#include "ultima/ultima8/world/actors/animation.h"
+#include "ultima/ultima8/world/actors/actor_anim_process.h"
+#include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/kernel/delay_process.h"
+#include "ultima/ultima8/kernel/core_app.h"
+#include "ultima/ultima8/world/get_object.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+// p_dynamic_cast stuff
+DEFINE_RUNTIME_CLASSTYPE_CODE(GuardProcess)
+
+GuardProcess::GuardProcess() : Process() {
+}
+
+GuardProcess::GuardProcess(Actor *actor) {
+ assert(actor);
+ _itemNum = actor->getObjId();
+ _type = 0x255;
+}
+
+void GuardProcess::run() {
+ Actor *a = getActor(_itemNum);
+ if (!a || a->isDead()) {
+ // dead?
+ terminate();
+ return;
+ }
+
+ int activeanim = Kernel::get_instance()->getNumProcesses(a->getObjId(), ActorAnimProcess::ACTOR_ANIM_PROC_TYPE);
+ if (activeanim > 0)
+ return;
+
+ Actor *mainactor = getMainActor();
+ if (!mainactor)
+ return;
+
+ int range = a->getRangeIfVisible(*mainactor);
+ if (!range) {
+ if (getRandom() % 2) {
+ DelayProcess *dp = new DelayProcess(30 * (1 + (getRandom() % 3)));
+ Kernel::get_instance()->addProcess(dp);
+ waitFor(dp);
+ return;
+ } else {
+ // TODO: What animation happens in here?
+ //a->tryAnim(0x1e, a->getDir());
+ }
+ return;
+ }
+
+ a->setActivity(5);
+}
+
+void GuardProcess::saveData(Common::WriteStream *ws) {
+ Process::saveData(ws);
+}
+
+bool GuardProcess::loadData(Common::ReadStream *rs, uint32 version) {
+ return Process::loadData(rs, version);
+}
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/actors/guard_process.h b/engines/ultima/ultima8/world/actors/guard_process.h
new file mode 100644
index 0000000000..121b375aba
--- /dev/null
+++ b/engines/ultima/ultima8/world/actors/guard_process.h
@@ -0,0 +1,50 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef WORLD_ACTORS_GUARDPROCESS_H
+#define WORLD_ACTORS_GUARDPROCESS_H
+
+#include "ultima/ultima8/kernel/process.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+class Actor;
+
+class GuardProcess : public Process {
+public:
+ GuardProcess();
+ GuardProcess(Actor *actor);
+
+ // p_dynamic_cast stuff
+ ENABLE_RUNTIME_CLASSTYPE()
+
+ void run() override;
+
+ bool loadData(Common::ReadStream *rs, uint32 version);
+ void saveData(Common::WriteStream *ws) override;
+};
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
+
+#endif
Commit: 5b7d73240740a48b1d6441a8c54f738236a11c02
https://github.com/scummvm/scummvm/commit/5b7d73240740a48b1d6441a8c54f738236a11c02
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-07-08T17:03:02+09:00
Commit Message:
ULTIMA8: Support a few more crusader intrinsics
Changed paths:
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
engines/ultima/ultima8/usecode/remorse_intrinsics.h
engines/ultima/ultima8/world/actors/actor.cpp
engines/ultima/ultima8/world/actors/actor.h
engines/ultima/ultima8/world/actors/main_actor.cpp
engines/ultima/ultima8/world/actors/main_actor.h
engines/ultima/ultima8/world/world.cpp
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 7efddb0849..436ce6d5d0 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -78,7 +78,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"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 *)", // Maybe get HP? Called from ANDROID::calledFromAnim, goes to NPCDEATH
+ "int16 Actor::I_GetNPCDataField0x63_00B(Actor *)", // Some unknown value set for NPCs based on Q of egg.
"void Ultima8Engine::I_setAvatarInStasis(int)",
"byte Item::I_getDirToItem(Item *, itemno)", // based on disasm
"int16 Actor::I_turnToward(Actor *, direction, unk)", // TODO: work out what unk is
@@ -152,13 +152,13 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"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
// 0050
- "int16 I_GetNPCDataField0x2_050(Actor *)",
+ "int16 Actor::I_getCurrentActivityNo(Actor *)",
"void Actor::I_clrInCombat(Actor *)", // probably, based on disasm.
"void Actor::I_setDefaultActivity0(Actor *, int)",
"void Actor::I_setDefaultActivity1(Actor *, int)",
"void Actor::I_setDefaultActivity2(Actor *, int)",
"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
- "void Intrinsic056(int itemno)", // Maybe set new target? TODO: check usecode to understand this.
+ "void I_setControlledNPCTo(int itemno)", // when you take over the Thermatron etc.
"int16 Item::I_getSurfaceWeight(Item *)",
"byte Item::I_isCentreOn(Item *, uint16 other)",
"void Item::I_setFrame(Item *, frame)", // based on same coff as 002
@@ -301,7 +301,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
"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 *)",
+ "int16 Actor::I_getLastActivityNo(Actor *)",
"void Actor::I_setCombatTactic(Actor *, int)",
"int16 Actor::I_getEquip(6 bytes)", // based on disasm
// 00E0
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index ec935dd093..ed987f054e 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -46,7 +46,7 @@ Intrinsic RemorseIntrinsics[] = {
Actor::I_isNPC, // byte Intrinsic008(Item *)
Item::I_getZ, // byte Intrinsic009(Item *)
Item::I_destroy, // void Intrinsic00A(Item *)
- 0, // get something npcdata, maybe HP void Intrinsic00B(4 bytes)
+ Actor::I_getUnkByte, // get something about npcdata - struct byte 0x63 (99)
Ultima8Engine::I_setAvatarInStasis, // void Intrinsic00C(2 bytes)
Item::I_getDirToItem, // byte Intrinsic00D(6 bytes)
0, // TODO: Actor::I_turnToward(Actor *, direction, unk)
@@ -120,7 +120,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_isOn,
Item::I_getQHi, // based on same coff set as 026
// 0x050
- 0, // void Intrinsic050(4 bytes)
+ 0, // TODO: int16 Actor::I_getCurrentActivityNo // void Intrinsic050(4 bytes)
Actor::I_clrInCombat, // void Intrinsic051(4 bytes)
Actor::I_setDefaultActivity0, // void Intrinsic052(6 bytes)
Actor::I_setDefaultActivity1, // void Intrinsic053(6 bytes)
@@ -186,7 +186,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_setBroken, // void Intrinsic08C(4 bytes)
Item::I_hurl, // void Intrinsic08D(12 bytes)
Item::I_getNpcNum, // based on same coff as 102 (-> variable name in TRIGGER::ordinal21)
- 0, // TODO: PaletteFaderProcess::I_setPalToAllBlack
+ 0, // TODO: PaletteFaderProcess::I_setPalToAllBlack - should also resume cycle process.
// 0x090
MusicProcess::I_musicStop, // void Intrinsic090(void)
0, // void Intrinsic091(void)
@@ -198,7 +198,7 @@ Intrinsic RemorseIntrinsics[] = {
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),
+ 0, // TODO: PaletteFaderProcess::I_stopFadesAndResetToGamePal(void), - should also stop cycle process.
PaletteFaderProcess::I_fadeFromBlack, // fade to game pal with number of steps
0, // TODO: PaletteFaderProcess::I_fadeFromBlackWithParam
PaletteFaderProcess::I_fadeToBlack, // fade to black with number of steps
@@ -269,7 +269,7 @@ Intrinsic RemorseIntrinsics[] = {
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)
+ 0, // TODO: Actor::I_getLastActivityNo void Intrinsic0DD(4 bytes)
Actor::I_setCombatTactic, // void Intrinsic0DE(6 bytes)
Actor::I_getEquip, // void Intrinsic0DF(6 bytes)
// 0x0E0
@@ -279,12 +279,12 @@ Intrinsic RemorseIntrinsics[] = {
Actor::I_getDefaultActivity2, // void Intrinsic0E3(4 bytes)
Actor::I_getLastAnimSet, // void Intrinsic0E4(4 bytes)
0, // TODO: Actor::I_attack(Actor *, uint16 target) (implement me)
- 0, // void Intrinsic0E6(6 bytes)
+ Actor::I_setUnkByte, // void Intrinsic0E6(6 bytes)
Actor::I_setDead,
Item::I_cast, // void Intrinsic0E8(6 bytes)
Item::I_andStatus, // void Intrinsic0E9(6 bytes)
Item::I_getQLo, // based on same coff set as 02B
- 0, // void Intrinsic0EB(void)
+ MainActor::I_getNumberOfCredits, // void Intrinsic0EB(void)
Item::I_popToEnd,
Item::I_popToContainer,
BatteryChargerProcess::I_create,
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index c5e83b43ba..0865328c23 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -66,9 +66,10 @@ static const unsigned int BACKPACK_SHAPE = 529;
DEFINE_RUNTIME_CLASSTYPE_CODE(Actor)
Actor::Actor() : _strength(0), _dexterity(0), _intelligence(0),
- _hitPoints(0), _mana(0), _alignment(0), _enemyAlignment(0),
- _lastAnim(Animation::stand), _animFrame(0), _direction(0),
- _fallStart(0), _unk0C(0), _actorFlags(0), _combatTactic(0) {
+ _hitPoints(0), _mana(0), _alignment(0), _enemyAlignment(0),
+ _lastAnim(Animation::stand), _animFrame(0), _direction(0),
+ _fallStart(0), _unkByte(0), _actorFlags(0), _combatTactic(0),
+ _homeX(0), _homeY(0), _homeZ(0) {
_defaultActivity[0] = 0;
_defaultActivity[1] = 0;
_defaultActivity[2] = 0;
@@ -674,6 +675,18 @@ uint16 Actor::getDefaultActivity(int no) const {
return _defaultActivity[no];
}
+void Actor::setHomePosition(int32 x, int32 y, int32 z) {
+ _homeX = x;
+ _homeY = y;
+ _homeZ = z;
+}
+
+void Actor::getHomePosition(int32 &x, int32 &y, int32 &z) const {
+ x = _homeX;
+ y = _homeY;
+ z = _homeZ;
+}
+
void Actor::receiveHit(uint16 other, int dir, int damage, uint16 damage_type) {
if (isDead())
return; // already dead, so don't bother
@@ -1110,11 +1123,16 @@ int32 Actor::collideMove(int32 x, int32 y, int32 z, bool teleport, bool force,
return result;
}
+static Std::set<uint16> _notifiedItems;
+
void Actor::notifyNearbyItems() {
-/*
+ /*
TODO: This is not right - maybe we want to trigger each item only when it gets close,
then reset the status after it moves away? Need to dig into the assembly more.
-
+
+ For now this is a temporary hack to trigger some usecode events so we can
+ debug more of the game.
+ */
UCList uclist(2);
LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
CurrentMap *currentmap = World::get_instance()->getCurrentMap();
@@ -1122,8 +1140,11 @@ void Actor::notifyNearbyItems() {
for (unsigned int i = 0; i < uclist.getSize(); ++i) {
Item *item = getItem(uclist.getuint16(i));
+ if (_notifiedItems.find(item->getObjId()) != _notifiedItems.end())
+ continue;
item->callUsecodeEvent_npcNearby(_objId);
- }*/
+ _notifiedItems.insert(item->getObjId());
+ }
}
bool Actor::areEnemiesNear() {
@@ -1210,13 +1231,16 @@ void Actor::saveData(Common::WriteStream *ws) {
ws->writeUint16LE(_direction);
ws->writeUint32LE(_fallStart);
ws->writeUint32LE(_actorFlags);
- ws->writeByte(_unk0C);
+ ws->writeByte(_unkByte);
if (GAME_IS_CRUSADER) {
ws->writeUint16LE(_defaultActivity[0]);
ws->writeUint16LE(_defaultActivity[1]);
ws->writeUint16LE(_defaultActivity[2]);
ws->writeUint16LE(_combatTactic);
+ ws->writeUint32LE(_homeX);
+ ws->writeUint32LE(_homeY);
+ ws->writeUint32LE(_homeZ);
}
}
@@ -1235,13 +1259,16 @@ bool Actor::loadData(Common::ReadStream *rs, uint32 version) {
_direction = rs->readUint16LE();
_fallStart = rs->readUint32LE();
_actorFlags = rs->readUint32LE();
- _unk0C = rs->readByte();
+ _unkByte = rs->readByte();
if (GAME_IS_CRUSADER) {
_defaultActivity[0] = rs->readUint16LE();
_defaultActivity[1] = rs->readUint16LE();
_defaultActivity[2] = rs->readUint16LE();
_combatTactic = rs->readUint16LE();
+ _homeX = rs->readUint32LE();
+ _homeY = rs->readUint32LE();
+ _homeZ = rs->readUint32LE();
}
return true;
@@ -1774,24 +1801,42 @@ uint32 Actor::I_createActorCru(const uint8 *args, unsigned int /*argsize*/) {
newactor->setDefaultActivity(1, item->getQuality() >> 8);
newactor->setDefaultActivity(2, other->getMapNum());
- // TODO: once I know what these fields are...
- /*
- newactor->setField0x5c(0);
- newactor->setField0x5e(x, y);
- newactor->setField0x12(item->getNpcNum() >> 4);
- newactor->setField0x63(item->getQuality() & 0xff);
+ newactor->setUnkByte(item->getQuality() & 0xff);
- uint16 wpnType = npcData->getWpnType();
- if (gameDifficulty == 4) {
- wpnType = randomlyGetHigherWeaponType(shape, wpntype);
- }
+ uint16 wpntype = npcData->getWpnType();
+ Item *weapon = ItemFactory::createItem(wpntype, 0, 0, 0, 0, newactor->getMapNum(), 0, true);
+ /* TODO:
+ if (gameDifficulty == 4) {
+ wpntype = randomlyGetHigherWeaponType(shape, wpntype);
+ }*/
+ // TODO: should this be addItemCru? If so need to move it from MainActor.
+ weapon->moveToContainer(newactor, false);
+ newactor->setCombatTactic(0);
+ newactor->setHomePosition(x, y, z);
- // give weapon to NPC.
+ /*
+ TODO: once I know what this field is.. seems to never be used in game?
+ newactor->setField0x12(item->getNpcNum() >> 4);
*/
return newactor->getObjId();
}
+uint32 Actor::I_setUnkByte(const uint8 *args, unsigned int /*argsize*/) {
+ ARG_ACTOR_FROM_PTR(actor);
+ ARG_UINT16(value);
+ if (actor)
+ actor->setUnkByte(static_cast<uint8>(value & 0xff));
+ return 0;
+}
+
+uint32 Actor::I_getUnkByte(const uint8 *args, unsigned int /*argsize*/) {
+ ARG_ACTOR_FROM_PTR(actor);
+ if (!actor) return 0;
+
+ return actor->getUnkByte();
+}
+
uint32 Actor::I_setActivity(const uint8 *args, unsigned int /*argsize*/) {
ARG_ACTOR_FROM_PTR(actor);
ARG_UINT16(activity);
diff --git a/engines/ultima/ultima8/world/actors/actor.h b/engines/ultima/ultima8/world/actors/actor.h
index 9f196545fc..1b7a77e7ac 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -122,8 +122,11 @@ public:
void setFallStart(int32 zp) {
_fallStart = zp;
}
- void setUnk0C(uint8 b) {
- _unk0C = b;
+ void setUnkByte(uint8 b) {
+ _unkByte = b;
+ }
+ uint8 getUnkByte() const {
+ return _unkByte;
}
bool hasActorFlags(uint32 flags) const {
@@ -170,6 +173,9 @@ public:
void setDefaultActivity(int no, uint16 activity);
uint16 getDefaultActivity(int no) const;
+ void setHomePosition(int32 x, int32 y, int32 z);
+ void getHomePosition(int32 &x, int32 &y, int32 &z) const;
+
//! calculate the damage an attack against this Actor does.
//! \param other the attacker (can be zero)
//! \param damage base damage
@@ -294,6 +300,8 @@ public:
INTRINSIC(I_getDefaultActivity1);
INTRINSIC(I_getDefaultActivity2);
INTRINSIC(I_setCombatTactic);
+ INTRINSIC(I_setUnkByte);
+ INTRINSIC(I_getUnkByte);
enum ActorFlags {
ACT_INVINCIBLE = 0x000001, // flags from npcdata byte 0x1B
@@ -329,7 +337,10 @@ protected:
uint16 _direction;
int32 _fallStart;
- uint8 _unk0C; // unknown byte 0x0C from npcdata.dat
+
+ //! Unknown byte 0x0C from npcdata.dat in U8, or
+ //! Unknown byte 0x99 from NPC struct in Crusader.
+ uint8 _unkByte;
//! tactic being used in combat (for Crusader), the entry in the combat.dat flex.
uint16 _combatTactic;
@@ -339,6 +350,11 @@ protected:
//! the 3 default NPC activities from Crusader
uint16 _defaultActivity[3];
+ //! The "home" position used in some Crusader attack tactics
+ int32 _homeX;
+ int32 _homeY;
+ int32 _homeZ;
+
//! starts an activity (Ultima 8 version)
//! \return processID of process handling the activity or zero
uint16 setActivityU8(int activity);
diff --git a/engines/ultima/ultima8/world/actors/main_actor.cpp b/engines/ultima/ultima8/world/actors/main_actor.cpp
index e75a2a904b..23d0517de3 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.cpp
+++ b/engines/ultima/ultima8/world/actors/main_actor.cpp
@@ -175,7 +175,6 @@ int16 MainActor::addItemCru(Item *item, bool showtoast) {
item->moveToContainer(this);
if (!_activeWeapon)
_activeWeapon = item->getObjId();
- warning("TODO: Set new weapon as active weapon if there is none");
if (showtoast)
pickupArea->addPickup(item);
}
@@ -803,6 +802,17 @@ uint32 MainActor::I_addItemCru(const uint8 *args,
return 0;
}
+uint32 MainActor::I_getNumberOfCredits(const uint8 *args,
+unsigned int /*argsize*/) {
+ MainActor *av = getMainActor();
+ if (av) {
+ Item *item = av->getFirstItemWithShape(0x4ed, true);
+ if (item)
+ return item->getQuality();
+ }
+ return 0;
+}
+
void MainActor::useInventoryItem(uint32 shapenum) {
Item *item = getFirstItemWithShape(shapenum, true);
useInventoryItem(item);
diff --git a/engines/ultima/ultima8/world/actors/main_actor.h b/engines/ultima/ultima8/world/actors/main_actor.h
index 98bfd99b38..c4f6ac4070 100644
--- a/engines/ultima/ultima8/world/actors/main_actor.h
+++ b/engines/ultima/ultima8/world/actors/main_actor.h
@@ -148,6 +148,7 @@ public:
INTRINSIC(I_hasKeycard);
INTRINSIC(I_clrKeycards);
INTRINSIC(I_addItemCru);
+ INTRINSIC(I_getNumberOfCredits);
void getWeaponOverlay(const WeaponOverlayFrame *&frame_, uint32 &shape_);
diff --git a/engines/ultima/ultima8/world/world.cpp b/engines/ultima/ultima8/world/world.cpp
index 466d89bf12..e62dcf5efa 100644
--- a/engines/ultima/ultima8/world/world.cpp
+++ b/engines/ultima/ultima8/world/world.cpp
@@ -288,7 +288,7 @@ void World::loadItemCachNPCData(Common::SeekableReadStream *itemcach, Common::Se
uint8 align = npcds->readByte(); // 0x0B: alignments
actor->setAlignment(align & 0x0F);
actor->setEnemyAlignment(align & 0xF0);
- actor->setUnk0C(npcds->readByte()); // 0x0C: unknown;
+ actor->setUnkByte(npcds->readByte()); // 0x0C: unknown;
// 0x0C is almost always zero, except for
// the avatar (0xC0) and
// Malchir, Vardion, Gorgrond, Beren (0xE0)
More information about the Scummvm-git-logs
mailing list