[Scummvm-git-logs] scummvm master -> a09add2af9978b6bf7e32cd77e181e611221a09e
mduggan
mgithub at guarana.org
Thu Jun 25 04:45:18 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:
a09add2af9 ULTIMA8: Load Crusader NPC data and use it for making NPCs
Commit: a09add2af9978b6bf7e32cd77e181e611221a09e
https://github.com/scummvm/scummvm/commit/a09add2af9978b6bf7e32cd77e181e611221a09e
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-06-25T13:44:21+09:00
Commit Message:
ULTIMA8: Load Crusader NPC data and use it for making NPCs
Changed paths:
A engines/ultima/ultima8/world/actors/npc_dat.cpp
A engines/ultima/ultima8/world/actors/npc_dat.h
engines/ultima/module.mk
engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
engines/ultima/ultima8/games/game_data.cpp
engines/ultima/ultima8/games/game_data.h
engines/ultima/ultima8/games/start_crusader_process.cpp
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/item.cpp
engines/ultima/ultima8/world/item.h
diff --git a/engines/ultima/module.mk b/engines/ultima/module.mk
index 449858a956..0a9ca13870 100644
--- a/engines/ultima/module.mk
+++ b/engines/ultima/module.mk
@@ -558,6 +558,7 @@ MODULE_OBJS := \
ultima8/world/actors/heal_process.o \
ultima8/world/actors/loiter_process.o \
ultima8/world/actors/main_actor.o \
+ ultima8/world/actors/npc_dat.o \
ultima8/world/actors/pathfinder.o \
ultima8/world/actors/pathfinder_process.o \
ultima8/world/actors/quick_avatar_mover_process.o \
diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index 98eb303015..156848bd90 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -388,7 +388,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
"void Item::I_getFootpadData(Item *, uint *, uint *, uint *)", // same coff as 064
"byte Actor::I_isDead(Item *)", // same coff as 122, 039
- "int16 MonsterEgg::I_monsterEggHatch(Item *, uint16 other_itemno)",
+ "int16 Actor::I_createActorCru(Item *, uint16 other_itemno)",
// 0130
"void Actor::I_clrImmortal(Actor *)", // same coff as 07B
"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
diff --git a/engines/ultima/ultima8/games/game_data.cpp b/engines/ultima/ultima8/games/game_data.cpp
index c16a7fedb0..0ff5a83e6a 100644
--- a/engines/ultima/ultima8/games/game_data.cpp
+++ b/engines/ultima/ultima8/games/game_data.cpp
@@ -31,6 +31,7 @@
#include "ultima/ultima8/graphics/fonts/font_shape_archive.h"
#include "ultima/ultima8/graphics/gump_shape_archive.h"
#include "ultima/ultima8/world/map_glob.h"
+#include "ultima/ultima8/world/actors/npc_dat.h"
#include "ultima/ultima8/graphics/palette_manager.h"
#include "ultima/ultima8/graphics/shape.h"
#include "ultima/ultima8/graphics/wpn_ovlay_dat.h"
@@ -93,6 +94,10 @@ GameData::~GameData() {
delete _soundFlex;
_soundFlex = nullptr;
+ for (unsigned int i = 0; i < _npcTable.size(); ++i)
+ delete _npcTable[i];
+ _npcTable.clear();
+
_gameData = nullptr;
for (unsigned int i = 0; i < _speech.size(); ++i) {
@@ -472,6 +477,23 @@ SpeechFlex *GameData::getSpeechFlex(uint32 shapeNum) {
return *s;
}
+const NPCDat *GameData::getNPCData(uint16 entry) const {
+ if (entry < _npcTable.size()) {
+ return _npcTable[entry];
+ }
+ return nullptr;
+}
+
+const NPCDat *GameData::getNPCDataForShape(uint16 shapeno) const {
+ for (Std::vector<NPCDat *>::const_iterator it = _npcTable.begin();
+ it != _npcTable.end();
+ it++) {
+ const NPCDat *npcdat = *it;
+ if (npcdat->getShapeNo() == shapeno)
+ return npcdat;
+ }
+ return nullptr;
+}
void GameData::loadRemorseData() {
FileSystem *filesystem = FileSystem::get_instance();
@@ -595,13 +617,7 @@ void GameData::loadRemorseData() {
error("Unable to load static/dtable.flx");
RawArchive *dtableflex = new RawArchive(dtableds);
-
- // TODO: What's in this flex file?
- // Object 1: 35 * 142-byte blocks of .. something. Shapeno at 0x3E (based on disasm)
- // Object 2: 35 * 32-byte long names of NPCs?
- //_dtable = new DtableDat();
- //_dtable->load(dtableflex);
-
+ _npcTable = NPCDat::load(dtableflex);
delete dtableflex;
Common::SeekableReadStream *damageds = filesystem->ReadFile("@game/static/damage.flx");
@@ -645,16 +661,6 @@ void GameData::loadRemorseData() {
delete stuffds;
- Common::SeekableReadStream *trigds = filesystem->ReadFile("@game/static/trig.dat");
- if (!trigds)
- error("Unable to load static/trig.dat");
-
- // TODO: What's in this dat file?
- // 12 x 256 bytes. Each block has consistently either 0000 or FFFF in the
- //vsecond word of each DWORD
-
- delete trigds;
-
Common::SeekableReadStream *xformpalds = filesystem->ReadFile("@game/static/xformpal.dat");
if (!xformpalds)
error("Unable to load static/xformpal.dat");
diff --git a/engines/ultima/ultima8/games/game_data.h b/engines/ultima/ultima8/games/game_data.h
index 6fc16fd0b7..052170f6e5 100644
--- a/engines/ultima/ultima8/games/game_data.h
+++ b/engines/ultima/ultima8/games/game_data.h
@@ -39,6 +39,7 @@ class MapGlob;
class Shape;
class MusicFlex;
class WpnOvlayDat;
+class NPCDat;
class ShapeFrame;
class SoundFlex;
class SpeechFlex;
@@ -91,6 +92,9 @@ public:
Shape *getShape(FrameID frameid) const;
const ShapeFrame *getFrame(FrameID frameid) const;
+ const NPCDat *getNPCData(uint16 entry) const;
+ const NPCDat *getNPCDataForShape(uint16 shapeno) const;
+
Std::string translate(const Std::string &text);
FrameID translate(FrameID frame);
@@ -113,6 +117,7 @@ private:
Shape *_mouse;
MusicFlex *_music;
WpnOvlayDat *_weaponOverlay;
+ Std::vector<NPCDat *> _npcTable;
SoundFlex *_soundFlex;
Std::vector<SpeechFlex **> _speech;
diff --git a/engines/ultima/ultima8/games/start_crusader_process.cpp b/engines/ultima/ultima8/games/start_crusader_process.cpp
index 55f90a9978..3cdf424deb 100644
--- a/engines/ultima/ultima8/games/start_crusader_process.cpp
+++ b/engines/ultima/ultima8/games/start_crusader_process.cpp
@@ -37,6 +37,7 @@
#include "ultima/ultima8/gumps/cru_status_gump.h"
#include "ultima/ultima8/conf/setting_manager.h"
#include "ultima/ultima8/world/get_object.h"
+#include "ultima/ultima8/world/item_factory.h"
#include "ultima/ultima8/graphics/palette_fader_process.h"
#include "ultima/ultima8/audio/music_process.h"
@@ -108,6 +109,11 @@ void StartCrusaderProcess::run() {
egg->hatch();
*/
+ // TODO: How is this created in the game??
+ Egg *miss1egg = new Egg();
+ miss1egg->setShape(2317);
+ miss1egg->assignObjId();
+ miss1egg->callUsecodeEvent_hatch();
}
//MusicProcess::get_instance()->playMusic(2);
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index b1177233fc..4faacc61b1 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -356,7 +356,7 @@ Intrinsic RemorseIntrinsics[] = {
Item::I_isOn,
Item::I_getFootpadData, // void Intrinsic12D(16 bytes)
Actor::I_isDead, // int Intrinsic12E(4 bytes)
- MonsterEgg::I_monsterEggHatch, // void Intrinsic12F(6 bytes) - FIXME: this is pretty different .. will it work?
+ Actor::I_createActorCru, // void Intrinsic12F(6 bytes)
// 0x130
Actor::I_clrImmortal, // void Intrinsic130(4 bytes)
Actor::I_setActivity, // void Intrinsic131(6 bytes)
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index adf2a74a8a..4bbd21c918 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -37,6 +37,7 @@
#include "ultima/ultima8/graphics/shape_info.h"
#include "ultima/ultima8/world/actors/pathfinder.h"
#include "ultima/ultima8/world/actors/animation.h"
+#include "ultima/ultima8/world/actors/npc_dat.h"
#include "ultima/ultima8/kernel/delay_process.h"
#include "ultima/ultima8/kernel/core_app.h"
#include "ultima/ultima8/world/actors/resurrection_process.h"
@@ -573,6 +574,7 @@ uint16 Actor::setActivityCru(int activity) {
default:
perr << "Actor::setActivityCru: invalid activity (" << activity << ")"
<< Std::endl;
+ return doAnim(Animation::stand, 8);
}
return 0;
@@ -1065,7 +1067,7 @@ void Actor::notifyNearbyItems() {
UCList uclist(2);
LOOPSCRIPT(script, LS_TOKEN_TRUE); // we want all items
CurrentMap *currentmap = World::get_instance()->getCurrentMap();
- currentmap->areaSearch(&uclist, script, sizeof(script), this, 0x40, false);
+ currentmap->areaSearch(&uclist, script, sizeof(script), this, 0x80, false);
for (unsigned int i = 0; i < uclist.getSize(); ++i) {
Item *item = getItem(uclist.getuint16(i));
@@ -1647,6 +1649,70 @@ uint32 Actor::I_createActor(const uint8 *args, unsigned int /*argsize*/) {
return objID;
}
+uint32 Actor::I_createActorCru(const uint8 *args, unsigned int /*argsize*/) {
+ ARG_ITEM_FROM_PTR(item);
+ ARG_ITEM_FROM_ID(other);
+
+ if (!item || !other)
+ return 0;
+
+ // TODO: get game difficulty here.
+ static const int gameDifficulty = 1;
+ int npcDifficulty = (item->getMapNum() & 3) + 1;
+
+ if (gameDifficulty < npcDifficulty)
+ return 0;
+
+ uint16 dtableidx = other->getNpcNum();
+ const NPCDat *npcData = GameData::get_instance()->getNPCData(dtableidx);
+ if (!npcData)
+ return 0;
+
+ int dir = item->getNpcNum() & 0xf;
+ int frame = (dir * 2 + 4) & 0xf;
+ uint16 shape = npcData->getShapeNo();
+
+ enum extflags ext = static_cast<extflags>(0);
+ if (shape == 0x597 || shape == 0x3ac)
+ ext = EXT_FEMALE;
+
+ Actor *newactor = ItemFactory::createActor(shape, frame, 0,
+ Item::FLG_IN_NPC_LIST | Item::FLG_DISPOSABLE,
+ 0, 0, ext, true);
+ if (!newactor) {
+ perr << "I_createActorCru failed to create actor ("
+ << npcData->getShapeNo() << ")." << Std::endl;
+ return 0;
+ }
+
+ newactor->setStr(npcData->getMaxHp() / 2);
+ newactor->setDir(dir);
+
+ int32 x, y, z;
+ item->getLocation(x, y, z);
+ newactor->move(x, y, z);
+
+ // TODO: once I know what these fields are...
+ /*
+ newactor->setField0x5c(0);
+ newactor->setField0x5e(x, y);
+ newactor->setField0x12(item->getNpcNum() >> 4);
+ newactor->setField0x06(other->getQuality() >> 8);
+ newactor->setField0x08(item->getQuality() >> 8);
+ newactor->setField0x0A(other->getMapArray());
+ newactor->setField0x63(item->getQuality() & 0xff);
+
+ uint16 wpnType = npcData->getWpnType();
+ if (gameDifficulty == 4) {
+ wpnType = randomlyGetHigherWeaponType(shape, wpntype);
+ }
+
+ // give weapon to NPC.
+ */
+
+ return newactor->getObjId();
+}
+
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 9eae47520b..337667cb8d 100644
--- a/engines/ultima/ultima8/world/actors/actor.h
+++ b/engines/ultima/ultima8/world/actors/actor.h
@@ -272,6 +272,7 @@ public:
INTRINSIC(I_areEnemiesNear);
INTRINSIC(I_isBusy);
INTRINSIC(I_createActor);
+ INTRINSIC(I_createActorCru);
INTRINSIC(I_setActivity);
INTRINSIC(I_setAirWalkEnabled);
INTRINSIC(I_getAirWalkEnabled);
diff --git a/engines/ultima/ultima8/world/actors/npc_dat.cpp b/engines/ultima/ultima8/world/actors/npc_dat.cpp
new file mode 100644
index 0000000000..9f99f03c37
--- /dev/null
+++ b/engines/ultima/ultima8/world/actors/npc_dat.cpp
@@ -0,0 +1,73 @@
+/* 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/npc_dat.h"
+
+#include "common/memstream.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+NPCDat::NPCDat(Common::SeekableReadStream &rs, Common::SeekableReadStream &namers) {
+ char namebuf[33] = {0};
+ namers.read(namebuf, 32);
+ _name.assign(namebuf);
+
+ _minHp = rs.readUint16LE();
+ _maxHp = rs.readUint16LE();
+ // TODO: Read the other data.
+ rs.skip(22);
+ // offset 0x1a (26): wpntype
+ _wpnType = rs.readUint16LE();
+ // offset 0x3e (62): shape
+ rs.skip(62 - 28);
+ _shapeNo = rs.readUint16LE();
+ rs.skip(142 - 64);
+}
+
+/*static*/
+Std::vector<NPCDat *> NPCDat::load(RawArchive *archive) {
+ Std::vector<NPCDat *> result;
+ assert(archive);
+ if (archive->getCount() < 2) {
+ warning("NPCDat: Archive does not include the expected objects.");
+ return result;
+ }
+
+ Common::MemoryReadStream datars(archive->get_object_nodel(0), archive->get_size(0));
+ Common::MemoryReadStream namers(archive->get_object_nodel(2), archive->get_size(2));
+
+ if (!datars.size() || !namers.size()) {
+ warning("NPCDat: Archive appears to be corrupt.");
+ return result;
+ }
+
+ while (!datars.eos() && !namers.eos() && (datars.size() - datars.pos() >= 142)) {
+ result.push_back(new NPCDat(datars, namers));
+ }
+
+ return result;
+}
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/actors/npc_dat.h b/engines/ultima/ultima8/world/actors/npc_dat.h
new file mode 100644
index 0000000000..9779082e24
--- /dev/null
+++ b/engines/ultima/ultima8/world/actors/npc_dat.h
@@ -0,0 +1,70 @@
+/* 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_NPC_DAT_H
+#define WORLD_ACTORS_NPC_DAT_H
+
+#include "ultima/ultima8/filesys/raw_archive.h"
+
+namespace Ultima {
+namespace Ultima8 {
+
+class NPCDat {
+public:
+ NPCDat();
+
+ static Std::vector<NPCDat *> load(RawArchive *archive);
+
+ const Std::string &getName() const {
+ return _name;
+ };
+
+ uint16 getShapeNo() const {
+ return _shapeNo;
+ };
+
+ uint16 getMinHp() const {
+ return _minHp;
+ };
+
+ uint16 getMaxHp() const {
+ return _maxHp;
+ };
+
+ uint16 getWpnType() const {
+ return _wpnType;
+ };
+
+private:
+ NPCDat(Common::SeekableReadStream &datars, Common::SeekableReadStream &namers);
+
+ Std::string _name;
+ uint16 _minHp;
+ uint16 _maxHp;
+ uint16 _shapeNo;
+ uint16 _wpnType;
+};
+
+} // End of namespace Ultima8
+} // End of namespace Ultima
+
+#endif
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 0b692a59f3..668c5a269b 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -695,7 +695,10 @@ Shape *Item::getShapeObject() const {
}
uint16 Item::getFamily() const {
- return static_cast<uint16>(getShapeInfo()->_family);
+ const ShapeInfo *info = getShapeInfo();
+ if (!info)
+ return 0;
+ return static_cast<uint16>(info->_family);
}
uint32 Item::getWeight() const {
diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index 7abeb1fde4..1328a34ee3 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -635,7 +635,8 @@ public:
EXT_CAMERA = 0x0020, //!< Item is being followed by the camera
EXT_SPRITE = 0x0040, //!< Item is a sprite
EXT_TRANSPARENT = 0x0080, //!< Item should be painted transparent
- EXT_PERMANENT_NPC = 0x0100 //!< Item is a permanent NPC
+ EXT_PERMANENT_NPC = 0x0100, //!< Item is a permanent NPC
+ EXT_FEMALE = 0x8000 //!< Crusader Female NPC (controls sfx)
};
};
More information about the Scummvm-git-logs
mailing list