[Scummvm-git-logs] scummvm master -> f13ebb9759416522b20daa7fa22b4e349e5624e8

mduggan mgithub at guarana.org
Fri Jun 19 02:36:53 UTC 2020


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
259e4d6589 ULTIMA8: More Crusader intrinsic support
f13ebb9759 ULTIMA8: Add support for Crusader enable/disable alert intrinsics


Commit: 259e4d6589256cef5935b74346e88256eeeb6f6c
    https://github.com/scummvm/scummvm/commit/259e4d6589256cef5935b74346e88256eeeb6f6c
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-06-19T11:35:43+09:00

Commit Message:
ULTIMA8: More Crusader intrinsic support

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/camera_process.cpp
    engines/ultima/ultima8/world/current_map.cpp
    engines/ultima/ultima8/world/item.cpp
    engines/ultima/ultima8/world/item.h
    engines/ultima/ultima8/world/sprite_process.cpp


diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index dcb495cd2c..cce60431ee 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -78,10 +78,10 @@ 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 I_GetNPCDataField0x63_00B(Actor *)", // could be getNPCNum? Called from ANDROID::calledFromAnim, goes to NPCDEATH
+	"int16 Actor::I_GetNPCDataField0x63_00B(Actor *)", // could be getNPCNum? Called from ANDROID::calledFromAnim, goes to NPCDEATH
 	"void I_NPCsetSomething_00C(int)",
 	"byte Item::I_getDirToItem(Item *, itemno)", // based on disasm
-	"int16 I_NPCSomething00E(Actor *, int, int)",
+	"int16 Actor::I_NPCSomething00E(Actor *, int, int)",
 	"void I_playFlic(void), int16 I_playFlic(Item *, char *name, int16 sizex, int16 sizey)",
 	// 0010
 	"int16 Item::I_getQLo(Item *)", // same as 02B based on same coff as 02B, 066, 084, 0A1, 0AE, 0D9, 0EA
@@ -237,7 +237,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 PaletteFaderProcess::I_fadeToBlackWithParam(nsteps, unk)", // TODO: what's the param?
 	"int16 PaletteFaderProcess::I_fadeToColor(r, g, b, nsteps, unk)", // TODO: what's the other param?
 	// 00A0
-	"void I_SetItemFlag0x8000AndNPCField0x13Flag0_0A0(Actor *)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
+	"void Actor::I_setDead(Actor *)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
 	"int16 Item::I_getQLo(Item *)", // same as 02B based on same coff set 010, 02B, 066, 084, 0A1, 0AE, 0D9, 0EA
 	"int16 Item::I_getUnkEggType(Item *)", // based on disassembly, same as U8
 	"void Egg::I_setEggXRange(Egg *, int)", // based on disasm
@@ -248,7 +248,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"void Actor::I_setDead(Actor *)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
 	"void I_playFlic0A9(char *)", // same coff as 092
 	"void I_playSFX(2 bytes)", // same coff as 0D4
-	"byte I_NPCGetField0x59Flag1_0AB(Actor *)",
+	"byte Actor::I_NPCGetField0x59Flag1_0AB(Actor *)",
 	"int16 Item::I_getFamilyOfType(Item *)", // per pentagram notes, matches disasm.
 	"int16 Item::I_getNPCNum(Item *)", // part of same coff set 067, 06D, 089, 08E, 0AD, 0F8, 100, 102, 105, 107, 109, 10B, 10D, 10F, 111, 115, 11C, 123, 129
 	"int16 Item::I_getQLo(Item *)", // same as 02B based on same coff set 010, 02B, 066, 084, 0A1, 0AE, 0D9, 0EA
@@ -283,7 +283,7 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 Item::I_getQHi(Item *)", // same as 026 based on same coff set 026, 045, 047, 049, 04B, 04D, 04F, 0AF, 0BE, 0C9, 0F0, 0F3, 0FB, 133
 	"byte Actor::I_addHp(Actor *, int)",
 	"void Intrinsic0CB(2 bytes)",
-	"byte I_GetNPCDataField0x59Flag3_0CC(Actor *)",
+	"byte Actor::I_GetNPCDataField0x59Flag3_0CC(Actor *)",
 	"void Actor::I_setActivity(Actor *, int)", // part of same coff set 055, 07D, 0CD, 0DB, 0F2, 131
 	"int16 Game::I_isReleaseBuild(void)", // whether the string "GAME COMPILE=1" has the 1.  Might be interesting to see what this does..
 	"void Item::setQAndCallSomething(Item *, int16 q)", // based on disassembly
@@ -301,17 +301,17 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"void Intrinsic0DA_Fade(void)", // something about fades
 	"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 I_GetNPCDataField0x4_0DD(Actor *)",
-	"void I_SetNPCDataField0x5c_0DE(Actor *, int)",
+	"int16 Actor::I_GetNPCDataField0x4_0DD(Actor *)",
+	"void Actor::I_SetNPCDataField0x5c_0DE(Actor *, int)",
 	"int16 Actor::I_getEquip(6 bytes)", // based on disasm
 	// 00E0
 	"void Actor::I_setEquip(8 bytes)",
-	"int16 I_GetNPCDataField0x6_0E1(Actor *)",
-	"int16 I_GetNPCDataField0x8_0E2(Actor *)",
-	"int16 I_GetNPCDataField0xa_0E3(Actor *)",
+	"int16 Actor::I_GetNPCDataField0x6_0E1(Actor *)",
+	"int16 Actor::I_GetNPCDataField0x8_0E2(Actor *)",
+	"int16 Actor::I_GetNPCDataField0xa_0E3(Actor *)",
 	"int16 Actor::I_getLastAnimSet(4 bytes)", // part of same coff set 01D, 05A, 0B9, 0D7, 0E4, 124
-	"void I_NPCSomething0E5(Actor *, uint16)",
-	"void I_SetNPCDataField0x63_0E6(Actor *, int)",
+	"void Actor::I_NPCSomething0E5(Actor *, uint16)",
+	"void Actor::I_SetNPCDataField0x63_0E6(Actor *, int)",
 	"void Actor::I_setDead(4 bytes)", // part of same coff set 021, 060, 073, 0A0, 0A8, 0D8, 0E7, 135
 	"int16 Item::I_cast(6 bytes)",
 	"void Item::I_andStatus(Item *, uint16 status)", // part of same coff set 01A, 031, 069, 06E, 099, 0B2, 0BF, 0C1, 0C3, 0E9, 0FC, 101, 104, 106, 108, 10A, 10C, 10E, 110, 114, 117, 11A, 128, 132
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index f43b27379c..6c50688085 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -142,7 +142,7 @@ Intrinsic RemorseIntrinsics[] = {
 	0, // void Intrinsic062(void)
 	Actor::I_teleport, // void Intrinsic063(12 bytes)
 	Item::I_getFootpadData, // void Intrinsic064(16 bytes)
-	0, // TODO: Item::I_isInNPC
+	Item::I_isInNpc,
 	Item::I_getQLo, // based on same coff set as 02B
 	Item::I_getNpcNum, // based on same coff as 102 (-> variable name in TRIGGER::ordinal21)
 	Item::I_setNpcNum, // void Item::I_setSomething068(Item *, int16 something) , see VALUEBOX:ordinal20
@@ -152,7 +152,7 @@ Intrinsic RemorseIntrinsics[] = {
 	Kernel::I_resetRef, // void Intrinsic06C(4 bytes)
 	Item::I_getNpcNum, // based on same coff as 102 (-> variable name in TRIGGER::ordinal21)
 	Item::I_andStatus, // void Intrinsic06E(6 bytes)
-	0, // TODO: Item::I_isCompletelyOn int Intrinsic06F(6 bytes)
+	Item::I_isCompletelyOn,
 	// 0x070
 	Ultima8Engine::I_getUnkCrusaderFlag, // int Intrinsic070(void)
 	Ultima8Engine::I_setUnkCrusaderFlag, // void Intrinsic071(void)
diff --git a/engines/ultima/ultima8/world/actors/actor.cpp b/engines/ultima/ultima8/world/actors/actor.cpp
index 7067f382a8..d578e4ce7d 100644
--- a/engines/ultima/ultima8/world/actors/actor.cpp
+++ b/engines/ultima/ultima8/world/actors/actor.cpp
@@ -1589,6 +1589,11 @@ uint32 Actor::I_pathfindToPoint(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_NULL16(); // unknown. Only one instance of this in U8, value is 5.
 	if (!actor) return 0;
 
+	if (GAME_IS_CRUSADER) {
+		x *= 2;
+		y *= 2;
+	}
+
 	return Kernel::get_instance()->addProcess(
 	           new PathfinderProcess(actor, x, y, z));
 }
diff --git a/engines/ultima/ultima8/world/camera_process.cpp b/engines/ultima/ultima8/world/camera_process.cpp
index 2deb55dc24..c24f7a7db0 100644
--- a/engines/ultima/ultima8/world/camera_process.cpp
+++ b/engines/ultima/ultima8/world/camera_process.cpp
@@ -320,6 +320,11 @@ uint32 CameraProcess::I_moveTo(const uint8 *args, unsigned int argsize) {
 	if (argsize > 6) {
 		ARG_SINT16(unk);
 	}
+
+	if (GAME_IS_CRUSADER) {
+		x *= 2;
+		y *= 2;
+	}
 	CameraProcess::SetCameraProcess(new CameraProcess(x, y, z));
 	return 0;
 }
@@ -337,6 +342,12 @@ uint32 CameraProcess::I_scrollTo(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(y);
 	ARG_UINT8(z);
 	ARG_SINT16(unk);
+
+	if (GAME_IS_CRUSADER) {
+		x *= 2;
+		y *= 2;
+	}
+
 	return CameraProcess::SetCameraProcess(new CameraProcess(x, y, z, 25));
 }
 
diff --git a/engines/ultima/ultima8/world/current_map.cpp b/engines/ultima/ultima8/world/current_map.cpp
index 3a7658b7d8..6a992f9e7e 100644
--- a/engines/ultima/ultima8/world/current_map.cpp
+++ b/engines/ultima/ultima8/world/current_map.cpp
@@ -1207,6 +1207,11 @@ uint32 CurrentMap::I_canExistAt(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(unk2); // looks like it could be an objid
 	ARG_UINT16(unk3); // always zero
 
+	if (GAME_IS_CRUSADER) {
+		x *= 2;
+		y *= 2;
+	}
+
 	const CurrentMap *cm = World::get_instance()->getCurrentMap();
 	bool valid = cm->isValidPosition(x, y, z, shape, 0, 0, 0);
 
diff --git a/engines/ultima/ultima8/world/item.cpp b/engines/ultima/ultima8/world/item.cpp
index 1cbe2e7266..1c71243410 100644
--- a/engines/ultima/ultima8/world/item.cpp
+++ b/engines/ultima/ultima8/world/item.cpp
@@ -116,7 +116,7 @@ void Item::dumpInfo() const {
 }
 
 Container *Item::getParentAsContainer() const {
-	// No _parent, no container
+	// No parent, no container
 	if (!_parent)
 		return nullptr;
 
@@ -529,6 +529,7 @@ bool Item::isOn(const Item &item2) const {
 }
 
 bool Item::isCompletelyOn(const Item &item2) const {
+	warning("TODO: Properly implement Item::isCompletelyOn");
 	// FIXME: this is just a copy of isOn at the moment
 	int32 x1a, y1a, z1a, x1b, y1b;
 	int32 x2a, y2a, z2a, x2b, y2b, z2b;
@@ -2475,6 +2476,11 @@ uint32 Item::I_legalCreateAtCoords(const uint8 *args, unsigned int /*argsize*/)
 	ARG_UINT16(y);
 	ARG_UINT16(z);
 
+	if (GAME_IS_CRUSADER) {
+		x *= 2;
+		y *= 2;
+	}
+
 	// check if item can exist
 	CurrentMap *cm = World::get_instance()->getCurrentMap();
 	bool valid = cm->isValidPosition(x, y, z, shape, 0, 0, 0);
@@ -2613,6 +2619,18 @@ uint32 Item::I_isOn(const uint8 *args, unsigned int /*argsize*/) {
 		return 0;
 }
 
+uint32 Item::I_isCompletelyOn(const uint8 *args, unsigned int /*argsize*/) {
+	ARG_ITEM_FROM_PTR(item);
+	ARG_ITEM_FROM_ID(item2);
+	if (!item) return 0;
+	if (!item2) return 0;
+
+	if (item->isCompletelyOn(*item2))
+		return 1;
+	else
+		return 0;
+}
+
 uint32 Item::I_isCentreOn(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_ITEM_FROM_PTR(item);
 	ARG_ITEM_FROM_ID(item2);
@@ -2625,6 +2643,21 @@ uint32 Item::I_isCentreOn(const uint8 *args, unsigned int /*argsize*/) {
 		return 0;
 }
 
+uint32 Item::I_isInNpc(const uint8 *args, unsigned int /*argsize*/) {
+	ARG_ITEM_FROM_PTR(item);
+	if (!item)
+		return 0;
+
+	const Container *container = item->getParentAsContainer();
+	while (container) {
+		const Actor *actor = dynamic_cast<const Actor *>(container);
+		if (actor)
+			return 1;
+		container = container->getParentAsContainer();
+	}
+	return 0;
+}
+
 uint32 Item::I_getFamilyOfType(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(shape);
 
@@ -2641,7 +2674,6 @@ uint32 Item::I_push(const uint8 *args, unsigned int /*argsize*/) {
 		perr << "Pushing item to ethereal void: " << item->getShape() << "," << item->getFrame() << Std::endl;
 	#endif
 
-
 	item->moveToEtherealVoid();
 
 	return 0;
@@ -3112,6 +3144,8 @@ uint32 Item::I_guardianBark(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(num);
 	if (!item) return 0;
 
+	assert(GAME_IS_U8);
+
 	return item->callUsecodeEvent_guardianBark(num);
 }
 
@@ -3176,6 +3210,8 @@ uint32 Item::I_igniteChaos(const uint8 *args, unsigned int /*argsize*/) {
 	ARG_UINT16(y);
 	ARG_NULL8();
 
+	assert(GAME_IS_U8);
+
 	UCList itemlist(2);
 	LOOPSCRIPT(script, LS_SHAPE_EQUAL(592)); // all oilflasks (CONSTANT!)
 	CurrentMap *currentmap = World::get_instance()->getCurrentMap();
diff --git a/engines/ultima/ultima8/world/item.h b/engines/ultima/ultima8/world/item.h
index 033755e907..10186809cf 100644
--- a/engines/ultima/ultima8/world/item.h
+++ b/engines/ultima/ultima8/world/item.h
@@ -499,6 +499,7 @@ public:
 	INTRINSIC(I_isOn);
 	INTRINSIC(I_isCompletelyOn);
 	INTRINSIC(I_isCentreOn);
+	INTRINSIC(I_isInNpc);
 	INTRINSIC(I_ascend);
 	INTRINSIC(I_getWeight);
 	INTRINSIC(I_getWeightIncludingContents);
diff --git a/engines/ultima/ultima8/world/sprite_process.cpp b/engines/ultima/ultima8/world/sprite_process.cpp
index 08da385b83..44246700c5 100644
--- a/engines/ultima/ultima8/world/sprite_process.cpp
+++ b/engines/ultima/ultima8/world/sprite_process.cpp
@@ -26,6 +26,7 @@
 #include "ultima/ultima8/world/item.h"
 #include "ultima/ultima8/world/current_map.h"
 #include "ultima/ultima8/kernel/kernel.h"
+#include "ultima/ultima8/kernel/core_app.h"
 #include "ultima/ultima8/world/get_object.h"
 
 namespace Ultima {
@@ -106,6 +107,12 @@ uint32 SpriteProcess::I_createSprite(const uint8 *args, unsigned int argsize) {
 	ARG_UINT16(x);
 	ARG_UINT16(y);
 	ARG_UINT8(z);
+
+	if (GAME_IS_CRUSADER) {
+		x *= 2;
+		y *= 2;
+	}
+
 	Process *p = new SpriteProcess(shape, frame, lastFrame, repeats, delay, x, y, z);
 	return Kernel::get_instance()->addProcess(p);
 }


Commit: f13ebb9759416522b20daa7fa22b4e349e5624e8
    https://github.com/scummvm/scummvm/commit/f13ebb9759416522b20daa7fa22b4e349e5624e8
Author: Matthew Duggan (mgithub at guarana.org)
Date: 2020-06-19T11:35:57+09:00

Commit Message:
ULTIMA8: Add support for Crusader enable/disable alert intrinsics

Changed paths:
    engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
    engines/ultima/ultima8/usecode/remorse_intrinsics.h
    engines/ultima/ultima8/world/map.cpp
    engines/ultima/ultima8/world/world.cpp
    engines/ultima/ultima8/world/world.h


diff --git a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
index cce60431ee..973a554734 100644
--- a/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
+++ b/engines/ultima/ultima8/convert/crusader/convert_usecode_crusader.h
@@ -258,9 +258,9 @@ const char* const ConvertUsecodeCrusader::_intrinsics[] = {
 	"int16 Item::I_spawnUsecodeEvent0x13(Item *, 2 bytes)", // based on disasm - what is event 0x13? "avatar stole something" in U8..
 	"void Item::I_andStatus(Item *, uint16 status)", // part of same coff set 01A, 031, 069, 06E, 099, 0B2, 0BF, 0C1, 0C3, 0E9, 0FC, 101, 104, 106, 108, 10A, 10C, 10E, 110, 114, 117, 11A, 128, 132
 	"int32 I_getCurrentTimerTick(void)",
-	"void Intrinsic0B4(void)",  // set or clear alert? (based on coff)
+	"void Ultima8Engine::I_setAlertActive(void)",
 	"int16 Item::I_equip(6 bytes)",
-	"void Intrinsic0B6(void)",  // set or clear alert? (based on coff)
+	"void Ultima8Engine::I_clrAlertActive(void)",
 	"int16 I_GetNPCGlobal0x7e24_0B7(void)",
 	"byte Intrinsic0B8(4 bytes)", // same coff as 037
 	"int16 Actor::I_getLastAnimSet(4 bytes)", // part of same coff set 01D, 05A, 0B9, 0D7, 0E4, 124
diff --git a/engines/ultima/ultima8/usecode/remorse_intrinsics.h b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
index 6c50688085..cc040134ae 100644
--- a/engines/ultima/ultima8/usecode/remorse_intrinsics.h
+++ b/engines/ultima/ultima8/usecode/remorse_intrinsics.h
@@ -35,17 +35,17 @@ namespace Ultima8 {
 // Most up-to-date version of unknown functions is in convert_usecode_crusader.h
 Intrinsic RemorseIntrinsics[] = {
 	// 0x000
-	Ultima8Engine::I_getAlertActive,  // basically confirmed.. see eg, ALARM_NS::enterFastArea - set frame for alert siren based on value.
-	Item::I_getFrame, // int Intrinsic001(4 bytes)
-	Item::I_setFrame, // basically confirmed..
+	World::I_getAlertActive,
+	Item::I_getFrame, // int Intrinsic001(Item *)
+	Item::I_setFrame, //
 	Item::I_getMapArray, // See TRIGGER::ordinal21 - stored in a variable 'mapNum'
-	Item::I_getStatus, // probably - see usage in GATGUNEW::enterFastArea - always followed by an AND against a single bit
-	Item::I_orStatus, // probably - see usage in GATGUNEW::enterFastArea
+	Item::I_getStatus,
+	Item::I_orStatus,
 	Item::I_equip, // void Intrinsic006(6 bytes)
 	Item::I_isOnScreen, //
-	Actor::I_isNPC, // byte Intrinsic008(Item *) // probably.. disasm checks for < 256
-	Item::I_getZ, // byte Intrinsic009(4 bytes) // probably, see PEPSIEW::use() variable names
-	Item::I_destroy, // void Intrinsic00A(4 bytes) // probably, often called after creating replacement object in same position eg, LUGGAGE::gotHit
+	Actor::I_isNPC, // byte Intrinsic008(Item *)
+	Item::I_getZ, // byte Intrinsic009(Item *)
+	Item::I_destroy, // void Intrinsic00A(Item *)
 	0, // something with npcdata void Intrinsic00B(4 bytes)
 	0, // void Intrinsic00C(2 bytes)
 	Item::I_getDirToItem, // byte Intrinsic00D(6 bytes)
@@ -55,19 +55,19 @@ Intrinsic RemorseIntrinsics[] = {
 	Item::I_getQLo, // Based on having same coff as 02B
 	Actor::I_getMap, // int Intrinsic011(4 bytes)
 	0, // void Intrinsic012(2 bytes)
-	Item::I_getX, //int Intrinsic013(4 bytes) // probably - see FREE::ordinal34
-	Item::I_getY, //int Intrinsic014(4 bytes) // probably - see FREE::ordinal34
-	AudioProcess::I_playSFXCru, // pretty sure, see SWITCH::ordinal21 which plays various sfx related to access status
-	Item::I_getShape, // in STEAMBOX::func0A, is compared to 0x511 (the STEAM2 shape number) to determine direction
+	Item::I_getX, //int Intrinsic013(4 bytes)
+	Item::I_getY, //int Intrinsic014(4 bytes)
+	AudioProcess::I_playSFXCru,
+	Item::I_getShape,
 	Item::I_explode, // void Intrinsic017(8 bytes)
 	UCMachine::I_rndRange, // int16 Intrinsic018(4 bytes) // probably.. always called with 2 constants, then result compared to some number between
-	Item::I_legalCreateAtCoords, // byte Intrinsic019(14 bytes),  probably, see usage in DOOR2::ordinal37
+	Item::I_legalCreateAtCoords, // byte Intrinsic019(14 bytes)
 	Item::I_andStatus, // void Intrinsic01A(6 bytes)
 	UCMachine::I_true, // FIXME: get the num of some npc - maybe currently controlled NPC? For now default to 1 (avatar).
 	Actor::I_getDir, // byte Intrinsic01C(4 bytes)
 	Actor::I_getLastAnimSet, // int Intrinsic01D(4 bytes)
 	0, // int Intrinsic01E(16 bytes)
-	Item::I_create, // probably - used in MISS1EGG creating keycards and NPCDEATH in creating blood spills
+	Item::I_create,
 	// 0x020
 	Item::I_popToCoords, // void Intrinsic020(10 bytes)
 	Actor::I_setDead, // void Intrinsic021(4 bytes)
@@ -75,12 +75,12 @@ Intrinsic RemorseIntrinsics[] = {
 	Item::I_getEtherealTop, // int Intrinsic023(void)
 	Item::I_setShape, // Probably, see PEPSIEW::gotHit
 	Item::I_touch,
-	Item::I_getQHi, // int16 Intrinsic026(Item *), // guess, based on variable name in BOUNCBOX::gotHit
+	Item::I_getQHi, // int16 Intrinsic026(Item *)
 	Item::I_getClosestDirectionInRange, // int Intrinsic027(14 bytes)
 	Item::I_hurl, // int Intrinsic028(12 bytes)
 	UCMachine::I_true, // TODO: This is actually game difficulty level.  Make an intrinsic for that once it's implemented (for now return 1, easiest difficulty).
 	AudioProcess::I_playAmbientSFXCru, // Confirmed!
-	Item::I_getQLo, // int16 Intrinsic02B(4 bytes), // guess, based on variable name in BOUNCBOX::gotHit
+	Item::I_getQLo, // int16 Intrinsic02B(4 bytes)
 	Item::I_inFastArea, // byte Intrinsic02C(4 bytes) // based on disassembly - checks for flag 0x2000
 	Item::I_setQHi,
 	Item::I_legalMoveToPoint, // byte Intrinsic02E(12 bytes)
@@ -226,9 +226,9 @@ Intrinsic RemorseIntrinsics[] = {
 	Item::I_avatarStoleSomething, // void Intrinsic0B1(6 bytes)
 	Item::I_andStatus, // void Intrinsic0B2(6 bytes)
 	Ultima8Engine::I_getCurrentTimerTick, // int32 Intrinsic0B3(void), probably, see FREE::ordinal32
-	0, // void Intrinsic0B4(void)
+	World::I_setAlertActive, // void Intrinsic0B4(void)
 	Item::I_equip, // void Intrinsic0B5(6 bytes)
-	0, // void Intrinsic0B6(void)
+	World::I_clrAlertActive, // void Intrinsic0B6(void)
 	0, // void Intrinsic0B7(void)
 	0, // int Intrinsic0B8(4 bytes)
 	Actor::I_getLastAnimSet, // void Intrinsic0B9(4 bytes)
diff --git a/engines/ultima/ultima8/world/map.cpp b/engines/ultima/ultima8/world/map.cpp
index 95573553a4..deeb884224 100644
--- a/engines/ultima/ultima8/world/map.cpp
+++ b/engines/ultima/ultima8/world/map.cpp
@@ -261,7 +261,11 @@ void Map::loadFixedFormatObjects(Std::list<Item *> &itemlist,
 			ShapeInfo *info = item->getShapeInfo();
 			assert(info);
 			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);
+				//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);
diff --git a/engines/ultima/ultima8/world/world.cpp b/engines/ultima/ultima8/world/world.cpp
index 365c6a017f..fb658d960b 100644
--- a/engines/ultima/ultima8/world/world.cpp
+++ b/engines/ultima/ultima8/world/world.cpp
@@ -29,6 +29,8 @@
 #include "ultima/ultima8/world/item_factory.h"
 #include "ultima/ultima8/world/actors/actor.h"
 #include "ultima/ultima8/world/actors/main_actor.h"
+#include "ultima/ultima8/world/loop_script.h"
+#include "ultima/ultima8/usecode/uc_list.h"
 #include "ultima/ultima8/misc/id_man.h"
 #include "ultima/ultima8/games/game_data.h"
 #include "ultima/ultima8/kernel/kernel.h"
@@ -48,7 +50,7 @@ namespace Ultima8 {
 
 World *World::_world = nullptr;
 
-World::World() : _currentMap(nullptr) {
+World::World() : _currentMap(nullptr),  _alertActive(false) {
 	debugN(MM_INFO, "Creating World...\n");
 
 	_world = this;
@@ -337,6 +339,10 @@ void World::save(Common::WriteStream *ws) {
 
 	ws->writeUint16LE(_currentMap->_eggHatcher);
 
+	if (GAME_IS_CRUSADER) {
+		ws->writeByte(_alertActive ? 0 : 1);
+	}
+
 	uint16 es = static_cast<uint16>(_ethereal.size());
 	ws->writeUint32LE(es);
 
@@ -362,6 +368,10 @@ bool World::load(Common::ReadStream *rs, uint32 version) {
 
 	_currentMap->_eggHatcher = rs->readUint16LE();
 
+	if (GAME_IS_CRUSADER) {
+		_alertActive = (rs->readByte() != 0);
+	}
+
 	uint32 etherealcount = rs->readUint32LE();
 	for (unsigned int i = 0; i < etherealcount; ++i) {
 		_ethereal.push_front(rs->readUint16LE());
@@ -377,7 +387,6 @@ void World::saveMaps(Common::WriteStream *ws) {
 	}
 }
 
-
 bool World::loadMaps(Common::ReadStream *rs, uint32 version) {
 	uint32 mapcount = rs->readUint32LE();
 
@@ -390,5 +399,62 @@ bool World::loadMaps(Common::ReadStream *rs, uint32 version) {
 	return true;
 }
 
+void World::setAlertActive(bool active)
+{
+	assert(GAME_IS_CRUSADER);
+    _alertActive = active;
+
+	// Replicate the behavior of the original game.
+	LOOPSCRIPT(script,
+		LS_OR(
+			LS_OR(
+				LS_OR(
+					LS_OR(LS_SHAPE_EQUAL(0x49), LS_SHAPE_EQUAL(0x21)),
+					LS_SHAPE_EQUAL(0x174)),
+				LS_SHAPE_EQUAL(0x271)),
+			  LS_SHAPE_EQUAL(0x477))
+	);
+
+	UCList itemlist(2);
+	_world->getCurrentMap()->areaSearch(&itemlist, script, sizeof(script),
+										nullptr, 0x7fff, false);
+	for (uint32 i = 0; i < itemlist.getSize(); i++) {
+		uint16 itemid = itemlist.getuint16(i);
+		Item *item = getItem(itemid);
+		int frame = item->getFrame();
+		if (_alertActive) {
+			if (item->getShape() == 0x477 && frame < 2) {
+				item->setFrame(frame + 2);
+			} else if (frame == 0) {
+				item->setFrame(1);
+			}
+		} else {
+			if (item->getShape() == 0x477 && frame > 1) {
+				item->setFrame(frame + 2);
+			} else if (frame == 1) {
+				item->setFrame(0);
+			}
+		}
+	}
+}
+
+uint32 World::I_getAlertActive(const uint8 * /*args*/,
+	unsigned int /*argsize*/) {
+	return get_instance()->_world->isAlertActive() ? 1 : 0;
+}
+
+uint32 World::I_setAlertActive(const uint8 * /*args*/,
+	unsigned int /*argsize*/) {
+	get_instance()->_world->setAlertActive(true);
+	return 0;
+}
+
+uint32 World::I_clrAlertActive(const uint8 * /*args*/,
+	unsigned int /*argsize*/) {
+	get_instance()->_world->setAlertActive(false);
+	return 0;
+}
+
+
 } // End of namespace Ultima8
 } // End of namespace Ultima
diff --git a/engines/ultima/ultima8/world/world.h b/engines/ultima/ultima8/world/world.h
index 7ee446d2b9..60a2a48ff4 100644
--- a/engines/ultima/ultima8/world/world.h
+++ b/engines/ultima/ultima8/world/world.h
@@ -57,6 +57,7 @@
 //  game data need this, actually.)
 
 #include "ultima/ultima8/misc/common_types.h"
+#include "ultima/ultima8/usecode/intrinsics.h"
 #include "ultima/shared/std/containers.h"
 
 namespace Ultima {
@@ -138,6 +139,16 @@ public:
 	//! load World data
 	bool load(Common::ReadStream *rs, uint32 version);
 
+	bool isAlertActive() {
+		return _alertActive;
+	}
+
+	void setAlertActive(bool active);
+
+	INTRINSIC(I_getAlertActive); // for Crusader
+	INTRINSIC(I_setAlertActive); // for Crusader
+	INTRINSIC(I_clrAlertActive); // for Crusader
+
 private:
 	static World *_world;
 
@@ -145,6 +156,9 @@ private:
 	CurrentMap *_currentMap;
 
 	Std::list<ObjId> _ethereal;
+
+	bool _alertActive; //!< is intruder alert active (Crusader)
+
 };
 
 } // End of namespace Ultima8




More information about the Scummvm-git-logs mailing list