[Scummvm-git-logs] scummvm master -> e485255cc2ba76a70c7a65afbc18fa73f3db5c5b
dreammaster
noreply at scummvm.org
Sat Feb 17 23:11:02 UTC 2024
This automated email contains information about 34 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
e603663a1b ULTIMA: NUVIE: Add optional ignoreObjects param to nscript_map_is_water
cfa91ad190 ULTIMA: NUVIE: Fix flask of oil fire placement
cf736c2f36 ULTIMA: NUVIE: Fix thrown weapon placement condition
a9aa083d8f ULTIMA: NUVIE: Fix movability check when pushing
8bae961208 ULTIMA: NUVIE: Fix condition for pushing actors
7d2aa52191 ULTIMA: NUVIE: Fix message when pushing sitting actors
c68b2c3999 ULTIMA: NUVIE: Do not allow selecting actor as push target on map
8ec62fbd70 ULTIMA: NUVIE: Constify some methods
06eac59abb ULTIMA: NUVIE: Fix move/drop to container on map
5eaa9ddda6 ULTIMA: NUVIE: Fix instance of inventory vs map coords comparison
1bca817346 ULTIMA: NUVIE: Constify some methods
8f7038c615 ULTIMA: NUVIE: Add method doesOccupyLocation() to Actor class
1980c18840 ULTIMA: NUVIE: Add method findActorAt() to ActorManager
77e77dc7f8 ULTIMA: NUVIE: Remove duplicated logic in get_actor()
5e9db60d02 ULTIMA: NUVIE: Test all actors at destination when moving
fbb2318cb0 ULTIMA: NUVIE: Test all actors at destination when pushing
289e2ee96c ULTIMA: NUVIE: Fix crash when pushing over map boundary
a142e944f9 ULTIMA: NUVIE: Assert index is in bounds when fetching chunk obj tree
e424a5c635 ULTIMA: NUVIE: Add some missing map coordinate wrapping
9c0bf4d332 ULTIMA: NUVIE: Add isFlying() method to Actor class
feb8296337 ULTIMA: NUVIE: Add isNonBlocking() method to Actor class
7dd18ae6b3 ULTIMA: NUVIE: Slightly rework actor passability
1ab56c07bc ULTIMA: NUVIE: Allow pushing party members onto each other
593472a252 ULTIMA: NUVIE: Only bump one party member on player move
7cd99686af ULTIMA: NUVIE: Do not swap positions with party when moving as Sherry
b9206fce97 ULTIMA: NUVIE: Fix Sherry blocking/being blocked during party move
37db6d1730 ULTIMA: NUVIE: Allow dropping objects onto passable actors
37502f406d ULTIMA: NUVIE: Allow pushing objects onto passable actors
159b2084df ULTIMA: NUVIE: Fix softlock on drop to impassable location with actor
6ca26ec1db ULTIMA: NUVIE: Prevent moving some containers into containers on map
e37d96aa19 ULTIMA: NUVIE: Hide menu in save thumbnails
704ca3c493 ULTIMA: NUVIE: Fix delete[] VS free
8f8b02e63f ULTIMA: NUVIE: Fix memory leak
e485255cc2 ULTIMA: NUVIE: Fix delete VS free
Commit: e603663a1b9afdec523f2fc3da2cdfa8c212e82b
https://github.com/scummvm/scummvm/commit/e603663a1b9afdec523f2fc3da2cdfa8c212e82b
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Add optional ignoreObjects param to nscript_map_is_water
Changed paths:
engines/ultima/nuvie/script/script.cpp
diff --git a/engines/ultima/nuvie/script/script.cpp b/engines/ultima/nuvie/script/script.cpp
index 6bb7f1855c4..44748793155 100644
--- a/engines/ultima/nuvie/script/script.cpp
+++ b/engines/ultima/nuvie/script/script.cpp
@@ -2997,6 +2997,7 @@ static int nscript_map_enable_temp_actor_cleaning(lua_State *L) {
Check map location for water
@function map_is_water
@tparam MapCoord|x,y,z location
+ at tparam bool[opt] ignore objects, defaults to false
@treturn bool true if the map at location is a water tile otherwise false
@within map
*/
@@ -3005,10 +3006,16 @@ static int nscript_map_is_water(lua_State *L) {
uint16 x, y;
uint8 z;
+ bool ignoreObjects;
+ int idx;
+
if (nscript_get_location_from_args(L, &x, &y, &z, 1) == false)
return 0;
- lua_pushboolean(L, map->is_water(x, y, z));
+ idx = lua_istable(L, 1) ? 2 : 4;
+ ignoreObjects = lua_toboolean(L, idx);
+
+ lua_pushboolean(L, map->is_water(x, y, z, ignoreObjects));
return 1;
}
Commit: cfa91ad190ffe737f607122565fa3fe2afe53724
https://github.com/scummvm/scummvm/commit/cfa91ad190ffe737f607122565fa3fe2afe53724
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix flask of oil fire placement
Place at correct location (pre-collision tile).
Ignore objects when checking for water.
Changed paths:
devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
diff --git a/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua b/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
index 2e6c8aee5ba..e9e77234be1 100644
--- a/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
+++ b/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
@@ -1619,7 +1619,7 @@ function combat_range_weapon_1D5F9(attacker, target_x, target_y, target_z, weapo
Actor.inv_remove_obj_qty(attacker, 0x53, 1)
- if map_is_water(target_x,target_y,target_z) == false then
+ if map_is_water(pre_coll_tiles[1].x, pre_coll_tiles[1].y, pre_coll_tiles[1].z, true) == false then
local obj = Obj.new(317); --fire field
obj.temporary = true
Obj.moveToMap(obj, pre_coll_tiles[1].x, pre_coll_tiles[1].y, pre_coll_tiles[1].z)
Commit: cf736c2f3674d2b06e4d8baed1498aa5b913f954
https://github.com/scummvm/scummvm/commit/cf736c2f3674d2b06e4d8baed1498aa5b913f954
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix thrown weapon placement condition
When attacking with spear, throwing axe or dagger:
Only prevent placement on map tiles that are either impassable water
or ethereal void (unless an object is already present).
Fixes thrown weapons not being placed on passable water (e.g. shore).
Changed paths:
devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
diff --git a/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua b/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
index e9e77234be1..08d9823737f 100644
--- a/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
+++ b/devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
@@ -1643,8 +1643,26 @@ function combat_range_weapon_1D5F9(attacker, target_x, target_y, target_z, weapo
end
if removal_candidate ~= nil then
Actor.inv_remove_obj(attacker, removal_candidate)
+
+ local function can_place_at(x, y, z)
+ -- Helper function to check if thrown weapon can be placed at target coordinates
+
+ local dest_tile_num = map_get_tile_num(x, y, z, true)
+
+ -- Tile flags: water and impassable
+ local bool is_impassable_water = tile_get_flag(dest_tile_num, 1, 0) and tile_get_flag(dest_tile_num, 1, 1)
+ -- Ethereal void tile
+ local bool is_ethereal_void = dest_tile_num >= 252 and dest_tile_num <= 255
+
+ -- Do not place on impassable water or ethereal void
+ -- unless there already is an object at the destination
+ -- (passable water is OK, e.g. shore tiles)
+ return not ((is_impassable_water or is_ethereal_void) and map_get_obj(x, y, z) == nil)
+ end
+
-- Do not place thrown weapon if target is an actor
- if (coll_tiles[1].foe == mil or coll_tiles[1].foe.luatype ~= "actor") and map_is_water(pre_coll_tiles[1].x, pre_coll_tiles[1].y, pre_coll_tiles[1].z) == false then
+ if (coll_tiles[1].foe == mil or coll_tiles[1].foe.luatype ~= "actor")
+ and can_place_at(pre_coll_tiles[1].x, pre_coll_tiles[1].y, pre_coll_tiles[1].z) then
local obj = Obj.new(weapon_obj_n);
obj.ok_to_take = true
obj.temporary = true
Commit: a9aa083d8ffd73caf847455f031ca26ba2c63408
https://github.com/scummvm/scummvm/commit/a9aa083d8ffd73caf847455f031ca26ba2c63408
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix movability check when pushing
Behave closer to the original when using the (m)ove action
with a target on the map:
- Delay the check for movability until after printing selected
move direction
- Always do a weight check, even for actors
- Allow multi-tile actors to be pushed
(e.g. Ultima 6 hydras)
- Do not allow dragons to be pushed in Ultima 6
- Use unscaled weight to prevent float conversion
With these changes it should no longer be possible to push
certain enemies (e.g. gargoyles).
Changed paths:
engines/ultima/nuvie/core/events.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index b7b57086f68..a6125b4be30 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1213,15 +1213,9 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
return false;
}
- if (push_actor) {
- if (!push_actor->can_be_moved() || push_actor->get_tile_type() != ACTOR_ST) {
- scroll->display_string("Not possible\n\n");
- scroll->display_prompt();
- endAction();
- return false;
- }
+ if (push_actor)
from = push_actor->get_location();
- } else {
+ else {
if (push_obj->is_on_map()) {
from = MapCoord(push_obj->x, push_obj->y, push_obj->z);
} else {
@@ -1270,6 +1264,22 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
endAction();
return true;
}
+
+ if (push_actor || push_obj->is_on_map()) {
+ const uint16 pushObjN = push_obj ? push_obj->obj_n : push_actor->get_obj_n();
+ // Objects/Actors with a base weight of 0 are not movable
+ bool isUnmovable = obj_manager->get_obj_weight_unscaled(pushObjN) == 0;
+ // U6 does not allow pushing dragons
+ if (game->get_game_type() == NUVIE_GAME_U6)
+ isUnmovable = isUnmovable || pushObjN == OBJ_U6_DRAGON;
+
+ if (isUnmovable || (push_actor && !push_actor->can_be_moved())) {
+ scroll->display_string("Not possible\n\n");
+ scroll->display_prompt();
+ endAction();
+ return false;
+ }
+ }
CanDropOrMoveMsg can_move_check;
if (push_obj && (can_move_check = map_window->can_drop_or_move_obj(to.x, to.y, player->get_actor(), push_obj))
!= MSG_SUCCESS) {
@@ -1399,9 +1409,6 @@ bool Events::pushFrom(const MapCoord &target) {
endAction(true);
return false;
}
- if (push_obj
- && (obj_manager->get_obj_weight(push_obj, OBJ_WEIGHT_EXCLUDE_CONTAINER_ITEMS) == 0))
- push_obj = nullptr;
if (push_actor && push_actor->is_visible()) {
scroll->display_string(push_actor->get_name());
Commit: 8bae96120863e32ad4fd1aca0fb39ade89695aa3
https://github.com/scummvm/scummvm/commit/8bae96120863e32ad4fd1aca0fb39ade89695aa3
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix condition for pushing actors
When using the (m)ove action with actors on the map:
- Do a strength check
- Prevent pushing self
Changed paths:
engines/ultima/nuvie/core/events.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index a6125b4be30..307811ab3c1 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1289,23 +1289,24 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
return true;
}
DEBUG(0, LEVEL_WARNING, "deduct moves from player\n");
- // FIXME: the random chance here is just made up, I don't know what
- // kind of check U6 did ("Failed.\n\n")
+
if (push_actor) {
- // if actor can take a step, do so; else 50% chance of pushing them
- if (push_actor == player->get_actor()) {
- if (player->check_walk_delay() && !view_manager->gumps_are_active()) {
- player->moveRelative(pushrel_x, pushrel_y);
- game->time_changed();
- }
- } else if (map->lineTest(to.x, to.y, to.x, to.y, to.z, LT_HitActors | LT_HitUnpassable, lt))
+ const auto playerActor = player->get_actor();
+ auto strengthCheckFailed = [=]() {
+ // Using adjusted strength here, which takes cursed status into account
+ const uint playerStr = script->call_actor_str_adj(playerActor);
+ const uint pushedActorStr = script->call_actor_str_adj(push_actor);
+ return (pushedActorStr / 2 + 30 - playerStr) / 2 > getRandom(29) + 1;
+ };
+
+ // Can not push self and must pass strength test
+ if (push_actor == playerActor || strengthCheckFailed())
+ scroll->display_string("Failed.\n\n");
+ else if (map->lineTest(to.x, to.y, to.x, to.y, to.z, LT_HitActors | LT_HitUnpassable, lt))
scroll->display_string("Blocked.\n\n");
- else if (!push_actor->moveRelative(pushrel_x, pushrel_y)) {
- if (NUVIE_RAND() % 2) { // already checked if target is passable
- push_actor->move(to.x, to.y, from.z, ACTOR_FORCE_MOVE | ACTOR_IGNORE_DANGER);
- player->subtract_movement_points(5);
- } else
- scroll->display_string("Failed.\n\n");
+ else {
+ push_actor->move(to.x, to.y, from.z, ACTOR_FORCE_MOVE | ACTOR_IGNORE_DANGER);
+ player->subtract_movement_points(5);
}
} else {
if (map_window->get_interface() != INTERFACE_IGNORE_BLOCK
Commit: 7d2aa52191bdaac08378c25a600685aa848bc68f
https://github.com/scummvm/scummvm/commit/7d2aa52191bdaac08378c25a600685aa848bc68f
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix message when pushing sitting actors
The correct message when attempting to push a sitting actor
is "Failed" not "Not possible".
Changed paths:
engines/ultima/nuvie/core/events.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index 307811ab3c1..0d9411cd9b0 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1273,7 +1273,7 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
if (game->get_game_type() == NUVIE_GAME_U6)
isUnmovable = isUnmovable || pushObjN == OBJ_U6_DRAGON;
- if (isUnmovable || (push_actor && !push_actor->can_be_moved())) {
+ if (isUnmovable) {
scroll->display_string("Not possible\n\n");
scroll->display_prompt();
endAction();
@@ -1300,7 +1300,7 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
};
// Can not push self and must pass strength test
- if (push_actor == playerActor || strengthCheckFailed())
+ if (push_actor == playerActor || !push_actor->can_be_moved() || strengthCheckFailed())
scroll->display_string("Failed.\n\n");
else if (map->lineTest(to.x, to.y, to.x, to.y, to.z, LT_HitActors | LT_HitUnpassable, lt))
scroll->display_string("Blocked.\n\n");
Commit: c68b2c39993be48b36f6c0ac8ace51f8d161aa91
https://github.com/scummvm/scummvm/commit/c68b2c39993be48b36f6c0ac8ace51f8d161aa91
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Do not allow selecting actor as push target on map
Cancel the move action and display "nowhere" as destination instead.
Matches original behavior. Also fixes a potential crash:
1. Enable hack move
2. Initiate a move action (default key: m)
3. Select a movable object or actor on the map
4. When prompted for a target, select a party member via keyboard
shortcut (default keys: 1-9)
This causes the selected actor's absolute coordinates to be passed to
Events::pushTo(sint16, sint16, bool).
However, the method expects relative coordinates.
For large enough numbers, an out-of-bounds access to
iAVLTree *ObjManager::surface[64] and a subsequent dereference of the
resulting pointer will then crash the game.
Changed paths:
engines/ultima/nuvie/core/events.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index 0d9411cd9b0..52445650006 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -430,6 +430,11 @@ bool Events::select_obj(Obj *obj, Actor *actor) {
bool Events::select_actor(Actor *actor) {
assert(mode == INPUT_MODE);
+ if (last_mode == PUSH_MODE && !move_in_inventory && (push_actor || push_obj)) {
+ // Prevent selecting an actor as target when pushing on the map
+ cancelAction();
+ return false;
+ }
input.type = EVENTINPUT_MAPCOORD;
input.actor = actor;
input.set_loc(actor->get_location());
Commit: 8ec62fbd70ccb0e1da484368dace3e001254ae15
https://github.com/scummvm/scummvm/commit/8ec62fbd70ccb0e1da484368dace3e001254ae15
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Constify some methods
Also, make ObjManager::get_obj_weight() not modify its arguments.
Changed paths:
engines/ultima/nuvie/core/obj.cpp
engines/ultima/nuvie/core/obj.h
engines/ultima/nuvie/core/obj_manager.cpp
engines/ultima/nuvie/core/obj_manager.h
engines/ultima/nuvie/gui/widgets/map_window.cpp
engines/ultima/nuvie/gui/widgets/map_window.h
engines/ultima/nuvie/script/script.cpp
engines/ultima/nuvie/script/script.h
diff --git a/engines/ultima/nuvie/core/obj.cpp b/engines/ultima/nuvie/core/obj.cpp
index 465876b2cf1..fc3b79ad222 100644
--- a/engines/ultima/nuvie/core/obj.cpp
+++ b/engines/ultima/nuvie/core/obj.cpp
@@ -245,7 +245,7 @@ bool Obj::remove(Obj *obj) {
return true;
}
-Obj *Obj::find_in_container(uint16 objN, uint8 quality_, bool match_quality, uint8 frameN, bool match_frame_n, Obj **prev_obj) {
+Obj *Obj::find_in_container(uint16 objN, uint8 quality_, bool match_quality, uint8 frameN, bool match_frame_n, Obj **prev_obj) const {
U6Link *link;
Obj *obj;
@@ -306,7 +306,7 @@ uint32 Obj::get_total_qty(uint16 match_obj_n) {
return total_qty;
}
-uint32 Obj::container_count_objects() {
+uint32 Obj::container_count_objects() const {
uint32 count = 0;
U6Link *link;
diff --git a/engines/ultima/nuvie/core/obj.h b/engines/ultima/nuvie/core/obj.h
index 341f69f0720..92cf542294c 100644
--- a/engines/ultima/nuvie/core/obj.h
+++ b/engines/ultima/nuvie/core/obj.h
@@ -153,7 +153,7 @@ public:
}
void make_container();
Obj *get_container_obj(bool recursive = false);
- uint32 container_count_objects();
+ uint32 container_count_objects() const;
uint8 get_engine_loc() const;
Actor *get_actor_holding_obj();
@@ -177,7 +177,7 @@ public:
bool remove(Obj *obj);
- Obj *find_in_container(uint16 obj_n, uint8 quality, bool match_quality = OBJ_MATCH_QUALITY, uint8 frame_n = 0, bool match_frame_n = OBJ_NOMATCH_FRAME_N, Obj **prev_obj = nullptr);
+ Obj *find_in_container(uint16 obj_n, uint8 quality, bool match_quality = OBJ_MATCH_QUALITY, uint8 frame_n = 0, bool match_frame_n = OBJ_NOMATCH_FRAME_N, Obj **prev_obj = nullptr) const;
uint32 get_total_qty(uint16 match_obj_n);
diff --git a/engines/ultima/nuvie/core/obj_manager.cpp b/engines/ultima/nuvie/core/obj_manager.cpp
index b7ae0c42a71..9bdf9ba98f7 100644
--- a/engines/ultima/nuvie/core/obj_manager.cpp
+++ b/engines/ultima/nuvie/core/obj_manager.cpp
@@ -559,7 +559,7 @@ bool ObjManager::is_damaging(uint16 x, uint16 y, uint8 level) {
return false;
}
-bool ObjManager::is_stackable(const Obj *obj) {
+bool ObjManager::is_stackable(const Obj *obj) const {
if (obj == nullptr)
return false;
if (obj->is_readied()) // readied objects cannot be stacked --SB-X
@@ -734,7 +734,7 @@ bool ObjManager::is_breakable(const Obj *obj) {
return false;
}
-bool ObjManager::can_store_obj(Obj *target, Obj *src) {
+bool ObjManager::can_store_obj(const Obj *target, Obj *src) const {
if (target == src || !can_get_obj(src) || target == nullptr)
return false;
@@ -831,7 +831,7 @@ bool ObjManager::can_store_obj(Obj *target, Obj *src) {
return false;
}
-bool ObjManager::can_get_obj(Obj *obj) {
+bool ObjManager::can_get_obj(Obj *obj) const {
// objects with 0 weight aren't gettable.
//255 is the max weight and means an object is movable but not getable.
//we can't get object that contains toptiles either. This makes dragon bits ungettable etc.
@@ -852,7 +852,7 @@ bool ObjManager::can_get_obj(Obj *obj) {
return false;
}
-bool ObjManager::has_reduced_weight(uint16 obj_n) {
+bool ObjManager::has_reduced_weight(uint16 obj_n) const {
// FIXME: HERE BE HARDCODED VALUES! FIXME: not sure if this list is complete!
if (game_type == NUVIE_GAME_U6) { // luteijn: I only know about U6...
if ((obj_n == OBJ_U6_GOLD)
@@ -916,7 +916,7 @@ bool ObjManager::has_reduced_weight(uint16 obj_n) {
return false;
}
-bool ObjManager::has_toptile(const Obj *obj) {
+bool ObjManager::has_toptile(const Obj *obj) const {
uint8 i = 1;
Tile *tile = tile_manager->get_tile(get_obj_tile_num(obj->obj_n) + obj->frame_n);
@@ -1258,7 +1258,7 @@ const char *ObjManager::get_obj_name(uint16 obj_n, uint8 frame_n) {
return tile_manager->lookAtTile(get_obj_tile_num(obj_n) + frame_n, 0, false);
}
-float ObjManager::get_obj_weight(uint16 obj_n) {
+float ObjManager::get_obj_weight(uint16 obj_n) const {
float weight = (float)get_obj_weight_unscaled(obj_n);
if (has_reduced_weight(obj_n)) {
weight /= 10;
@@ -1267,14 +1267,12 @@ float ObjManager::get_obj_weight(uint16 obj_n) {
return weight / 10;
}
-float ObjManager::get_obj_weight(Obj *obj, bool include_container_items, bool scale, bool include_qty) {
+float ObjManager::get_obj_weight(const Obj *obj, bool include_container_items, bool scale, bool include_qty) const {
float weight = obj_weight[obj->obj_n];
if (is_stackable(obj)) {
if (include_qty) {
- if (obj->qty == 0)
- obj->qty = 1;
- weight *= obj->qty;
+ weight *= obj->qty ? obj->qty : 1;
}
/* luteijn: only some need to be divided by an extra 10 for a total of 100.
* unfortunately can't seem to find a tileflag that controls this so would have to be hardcoded!
@@ -1297,11 +1295,11 @@ float ObjManager::get_obj_weight(Obj *obj, bool include_container_items, bool sc
return weight;
}
-uint16 ObjManager::get_obj_tile_num(uint16 obj_num) { //assume obj_num is < 1024 :)
+uint16 ObjManager::get_obj_tile_num(uint16 obj_num) const { //assume obj_num is < 1024 :)
return obj_to_tile[obj_num];
}
-inline bool ObjManager::is_corpse(const Obj *obj) {
+inline bool ObjManager::is_corpse(const Obj *obj) const {
if (game_type == NUVIE_GAME_U6) {
switch (obj->obj_n) {
case OBJ_U6_DEAD_BODY:
@@ -1332,7 +1330,7 @@ inline bool ObjManager::is_corpse(const Obj *obj) {
return false;
}
-uint16 ObjManager::get_obj_tile_num(const Obj *obj) { //assume obj_num is < 1024 :)
+uint16 ObjManager::get_obj_tile_num(const Obj *obj) const { //assume obj_num is < 1024 :)
if (custom_actor_tiles && is_corpse(obj)) {
return Game::get_game()->get_actor_manager()->get_actor(obj->quality)->get_custom_tile_num(obj->obj_n);
}
diff --git a/engines/ultima/nuvie/core/obj_manager.h b/engines/ultima/nuvie/core/obj_manager.h
index 39aea9866d7..cf38c2af7b5 100644
--- a/engines/ultima/nuvie/core/obj_manager.h
+++ b/engines/ultima/nuvie/core/obj_manager.h
@@ -142,15 +142,15 @@ public:
bool is_damaging(uint16 x, uint16 y, uint8 level);
uint8 is_passable(uint16 x, uint16 y, uint8 level);
bool is_forced_passable(uint16 x, uint16 y, uint8 level);
- bool is_stackable(const Obj *obj);
+ bool is_stackable(const Obj *obj) const;
bool is_breakable(const Obj *obj);
- bool can_store_obj(Obj *target, Obj *src); // Bag, open chest, spellbook.
- bool can_get_obj(Obj *obj);
- bool has_reduced_weight(uint16 obj_n);
- bool has_reduced_weight(const Obj *obj) {
+ bool can_store_obj(const Obj *target, Obj *src) const; // Bag, open chest, spellbook.
+ bool can_get_obj(Obj *obj) const;
+ bool has_reduced_weight(uint16 obj_n) const;
+ bool has_reduced_weight(const Obj *obj) const {
return has_reduced_weight(obj->obj_n);
}
- bool has_toptile(const Obj *obj);
+ bool has_toptile(const Obj *obj) const;
bool obj_is_damaging(const Obj *obj, Actor *actor = nullptr); // if actor, it will damage and display text
bool is_door(uint16 x, uint16 y, uint8 level);
@@ -167,9 +167,9 @@ public:
Obj *get_objBasedAt(uint16 x, uint16 y, uint8 level, bool top_obj, bool include_ignored_objects = true, Obj *excluded_obj = nullptr);
Obj *get_tile_obj(uint16 obj_n);
- uint16 get_obj_tile_num(uint16 obj_num);
- inline bool is_corpse(const Obj *obj);
- uint16 get_obj_tile_num(const Obj *obj);
+ uint16 get_obj_tile_num(uint16 obj_num) const;
+ inline bool is_corpse(const Obj *obj) const;
+ uint16 get_obj_tile_num(const Obj *obj) const;
void set_obj_tile_num(uint16 obj_num, uint16 tile_num);
U6LList *get_actor_inventory(uint16 actor_num);
@@ -194,11 +194,11 @@ public:
const char *get_obj_name(uint16 obj_n);
const char *get_obj_name(uint16 obj_n, uint8 frame_n);
- float get_obj_weight(Obj *obj, bool include_container_items = OBJ_WEIGHT_INCLUDE_CONTAINER_ITEMS, bool scale = true, bool include_qty = true);
- uint8 get_obj_weight_unscaled(uint16 obj_n) {
+ float get_obj_weight(const Obj *obj, bool include_container_items = OBJ_WEIGHT_INCLUDE_CONTAINER_ITEMS, bool scale = true, bool include_qty = true) const;
+ uint8 get_obj_weight_unscaled(uint16 obj_n) const {
return obj_weight[obj_n];
}
- float get_obj_weight(uint16 obj_n);
+ float get_obj_weight(uint16 obj_n) const;
void animate_forwards(Obj *obj, uint32 loop_count = 1);
void animate_backwards(Obj *obj, uint32 loop_count = 1);
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.cpp b/engines/ultima/nuvie/gui/widgets/map_window.cpp
index 8529ef167fc..b6629dd85e4 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.cpp
+++ b/engines/ultima/nuvie/gui/widgets/map_window.cpp
@@ -478,7 +478,7 @@ bool MapWindow::can_display_obj(uint16 x, uint16 y, Obj *obj) {
return true;
}
-bool MapWindow::tile_is_black(uint16 x, uint16 y, Obj *obj) {
+bool MapWindow::tile_is_black(uint16 x, uint16 y, const Obj *obj) const {
if (game->using_hackmove())
return false;
if (!MapCoord(x, y, cur_level).is_visible()) // tmpBufTileIsBlack will crash if called (doesn't happen in gdb)
@@ -1565,7 +1565,7 @@ void MapWindow::reshapeBoundary() {
}
}
-inline bool MapWindow::tmpBufTileIsBlack(uint16 x, uint16 y) {
+inline bool MapWindow::tmpBufTileIsBlack(uint16 x, uint16 y) const {
if (tmp_map_buf[y * tmp_map_width + x] == 0)
return true;
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.h b/engines/ultima/nuvie/gui/widgets/map_window.h
index a7978af53ae..f5dd44cf488 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.h
+++ b/engines/ultima/nuvie/gui/widgets/map_window.h
@@ -242,7 +242,7 @@ public:
return look_on_left_click;
}
bool is_on_screen(uint16 x, uint16 y, uint8 z);
- bool tile_is_black(uint16 x, uint16 y, Obj *obj = nullptr); // subtracts cur_x and cur_y
+ bool tile_is_black(uint16 x, uint16 y, const Obj *obj = nullptr) const; // subtracts cur_x and cur_y
const char *look(uint16 x, uint16 y, bool show_prefix = true);
const char *lookAtCursor(bool show_prefix = true) {
return (look(cursor_x, cursor_y, show_prefix));
@@ -357,7 +357,7 @@ protected:
bool boundaryLookThroughWindow(uint16 tile_num, uint16 x, uint16 y);
void reshapeBoundary();
- inline bool tmpBufTileIsBlack(uint16 x, uint16 y);
+ inline bool tmpBufTileIsBlack(uint16 x, uint16 y) const;
bool tmpBufTileIsBoundary(uint16 x, uint16 y);
bool tmpBufTileIsWall(uint16 x, uint16 y, NuvieDir direction);
diff --git a/engines/ultima/nuvie/script/script.cpp b/engines/ultima/nuvie/script/script.cpp
index 44748793155..82e34642842 100644
--- a/engines/ultima/nuvie/script/script.cpp
+++ b/engines/ultima/nuvie/script/script.cpp
@@ -1308,7 +1308,7 @@ bool Script::call_actor_use_effect(Obj *effect_obj, Actor *actor) {
return call_function("actor_use_effect", 2, 0);
}
-bool Script::call_can_get_obj_override(Obj *obj) {
+bool Script::call_can_get_obj_override(Obj *obj) const {
lua_getglobal(L, "can_get_obj_override");
nscript_obj_new(L, obj);
@@ -1349,7 +1349,7 @@ bool Script::call_is_ranged_select(UseCodeType operation) {
return lua_toboolean(L, -1);
}
-bool Script::call_function(const char *func_name, int num_args, int num_return, bool print_stacktrace) {
+bool Script::call_function(const char *func_name, int num_args, int num_return, bool print_stacktrace) const{
int start_idx = lua_gettop(L);
int error_index = 0;
diff --git a/engines/ultima/nuvie/script/script.h b/engines/ultima/nuvie/script/script.h
index 54f9342bb26..27265f92b03 100644
--- a/engines/ultima/nuvie/script/script.h
+++ b/engines/ultima/nuvie/script/script.h
@@ -156,12 +156,12 @@ public:
bool call_magic_get_spell_list(Spell **spell_list);
bool call_actor_use_effect(Obj *effect_obj, Actor *actor);
- bool call_function(const char *func_name, int num_args, int num_return, bool print_stacktrace = true);
+ bool call_function(const char *func_name, int num_args, int num_return, bool print_stacktrace = true) const;
ScriptThread *call_function_in_thread(const char *function_name);
bool run_lua_file(const char *filename);
bool call_moonstone_set_loc(uint8 phase, MapCoord location); //this is a hack until we have 'use' moonstone in script.
bool call_advance_time(uint16 minutes);
- bool call_can_get_obj_override(Obj *obj);
+ bool call_can_get_obj_override(Obj *obj) const;
bool call_out_of_ammo(Actor *attacker, Obj *weapon, bool print_message);
bool call_is_avatar_dead();
bool call_is_ranged_select(UseCodeType operation);
Commit: 06eac59abb72d08618401af43d604627763f82bc
https://github.com/scummvm/scummvm/commit/06eac59abb72d08618401af43d604627763f82bc
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix move/drop to container on map
can_drop_or_move_obj() only tested for containers if a collision
with a missile boundary occured.
Change this and refactor the relevant code.
Makes it possible for (d)rop and (m)ove actions to place items
into containers on the map.
Changed paths:
engines/ultima/nuvie/gui/widgets/map_window.cpp
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.cpp b/engines/ultima/nuvie/gui/widgets/map_window.cpp
index b6629dd85e4..43e004da9bc 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.cpp
+++ b/engines/ultima/nuvie/gui/widgets/map_window.cpp
@@ -1682,38 +1682,29 @@ CanDropOrMoveMsg MapWindow::can_drop_or_move_obj(uint16 x, uint16 y, Actor *acto
if (actor_loc.distance(target_loc) > 5 && get_interface() == INTERFACE_NORMAL)
return MSG_OUT_OF_RANGE;
+ bool blocked = false;
uint8 lt_flags = (game_type == NUVIE_GAME_U6) ? LT_HitMissileBoundary : 0; //FIXME this probably isn't quite right for MD/SE
if (map->lineTest(actor_loc.x, actor_loc.y, x, y, actor_loc.z, lt_flags, lt, 0, obj)) {
MapCoord hit_loc = MapCoord(lt.hit_x, lt.hit_y, lt.hit_level);
- if (obj_loc.distance(target_loc) != 1 || hit_loc.distance(target_loc) != 1) {
- if (lt.hitObj && target_loc == hit_loc) {
- if (obj_manager->can_store_obj(lt.hitObj, obj)) //if we are moving onto a container.
- return MSG_SUCCESS;
- }
- return MSG_BLOCKED;
- }
- // trying to push object one tile away from actor
- if (map->lineTest(obj->x, obj->y, x, y, actor_loc.z, lt_flags, lt, 0, obj)) {
- if (lt.hitObj) {
- if (obj_manager->can_store_obj(lt.hitObj, obj)) //if we are moving onto a container.
- return MSG_SUCCESS;
- /* else // I don't think these are needed
- {
- // We can place an object on a bench or table. Or on any other object if
- // the object is passable and not on a boundary.
-
- Tile *obj_tile = obj_manager->get_obj_tile(lt.hitObj->obj_n, lt.hitObj->frame_n);
- if(!obj_tile) // shouldn't happen
- return MSG_NO_TILE;
- if((obj_tile->flags3 & TILEFLAG_CAN_PLACE_ONTOP)
- || (obj_tile->passable && !map->is_boundary(lt.hit_x, lt.hit_y, lt.hit_level)) )
- return MSG_SUCCESS;
- }*/
- }
- return MSG_BLOCKED;
- }
+ if (obj_loc.distance(target_loc) != 1 || hit_loc.distance(target_loc) != 1)
+ blocked = true; // Just set a bool and don't return yet: blocker might be a suitable container.
+ else // trying to push object one tile away from actor
+ blocked = map->lineTest(obj->x, obj->y, x, y, actor_loc.z, lt_flags, lt, 0, obj);
}
+ const Obj* potentialContainer = nullptr;
+ if (blocked) {
+ if (lt.hitObj && MapCoord(lt.hitObj) == target_loc)
+ potentialContainer = lt.hitObj;
+ } else
+ potentialContainer = dest_obj;
+
+ if (potentialContainer && obj_manager->can_store_obj(potentialContainer, obj)) //if we are moving onto a container.
+ return MSG_SUCCESS;
+
+ if (blocked)
+ return MSG_BLOCKED;
+
const Tile *tile;
if (dest_obj)
tile = obj_manager->get_obj_tile(dest_obj->obj_n, dest_obj->frame_n);
Commit: 5eaa9ddda69991d2ffaaaf0bf9e17a9d85daccde
https://github.com/scummvm/scummvm/commit/5eaa9ddda69991d2ffaaaf0bf9e17a9d85daccde
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix instance of inventory vs map coords comparison
Changed paths:
engines/ultima/nuvie/gui/widgets/map_window.cpp
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.cpp b/engines/ultima/nuvie/gui/widgets/map_window.cpp
index 43e004da9bc..b790fe519ee 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.cpp
+++ b/engines/ultima/nuvie/gui/widgets/map_window.cpp
@@ -1686,7 +1686,7 @@ CanDropOrMoveMsg MapWindow::can_drop_or_move_obj(uint16 x, uint16 y, Actor *acto
uint8 lt_flags = (game_type == NUVIE_GAME_U6) ? LT_HitMissileBoundary : 0; //FIXME this probably isn't quite right for MD/SE
if (map->lineTest(actor_loc.x, actor_loc.y, x, y, actor_loc.z, lt_flags, lt, 0, obj)) {
MapCoord hit_loc = MapCoord(lt.hit_x, lt.hit_y, lt.hit_level);
- if (obj_loc.distance(target_loc) != 1 || hit_loc.distance(target_loc) != 1)
+ if (in_inventory || obj_loc.distance(target_loc) != 1 || hit_loc.distance(target_loc) != 1)
blocked = true; // Just set a bool and don't return yet: blocker might be a suitable container.
else // trying to push object one tile away from actor
blocked = map->lineTest(obj->x, obj->y, x, y, actor_loc.z, lt_flags, lt, 0, obj);
Commit: 1bca817346553e7d377b1382e2398306d58f19be
https://github.com/scummvm/scummvm/commit/1bca817346553e7d377b1382e2398306d58f19be
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Constify some methods
Changed paths:
engines/ultima/nuvie/actors/actor_manager.cpp
engines/ultima/nuvie/actors/actor_manager.h
engines/ultima/nuvie/core/obj_manager.cpp
engines/ultima/nuvie/core/obj_manager.h
diff --git a/engines/ultima/nuvie/actors/actor_manager.cpp b/engines/ultima/nuvie/actors/actor_manager.cpp
index e5e54a2ecf2..865a84658de 100644
--- a/engines/ultima/nuvie/actors/actor_manager.cpp
+++ b/engines/ultima/nuvie/actors/actor_manager.cpp
@@ -519,7 +519,7 @@ ActorList *ActorManager::get_actor_list() {
return _actors;
}
-Actor *ActorManager::get_actor(uint8 actor_num) {
+Actor *ActorManager::get_actor(uint8 actor_num) const {
return actors[actor_num];
}
diff --git a/engines/ultima/nuvie/actors/actor_manager.h b/engines/ultima/nuvie/actors/actor_manager.h
index d5277f105b6..675dba6f452 100644
--- a/engines/ultima/nuvie/actors/actor_manager.h
+++ b/engines/ultima/nuvie/actors/actor_manager.h
@@ -78,7 +78,7 @@ public:
ActorList *filter_alignment(ActorList *list, ActorAlignment align);
ActorList *filter_party(ActorList *list);
- Actor *get_actor(uint8 actor_num);
+ Actor *get_actor(uint8 actor_num) const;
Actor *get_actor(uint16 x, uint16 y, uint8 z, bool inc_surrounding_objs = true, Actor *excluded_actor = nullptr);
Actor *get_actor_holding_obj(Obj *obj);
diff --git a/engines/ultima/nuvie/core/obj_manager.cpp b/engines/ultima/nuvie/core/obj_manager.cpp
index 9bdf9ba98f7..65f637d1b46 100644
--- a/engines/ultima/nuvie/core/obj_manager.cpp
+++ b/engines/ultima/nuvie/core/obj_manager.cpp
@@ -943,7 +943,7 @@ bool ObjManager::has_toptile(const Obj *obj) const {
//gets the linked list of objects at a particular location.
-U6LList *ObjManager::get_obj_list(uint16 x, uint16 y, uint8 level) {
+U6LList *ObjManager::get_obj_list(uint16 x, uint16 y, uint8 level) const {
WRAP_COORD(x, level); // wrap on map edge
WRAP_COORD(y, level);
@@ -1537,7 +1537,7 @@ Obj *ObjManager::loadObj(NuvieIO *buf) {
}
-iAVLTree *ObjManager::get_obj_tree(uint16 x, uint16 y, uint8 level) {
+iAVLTree *ObjManager::get_obj_tree(uint16 x, uint16 y, uint8 level) const {
if (level == 0) {
x >>= 7; // x = floor(x / 128) 128 = superchunk width
y >>= 7; // y = floor(y / 128) 128 = superchunk height
@@ -1551,11 +1551,11 @@ iAVLTree *ObjManager::get_obj_tree(uint16 x, uint16 y, uint8 level) {
return dungeon[level - 1];
}
-inline iAVLKey ObjManager::get_obj_tree_key(Obj *obj) {
+inline iAVLKey ObjManager::get_obj_tree_key(Obj *obj) const {
return get_obj_tree_key(obj->x, obj->y, obj->z);
}
-iAVLKey ObjManager::get_obj_tree_key(uint16 x, uint16 y, uint8 level) {
+iAVLKey ObjManager::get_obj_tree_key(uint16 x, uint16 y, uint8 level) const {
iAVLKey key;
if (level == 0)
key._int = y * 1024 + x;
diff --git a/engines/ultima/nuvie/core/obj_manager.h b/engines/ultima/nuvie/core/obj_manager.h
index cf38c2af7b5..70a95a6afea 100644
--- a/engines/ultima/nuvie/core/obj_manager.h
+++ b/engines/ultima/nuvie/core/obj_manager.h
@@ -154,7 +154,7 @@ public:
bool obj_is_damaging(const Obj *obj, Actor *actor = nullptr); // if actor, it will damage and display text
bool is_door(uint16 x, uint16 y, uint8 level);
- U6LList *get_obj_list(uint16 x, uint16 y, uint8 level);
+ U6LList *get_obj_list(uint16 x, uint16 y, uint8 level) const;
Tile *get_obj_tile(uint16 obj_n, uint8 frame_n);
const Tile *get_obj_tile(uint16 x, uint16 y, uint8 level, bool top_obj = true);
@@ -222,10 +222,10 @@ protected:
bool addObjToContainer(U6LList *list, Obj *obj);
Obj *loadObj(NuvieIO *buf);
- iAVLTree *get_obj_tree(uint16 x, uint16 y, uint8 level);
+ iAVLTree *get_obj_tree(uint16 x, uint16 y, uint8 level) const;
- iAVLKey get_obj_tree_key(Obj *obj);
- iAVLKey get_obj_tree_key(uint16 x, uint16 y, uint8 level);
+ iAVLKey get_obj_tree_key(Obj *obj) const;
+ iAVLKey get_obj_tree_key(uint16 x, uint16 y, uint8 level) const;
//inline U6LList *ObjManager::get_schunk_list(uint16 x, uint16 y, uint8 level);
bool temp_obj_list_add(Obj *obj);
Commit: 8f7038c615ccf3b9779754885f96776830252ad9
https://github.com/scummvm/scummvm/commit/8f7038c615ccf3b9779754885f96776830252ad9
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Add method doesOccupyLocation() to Actor class
Changed paths:
engines/ultima/nuvie/actors/actor.cpp
engines/ultima/nuvie/actors/actor.h
diff --git a/engines/ultima/nuvie/actors/actor.cpp b/engines/ultima/nuvie/actors/actor.cpp
index 886dd979d0b..1427765cb92 100644
--- a/engines/ultima/nuvie/actors/actor.cpp
+++ b/engines/ultima/nuvie/actors/actor.cpp
@@ -1929,5 +1929,30 @@ void Actor::set_custom_tile_num(uint16 obj_num, uint16 tile_num) {
(*custom_tile_tbl)[obj_num] = tile_num;
}
+bool Actor::doesOccupyLocation(uint16 lx, uint16 ly, uint8 lz, bool incDoubleTile, bool incSurroundingObjs) const {
+ if (z != lz)
+ return false;
+
+ const Tile *const tile = get_tile();
+
+ // If actor has double height, also check tile S of location.
+ // If actor has double width, also check tile E of location.
+ for (int relX = 0; relX < 2 && (tile->dbl_width || !relX); ++relX)
+ for (int relY = 0; relY < 2 && (tile->dbl_height || !relY); ++relY)
+ if (relY && !incDoubleTile)
+ goto NotFound;
+ else if (WRAPPED_COORD(lx + relX, lz) == x && WRAPPED_COORD(ly + relY, lz) == y)
+ return true;
+
+ NotFound:
+
+ if (incSurroundingObjs)
+ for (const Obj *obj : surrounding_objects)
+ if (obj && obj->x == WRAPPED_COORD(lx, lz) && obj->y == WRAPPED_COORD(ly, lz) && obj->z == lz)
+ return true;
+
+ return false;
+}
+
} // End of namespace Nuvie
} // End of namespace Ultima
diff --git a/engines/ultima/nuvie/actors/actor.h b/engines/ultima/nuvie/actors/actor.h
index 87e1eca5612..cb66918226f 100644
--- a/engines/ultima/nuvie/actors/actor.h
+++ b/engines/ultima/nuvie/actors/actor.h
@@ -332,6 +332,16 @@ public:
bool is_temp() const {
return temp_actor;
}
+ /**
+ * @brief Does any tile of this actor occupy the given world location?
+ * @param lx world coordinate
+ * @param ly world coordinate
+ * @param lz level
+ * @param incDoubleTile include all tiles of double width/height actors
+ * @param incSurroundingObjs include surrounding actor objects
+ * @return true if actor occupies location, false otherwise
+ */
+ virtual bool doesOccupyLocation(uint16 lx, uint16 ly, uint8 lz, bool incDoubleTile = true, bool incSurroundingObjs = true) const;
//for lack of a better name:
bool is_met() const {
Commit: 1980c188404702c6bbe35c433cca0e78c8f441be
https://github.com/scummvm/scummvm/commit/1980c188404702c6bbe35c433cca0e78c8f441be
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Add method findActorAt() to ActorManager
The method can be used to find an actor matched by a predicate
function.
It is intended to be used in situations where _all_ actors on a tile
need to pass some tests (e.g. for passability) instead of just the
first one found.
Changed paths:
engines/ultima/nuvie/actors/actor_manager.cpp
engines/ultima/nuvie/actors/actor_manager.h
diff --git a/engines/ultima/nuvie/actors/actor_manager.cpp b/engines/ultima/nuvie/actors/actor_manager.cpp
index 865a84658de..2fceea31f89 100644
--- a/engines/ultima/nuvie/actors/actor_manager.cpp
+++ b/engines/ultima/nuvie/actors/actor_manager.cpp
@@ -1190,5 +1190,35 @@ Std::set<Std::string> ActorManager::getCustomTileFilenames(const Common::Path &d
return files;
}
+Actor *ActorManager::findActorAtImpl(uint16 x, uint16 y, uint8 z, bool (*predicateWrapper)(void *predicate, const Actor *), bool incDoubleTile, bool incSurroundingObjs, void *predicate) const {
+
+ for (uint16 i = 0; i < ACTORMANAGER_MAX_ACTORS; ++i)
+ // Exclude surrounding objects here since we can get them directly via the AVL tree instead of going through earch actor's surrounding objects list
+ if (actors[i] && actors[i]->doesOccupyLocation(x, y, z, incDoubleTile, false) && predicateWrapper(predicate, actors[i]))
+ return actors[i];
+
+ if (incSurroundingObjs) {
+ // Look for actor objects (e.g. Silver Serpent body, Hydra parts, etc.)
+ const U6LList *const obj_list = obj_manager->get_obj_list(x, y, z);
+
+ if (obj_list) {
+ for (const U6Link *link = obj_list->start(); link != nullptr; link = link->next) {
+ const Obj *obj = (Obj *)link->data;
+
+ if (obj->is_actor_obj()) {
+ const uint8 actorNum = obj->obj_n == OBJ_U6_SILVER_SERPENT
+ && Game::get_game()->get_game_type() == NUVIE_GAME_U6 ? obj->qty : obj->quality;
+ Actor *actor = get_actor(actorNum);
+ if (actor && predicateWrapper(predicate, actor))
+ return actor;
+ }
+ }
+ }
+ }
+
+ // No match
+ return nullptr;
+}
+
} // End of namespace Nuvie
} // End of namespace Ultima
diff --git a/engines/ultima/nuvie/actors/actor_manager.h b/engines/ultima/nuvie/actors/actor_manager.h
index 675dba6f452..fe102b37d5e 100644
--- a/engines/ultima/nuvie/actors/actor_manager.h
+++ b/engines/ultima/nuvie/actors/actor_manager.h
@@ -82,6 +82,32 @@ public:
Actor *get_actor(uint16 x, uint16 y, uint8 z, bool inc_surrounding_objs = true, Actor *excluded_actor = nullptr);
Actor *get_actor_holding_obj(Obj *obj);
+ private:
+ Actor *findActorAtImpl(uint16 x, uint16 y, uint8 z, bool(*predicateWrapper)(void *, const Actor *), bool incDoubleTile, bool incSurroundingObjs, void *predicate) const;
+
+ public:
+ /**
+ * @brief Find first actor at location for which predicate function returns true
+ * @param x world coordinate
+ * @param y world coordinate
+ * @param z level
+ * @param predicate predicate function/lambda of the form: bool f(const Actor*)
+ * @param incDoubleTile include all tiles of double width/height actors
+ * @param incSurroundingObjs include surrounding actor objects
+ * @return pointer to actor or nullptr
+ */
+ template<typename F>
+ Actor *findActorAt(uint16 x, uint16 y, uint8 z, F predicate, bool incDoubleTile = true, bool incSurroundingObjs = true) {
+ // This is a template so it can take lambdas.
+ // To keep the implementation out of the header, the type of the passed lambda/function
+ // is hidden inside a wrapping lambda, which is then passed as a function pointer.
+ // TODO: Use a class for this.
+ auto predicateWrapper = +[](void *wrappedPredicate, const Actor *a) -> bool {
+ return (*(F*)wrappedPredicate)(a);
+ };
+ return findActorAtImpl(x, y, z, predicateWrapper, incDoubleTile, incSurroundingObjs, &predicate);
+ }
+
Actor *get_avatar();
Actor *get_player();
Commit: 77e77dc7f8f9c21a8dc5771e5cbced2e5cd6df4d
https://github.com/scummvm/scummvm/commit/77e77dc7f8f9c21a8dc5771e5cbced2e5cd6df4d
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Remove duplicated logic in get_actor()
Make ActorManager::get_actor() use findActorAt() to avoid code
duplication.
Disable now unused method get_multi_tile_actor().
Changed paths:
engines/ultima/nuvie/actors/actor_manager.cpp
diff --git a/engines/ultima/nuvie/actors/actor_manager.cpp b/engines/ultima/nuvie/actors/actor_manager.cpp
index 2fceea31f89..d17d03231a5 100644
--- a/engines/ultima/nuvie/actors/actor_manager.cpp
+++ b/engines/ultima/nuvie/actors/actor_manager.cpp
@@ -524,28 +524,13 @@ Actor *ActorManager::get_actor(uint8 actor_num) const {
}
Actor *ActorManager::get_actor(uint16 x, uint16 y, uint8 z, bool inc_surrounding_objs, Actor *excluded_actor) {
- uint16 i;
-
- for (i = 0; i < ACTORMANAGER_MAX_ACTORS; i++) {
- if (actors[i]->x == x && actors[i]->y == y && actors[i]->z == z && actors[i] != excluded_actor)
- return actors[i];
- }
-
- if (inc_surrounding_objs) {
- Obj *obj = obj_manager->get_obj(x, y, z);
- if (obj && obj->is_actor_obj()) {
- if (obj->obj_n == OBJ_U6_SILVER_SERPENT && Game::get_game()->get_game_type() == NUVIE_GAME_U6)
- return actors[obj->qty];
-
- return actors[obj->quality];
- }
-
- return get_multi_tile_actor(x, y, z);
- }
-
- return nullptr;
+ // Note: Semantics have changed slightly since moving to findActorAt():
+ // excluded_actor is now excluded when looking for multi-tile actors and surrounding objects
+ return findActorAt(x, y, z, [=](const Actor *a) {return a != excluded_actor;}, inc_surrounding_objs, inc_surrounding_objs);
}
+#if 0
+// This was used as a helper method by get_actor() before it was changed to use findActorAt()
Actor *ActorManager::get_multi_tile_actor(uint16 x, uint16 y, uint8 z) {
Actor *actor = get_actor(x + 1, y + 1, z, false); //search for 2x2 tile actor.
if (actor) {
@@ -571,6 +556,7 @@ Actor *ActorManager::get_multi_tile_actor(uint16 x, uint16 y, uint8 z) {
return nullptr;
}
+#endif
Actor *ActorManager::get_avatar() {
return get_actor(ACTOR_AVATAR_ID_N);
Commit: 5e9db60d023abf42219803c193454102559f8704
https://github.com/scummvm/scummvm/commit/5e9db60d023abf42219803c193454102559f8704
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Test all actors at destination when moving
Multiple actors can share the same tile, so they all need to be
checked for passability instead of just the first one found.
Changed paths:
engines/ultima/nuvie/actors/actor.cpp
diff --git a/engines/ultima/nuvie/actors/actor.cpp b/engines/ultima/nuvie/actors/actor.cpp
index 1427765cb92..3f3e0c3b7d1 100644
--- a/engines/ultima/nuvie/actors/actor.cpp
+++ b/engines/ultima/nuvie/actors/actor.cpp
@@ -351,9 +351,8 @@ bool Actor::moveRelative(sint16 rel_x, sint16 rel_y, ActorMoveFlags flags) {
bool Actor::check_move(uint16 new_x, uint16 new_y, uint8 new_z, ActorMoveFlags flags) {
- Actor *a;
- bool ignore_actors = flags & ACTOR_IGNORE_OTHERS;
- bool ignore_danger = (flags & ACTOR_IGNORE_DANGER);
+ const bool ignore_actors = flags & ACTOR_IGNORE_OTHERS;
+ const bool ignore_danger = flags & ACTOR_IGNORE_DANGER;
// bool ignore_danger = true;
/*
uint16 pitch = map->get_width(new_z);
@@ -363,13 +362,15 @@ bool Actor::check_move(uint16 new_x, uint16 new_y, uint8 new_z, ActorMoveFlags f
return(false);
*/
if (!ignore_actors) {
- a = map->get_actor(new_x, new_y, new_z, false);
- if (a /*&& a->is_visible()*/) {
- bool ignore_party_members = (flags & ACTOR_IGNORE_PARTY_MEMBERS);
- if (ignore_party_members && a->is_in_party())
- return true;
- return a->can_be_passed(this); // we can move over or under some actors. eg mice, dragons etc.
- }
+ const bool ignore_party_members = flags & ACTOR_IGNORE_PARTY_MEMBERS;
+
+ auto isBlocker = [=](const Actor *a) {
+ // we can move over or under some actors. eg mice, dragons etc.
+ return !(a->can_be_passed(this) || (ignore_party_members && a->is_in_party()));
+ };
+
+ if (Game::get_game()->get_actor_manager()->findActorAt(new_x, new_y, new_z, isBlocker, true, false))
+ return false;
}
// if(map->is_passable(new_x,new_y,new_z) == false)
@@ -456,12 +457,19 @@ bool Actor::move(uint16 new_x, uint16 new_y, uint8 new_z, ActorMoveFlags flags)
}
}
Game *game = Game::get_game();
- Actor *other = map->get_actor(new_x, new_y, new_z, false);
- if (!ignore_actors && !force_move && other && !other->can_be_passed(this)
- && (!game->get_party()->get_autowalk() || other->is_visible())) {
- set_error(ACTOR_BLOCKED_BY_ACTOR);
- error_struct.blocking_actor = other;
- return false; // blocked by actor
+
+ if (!ignore_actors && !force_move) {
+ auto isBlocker = [=](const Actor *a) {
+ return !a->can_be_passed(this) && (!game->get_party()->get_autowalk() || a->is_visible());
+ };
+
+ Actor *const other = game->get_actor_manager()->findActorAt(new_x, new_y, new_z, isBlocker, true, false);
+
+ if (other) {
+ set_error(ACTOR_BLOCKED_BY_ACTOR);
+ error_struct.blocking_actor = other;
+ return false; // blocked by actor
+ }
}
// move
Commit: fbb2318cb07b241364b3d6a235ed251c2eeaec18
https://github.com/scummvm/scummvm/commit/fbb2318cb07b241364b3d6a235ed251c2eeaec18
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Test all actors at destination when pushing
Do not automatically abort pushing an actor when there is also
one at the destination.
Instead, test every actor at the location for passability by using
Actor::move().
Changed paths:
engines/ultima/nuvie/core/events.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index 52445650006..00d8ff1a97c 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1304,15 +1304,15 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
return (pushedActorStr / 2 + 30 - playerStr) / 2 > getRandom(29) + 1;
};
+ const ActorMoveFlags moveFlags = ACTOR_IGNORE_MOVES | ACTOR_IGNORE_DANGER;
+
// Can not push self and must pass strength test
if (push_actor == playerActor || !push_actor->can_be_moved() || strengthCheckFailed())
scroll->display_string("Failed.\n\n");
- else if (map->lineTest(to.x, to.y, to.x, to.y, to.z, LT_HitActors | LT_HitUnpassable, lt))
+ else if (!push_actor->move(to.x, to.y, to.z, moveFlags))
scroll->display_string("Blocked.\n\n");
- else {
- push_actor->move(to.x, to.y, from.z, ACTOR_FORCE_MOVE | ACTOR_IGNORE_DANGER);
+ else
player->subtract_movement_points(5);
- }
} else {
if (map_window->get_interface() != INTERFACE_IGNORE_BLOCK
&& map_window->blocked_by_wall(player->get_actor(), push_obj)) {
Commit: 289e2ee96cf421bf1108bec0d144dff0b739b9c7
https://github.com/scummvm/scummvm/commit/289e2ee96cf421bf1108bec0d144dff0b739b9c7
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix crash when pushing over map boundary
Also fix printed direction.
Changed paths:
engines/ultima/nuvie/core/events.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index 00d8ff1a97c..2792fb41f86 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1261,9 +1261,16 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
to.y = from.y + pushrel_y;
to.z = from.z;
- scroll->display_string(get_direction_name(pushrel_x, pushrel_y));
+ // Use wrapped direction since we could have crossed a map boundary
+ sint8 wrappedXDir = get_wrapped_rel_dir(to.x, from.x, to.z);
+ sint8 wrappedYDir = get_wrapped_rel_dir(to.y, from.y, to.z);
+ scroll->display_string(get_direction_name(wrappedXDir, wrappedYDir));
scroll->display_string(".\n\n");
+ // Coordinates could be out of the map's bounds now, make them wrap around
+ WRAP_COORD(to.x, to.z);
+ WRAP_COORD(to.y, to.z);
+
if (pushrel_x == 0 && pushrel_y == 0) {
scroll->display_prompt();
endAction();
Commit: a142e944f95f410010e7012fa4c3e58b771559fb
https://github.com/scummvm/scummvm/commit/a142e944f95f410010e7012fa4c3e58b771559fb
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Assert index is in bounds when fetching chunk obj tree
Changed paths:
engines/ultima/nuvie/core/obj_manager.cpp
diff --git a/engines/ultima/nuvie/core/obj_manager.cpp b/engines/ultima/nuvie/core/obj_manager.cpp
index 65f637d1b46..f8bba3535e3 100644
--- a/engines/ultima/nuvie/core/obj_manager.cpp
+++ b/engines/ultima/nuvie/core/obj_manager.cpp
@@ -1542,7 +1542,10 @@ iAVLTree *ObjManager::get_obj_tree(uint16 x, uint16 y, uint8 level) const {
x >>= 7; // x = floor(x / 128) 128 = superchunk width
y >>= 7; // y = floor(y / 128) 128 = superchunk height
- return surface[x + y * 8];
+ const int idx = x + y * 8;
+ assert(idx < ARRAYSIZE(surface));
+
+ return surface[idx];
}
if (level > 5)
Commit: e424a5c635f1d00911ba2f3375856d58c5666a5a
https://github.com/scummvm/scummvm/commit/e424a5c635f1d00911ba2f3375856d58c5666a5a
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Add some missing map coordinate wrapping
Prevents bugs/crashes due to incorrect coordinates
when performing actions across a map boundary.
Changed paths:
engines/ultima/nuvie/core/events.cpp
engines/ultima/nuvie/gui/widgets/map_window.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index 2792fb41f86..329ccbbe9f5 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1252,18 +1252,19 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
pushrel_x = to.x - from.x;
pushrel_y = to.y - from.y;
+ sint8 wrappedXDir = get_wrapped_rel_dir(to.x, from.x, to.z);
+ sint8 wrappedYDir = get_wrapped_rel_dir(to.y, from.y, to.z);
+
if (map_window->get_interface() == INTERFACE_NORMAL || push_actor) {
// you can only push one space at a time
- pushrel_x = (pushrel_x == 0) ? 0 : (pushrel_x < 0) ? -1 : 1;
- pushrel_y = (pushrel_y == 0) ? 0 : (pushrel_y < 0) ? -1 : 1;
+ pushrel_x = wrappedXDir;
+ pushrel_y = wrappedYDir;
}
to.x = from.x + pushrel_x;
to.y = from.y + pushrel_y;
to.z = from.z;
// Use wrapped direction since we could have crossed a map boundary
- sint8 wrappedXDir = get_wrapped_rel_dir(to.x, from.x, to.z);
- sint8 wrappedYDir = get_wrapped_rel_dir(to.y, from.y, to.z);
scroll->display_string(get_direction_name(wrappedXDir, wrappedYDir));
scroll->display_string(".\n\n");
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.cpp b/engines/ultima/nuvie/gui/widgets/map_window.cpp
index b790fe519ee..630770097c7 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.cpp
+++ b/engines/ultima/nuvie/gui/widgets/map_window.cpp
@@ -543,11 +543,11 @@ Actor *MapWindow::get_actorAtCursor() {
if (tmp_map_buf[(cursor_y + TMP_MAP_BORDER) * tmp_map_width + (cursor_x + TMP_MAP_BORDER)] == 0) //black area
return nullptr; // nothing to see here. ;)
- return actor_manager->get_actor(WRAPPED_COORD(cur_x + cursor_x, cur_level), cur_y + cursor_y, cur_level);
+ return actor_manager->get_actor(WRAPPED_COORD(cur_x + cursor_x, cur_level), WRAPPED_COORD(cur_y + cursor_y, cur_level), cur_level);
}
MapCoord MapWindow::get_cursorCoord() {
- return (MapCoord(WRAPPED_COORD(cur_x + cursor_x, cur_level), cur_y + cursor_y, cur_level));
+ return MapCoord(WRAPPED_COORD(cur_x + cursor_x, cur_level), WRAPPED_COORD(cur_y + cursor_y, cur_level), cur_level);
}
void MapWindow::get_level(uint8 *level) const {
@@ -1864,8 +1864,8 @@ void MapWindow::drag_perform_drop(int x, int y, int message, void *data) {
y -= area.top;
if (message == GUI_DRAG_OBJ) {
- x = (cur_x + x / 16) % mapWidth;
- y = (cur_y + y / 16) % mapWidth;
+ x = (uint)(cur_x + x / 16) % mapWidth;
+ y = (uint)(cur_y + y / 16) % mapWidth;
Obj *obj = (Obj *)data;
if (obj->obj_n == OBJ_U6_LOCK_PICK && game_type == NUVIE_GAME_U6)
@@ -2257,7 +2257,7 @@ void MapWindow::teleport_to_cursor() {
void MapWindow::select_target(int x, int y) {
int wx, wy;
mouseToWorldCoords(x, y, wx, wy);
- moveCursor(WRAP_VIEWP(cur_x, wx, map_width), wy - cur_y);
+ moveCursor(WRAPPED_COORD(wx - cur_x, cur_level), WRAPPED_COORD(wy - cur_y, cur_level));
game->get_event()->select_target(uint16(wx), uint16(wy), cur_level);
}
@@ -2267,8 +2267,8 @@ void MapWindow::mouseToWorldCoords(int mx, int my, int &wx, int &wy) {
int mapWidth = map->get_width(cur_level);
- wx = (cur_x + x / 16) % mapWidth;
- wy = (cur_y + y / 16) % mapWidth;
+ wx = (uint)(cur_x + x / 16) % mapWidth;
+ wy = (uint)(cur_y + y / 16) % mapWidth;
}
void MapWindow::drag_draw(int x, int y, int message, void *data) {
Commit: 9c0bf4d332ede06e4cb7224c0cad9d2ebf9a96b0
https://github.com/scummvm/scummvm/commit/9c0bf4d332ede06e4cb7224c0cad9d2ebf9a96b0
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Add isFlying() method to Actor class
Changed paths:
engines/ultima/nuvie/actors/actor.h
engines/ultima/nuvie/actors/u6_actor.h
diff --git a/engines/ultima/nuvie/actors/actor.h b/engines/ultima/nuvie/actors/actor.h
index cb66918226f..75c4bac6984 100644
--- a/engines/ultima/nuvie/actors/actor.h
+++ b/engines/ultima/nuvie/actors/actor.h
@@ -332,6 +332,9 @@ public:
bool is_temp() const {
return temp_actor;
}
+ virtual bool isFlying() const {
+ return false;
+ }
/**
* @brief Does any tile of this actor occupy the given world location?
* @param lx world coordinate
diff --git a/engines/ultima/nuvie/actors/u6_actor.h b/engines/ultima/nuvie/actors/u6_actor.h
index d4237eac28c..8dfecb78218 100644
--- a/engines/ultima/nuvie/actors/u6_actor.h
+++ b/engines/ultima/nuvie/actors/u6_actor.h
@@ -24,6 +24,7 @@
#include "ultima/nuvie/actors/actor.h"
#include "ultima/nuvie/misc/actor_list.h"
+#include "ultima/nuvie/core/u6_objects.h"
namespace Ultima {
namespace Nuvie {
@@ -130,6 +131,19 @@ public:
uint8 get_dex_text_color() const override {
return 0x48;
}
+ bool isFlying() const override {
+ // FIXME: Get flying flag from lua actor_tbl
+ // in devtools/create_ultima/files/ultima6/scripts/u6/actor.lua
+ const uint16 flyingObjs[] = {
+ OBJ_U6_INSECTS, OBJ_U6_GIANT_BAT, OBJ_U6_GAZER, OBJ_U6_BIRD,
+ OBJ_U6_WINGED_GARGOYLE, OBJ_U6_DAEMON, OBJ_U6_DRAKE,
+ OBJ_U6_MONGBAT, OBJ_U6_DRAGON, OBJ_U6_INFLATED_BALLOON };
+
+ for (const auto flyingObj : flyingObjs)
+ if (obj_n == flyingObj)
+ return true;
+ return false;
+ }
protected:
bool init_ship();
Commit: feb829633737ac35018a1f4bfedef02a8723a881
https://github.com/scummvm/scummvm/commit/feb829633737ac35018a1f4bfedef02a8723a881
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Add isNonBlocking() method to Actor class
Changed paths:
engines/ultima/nuvie/actors/actor.h
engines/ultima/nuvie/actors/u6_actor.h
diff --git a/engines/ultima/nuvie/actors/actor.h b/engines/ultima/nuvie/actors/actor.h
index 75c4bac6984..0cf3703a6e8 100644
--- a/engines/ultima/nuvie/actors/actor.h
+++ b/engines/ultima/nuvie/actors/actor.h
@@ -335,6 +335,9 @@ public:
virtual bool isFlying() const {
return false;
}
+ virtual bool isNonBlocking() const {
+ return false;
+ }
/**
* @brief Does any tile of this actor occupy the given world location?
* @param lx world coordinate
diff --git a/engines/ultima/nuvie/actors/u6_actor.h b/engines/ultima/nuvie/actors/u6_actor.h
index 8dfecb78218..e7a83ee9170 100644
--- a/engines/ultima/nuvie/actors/u6_actor.h
+++ b/engines/ultima/nuvie/actors/u6_actor.h
@@ -144,6 +144,17 @@ public:
return true;
return false;
}
+ bool isNonBlocking() const override {
+ // These are hard-coded in original U6
+ const uint16 u6NonBlockingObjs[] = {
+ OBJ_U6_INSECTS, OBJ_U6_MOUSE, OBJ_U6_BIRD, OBJ_U6_CORPSER,
+ OBJ_U6_RABBIT };
+
+ for (const auto nonBlockingObj : u6NonBlockingObjs)
+ if (obj_n == nonBlockingObj)
+ return true;
+ return false;
+ }
protected:
bool init_ship();
Commit: 7dd18ae6b3ca7fbc688766ddde5ecc9294652050
https://github.com/scummvm/scummvm/commit/7dd18ae6b3ca7fbc688766ddde5ecc9294652050
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Slightly rework actor passability
Make U6Actor::can_be_passed() behave closer to original Ultima 6:
- Match original tests when handling party members
Note: U6 ignores party members by default and only considers
them as blocking in a specific function which makes NPCs walk towards
a destination. In Nuvie, it is the other way around, so the ignoreParty
flag needs to be explicitly set most of the time. This difference was
kept to not risk breaking existing code.
- Do not allow actors with different movement types to automatically
pass each other
Note: Flying actors in U6 only get to ignore some terrain, not other
actors.
- Only allow actors marked as non-blocking to be passed, regardless
of tile passability
- Prevent actors with the same object type from passing each other
These changes also make treating Sherry as a special case redundant.
Changed paths:
engines/ultima/nuvie/actors/actor.cpp
engines/ultima/nuvie/actors/actor.h
engines/ultima/nuvie/actors/u6_actor.cpp
engines/ultima/nuvie/actors/u6_actor.h
diff --git a/engines/ultima/nuvie/actors/actor.cpp b/engines/ultima/nuvie/actors/actor.cpp
index 3f3e0c3b7d1..06682298e48 100644
--- a/engines/ultima/nuvie/actors/actor.cpp
+++ b/engines/ultima/nuvie/actors/actor.cpp
@@ -362,11 +362,11 @@ bool Actor::check_move(uint16 new_x, uint16 new_y, uint8 new_z, ActorMoveFlags f
return(false);
*/
if (!ignore_actors) {
- const bool ignore_party_members = flags & ACTOR_IGNORE_PARTY_MEMBERS;
+ const bool ignoreParty = flags & ACTOR_IGNORE_PARTY_MEMBERS;
auto isBlocker = [=](const Actor *a) {
// we can move over or under some actors. eg mice, dragons etc.
- return !(a->can_be_passed(this) || (ignore_party_members && a->is_in_party()));
+ return !(a->can_be_passed(this, ignoreParty));
};
if (Game::get_game()->get_actor_manager()->findActorAt(new_x, new_y, new_z, isBlocker, true, false))
@@ -392,7 +392,7 @@ bool Actor::can_be_moved() {
return can_move;
}
-bool Actor::can_be_passed(const Actor *other) const {
+bool Actor::can_be_passed(const Actor *other, bool ignoreParty) const {
// ethereal actors can always pass us
return other->ethereal || is_passable();
}
@@ -459,8 +459,10 @@ bool Actor::move(uint16 new_x, uint16 new_y, uint8 new_z, ActorMoveFlags flags)
Game *game = Game::get_game();
if (!ignore_actors && !force_move) {
+ const bool ignoreParty = flags & ACTOR_IGNORE_PARTY_MEMBERS;
+
auto isBlocker = [=](const Actor *a) {
- return !a->can_be_passed(this) && (!game->get_party()->get_autowalk() || a->is_visible());
+ return !a->can_be_passed(this, ignoreParty) && (!game->get_party()->get_autowalk() || a->is_visible());
};
Actor *const other = game->get_actor_manager()->findActorAt(new_x, new_y, new_z, isBlocker, true, false);
diff --git a/engines/ultima/nuvie/actors/actor.h b/engines/ultima/nuvie/actors/actor.h
index 0cf3703a6e8..1583b725ba9 100644
--- a/engines/ultima/nuvie/actors/actor.h
+++ b/engines/ultima/nuvie/actors/actor.h
@@ -592,7 +592,7 @@ public:
bool check_moveRelative(sint16 rel_x, sint16 rel_y, ActorMoveFlags flags = 0);
virtual bool can_be_moved();
- virtual bool can_be_passed(const Actor *other) const;
+ virtual bool can_be_passed(const Actor *other, bool ignoreParty = false) const;
virtual void update();
void set_in_party(bool state);
void set_pathfinder(ActorPathFinder *new_pf, Path *path_type = 0);
diff --git a/engines/ultima/nuvie/actors/u6_actor.cpp b/engines/ultima/nuvie/actors/u6_actor.cpp
index 7c251f989f4..72df96d6f1a 100644
--- a/engines/ultima/nuvie/actors/u6_actor.cpp
+++ b/engines/ultima/nuvie/actors/u6_actor.cpp
@@ -1504,11 +1504,45 @@ bool U6Actor::can_twitch() {
&& !is_paralyzed());
}
-bool U6Actor::can_be_passed(const Actor *other) const {
+bool U6Actor::can_be_passed(const Actor *other, bool ignoreParty) const {
+ // FIXME: Original U6 instead uses a function that checks if a game object (actor or object)
+ // can occupy a world location:
+ // Figure out which of the remaining tests are relevant to actors and add them here.
+
const U6Actor *other_ = static_cast<const U6Actor *>(other);
- // Sherry the mouse can pass others if they are in a party with her.
- bool is_sherry = is_in_party() && other_->is_in_party() && other_->obj_n == OBJ_U6_MOUSE;
- return (Actor::can_be_passed(other_) || other_->current_movetype != current_movetype || is_sherry);
+
+ if (other_->ethereal)
+ return true;
+
+ if (other_ == this)
+ return true;
+
+ if (!other_->isFlying() && is_passable())
+ goto FinalTest;
+
+ // Flying actors can not pass each other unless both are in the party
+ if (other_->isFlying() && !isFlying())
+ goto FinalTest;
+
+ // If the ignoreParty flag is set and we are in the party and not immobilized,
+ // other members can pass us.
+ if (ignoreParty && is_in_party() && other_->is_in_party() && !is_immobile()
+ && this != Game::get_game()->get_player()->get_actor())
+ return true;
+
+ return false; // default
+
+ FinalTest:
+
+ // Same type can not pass us
+ if (obj_n == other_->get_obj_n())
+ return false;
+
+ // Some actors do not block others (e.g. mice, rabbits etc.)
+ if (!isNonBlocking())
+ return false;
+
+ return true;
}
void U6Actor::print() {
diff --git a/engines/ultima/nuvie/actors/u6_actor.h b/engines/ultima/nuvie/actors/u6_actor.h
index e7a83ee9170..a3941960cf9 100644
--- a/engines/ultima/nuvie/actors/u6_actor.h
+++ b/engines/ultima/nuvie/actors/u6_actor.h
@@ -117,7 +117,7 @@ public:
bool get_corpser_flag() const override {
return (movement_flags & ACTOR_MOVEMENT_FLAGS_CORPSER);
}
- bool can_be_passed(const Actor *other) const override;
+ bool can_be_passed(const Actor *other, bool ignoreParty) const override;
bool will_not_talk() const override;
void set_actor_obj_n(uint16 new_obj_n);
Commit: 1ab56c07bc3d85a1d980d60c7c1b045ecb2cee08
https://github.com/scummvm/scummvm/commit/1ab56c07bc3d85a1d980d60c7c1b045ecb2cee08
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Allow pushing party members onto each other
Changed paths:
engines/ultima/nuvie/core/events.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index 329ccbbe9f5..62397d6d774 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1312,7 +1312,7 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
return (pushedActorStr / 2 + 30 - playerStr) / 2 > getRandom(29) + 1;
};
- const ActorMoveFlags moveFlags = ACTOR_IGNORE_MOVES | ACTOR_IGNORE_DANGER;
+ const ActorMoveFlags moveFlags = ACTOR_IGNORE_MOVES | ACTOR_IGNORE_DANGER | ACTOR_IGNORE_PARTY_MEMBERS;
// Can not push self and must pass strength test
if (push_actor == playerActor || !push_actor->can_be_moved() || strengthCheckFailed())
Commit: 593472a252c2644f9218139cc66e08589a6dfbf4
https://github.com/scummvm/scummvm/commit/593472a252c2644f9218139cc66e08589a6dfbf4
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Only bump one party member on player move
If there are more party members on the destination tile, ignore them.
Changed paths:
engines/ultima/nuvie/core/player.cpp
diff --git a/engines/ultima/nuvie/core/player.cpp b/engines/ultima/nuvie/core/player.cpp
index 1976392bda8..1b4106b3a82 100644
--- a/engines/ultima/nuvie/core/player.cpp
+++ b/engines/ultima/nuvie/core/player.cpp
@@ -275,7 +275,8 @@ bool Player::check_moveRelative(sint16 rel_x, sint16 rel_y) {
if (ret->err == ACTOR_BLOCKED_BY_ACTOR
&& party->contains_actor(ret->blocking_actor) && ret->blocking_actor->is_immobile() == false)
ret->blocking_actor->push(actor, ACTOR_PUSH_HERE);
- if (!actor->moveRelative(rel_x, rel_y, ACTOR_IGNORE_DANGER)) /**MOVE**/
+ // There could be more party members at the destination, but U6 ignores them - hence the ACTOR_IGNORE_PARTY_MEMBERS.
+ if (!actor->moveRelative(rel_x, rel_y, ACTOR_IGNORE_DANGER | ACTOR_IGNORE_PARTY_MEMBERS)) /**MOVE**/
return false;
}
return true;
Commit: 7cd99686af236ada2745b03d3caa49ddf7cd3ad9
https://github.com/scummvm/scummvm/commit/7cd99686af236ada2745b03d3caa49ddf7cd3ad9
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Do not swap positions with party when moving as Sherry
The regression was introduced with the recent actor passability
changes.
Changed paths:
engines/ultima/nuvie/core/player.cpp
diff --git a/engines/ultima/nuvie/core/player.cpp b/engines/ultima/nuvie/core/player.cpp
index 1b4106b3a82..0a5c05e7fdf 100644
--- a/engines/ultima/nuvie/core/player.cpp
+++ b/engines/ultima/nuvie/core/player.cpp
@@ -272,7 +272,9 @@ const char *Player::get_gender_title() const {
bool Player::check_moveRelative(sint16 rel_x, sint16 rel_y) {
if (!actor->moveRelative(rel_x, rel_y, ACTOR_IGNORE_DANGER)) { /**MOVE**/
ActorError *ret = actor->get_error();
+ // FIXME: When in combat, U6 attempts to move party members with role "front" forward instead of swapping.
if (ret->err == ACTOR_BLOCKED_BY_ACTOR
+ && (game_type != NUVIE_GAME_U6 || actor->obj_n != OBJ_U6_MOUSE) // Only exchange positions if player is not U6 mouse
&& party->contains_actor(ret->blocking_actor) && ret->blocking_actor->is_immobile() == false)
ret->blocking_actor->push(actor, ACTOR_PUSH_HERE);
// There could be more party members at the destination, but U6 ignores them - hence the ACTOR_IGNORE_PARTY_MEMBERS.
Commit: b9206fce97e980441c005067b51f64bb81c3fd50
https://github.com/scummvm/scummvm/commit/b9206fce97e980441c005067b51f64bb81c3fd50
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix Sherry blocking/being blocked during party move
Ultima 6 does not consider party members to be blocking when the party
is following the player. It avoids stacking them via the is_contiguous()
check instead, which also has an exception for Sherry the mouse.
Changed paths:
engines/ultima/nuvie/pathfinder/party_path_finder.cpp
diff --git a/engines/ultima/nuvie/pathfinder/party_path_finder.cpp b/engines/ultima/nuvie/pathfinder/party_path_finder.cpp
index d90c4f01e9a..9fad2a37896 100644
--- a/engines/ultima/nuvie/pathfinder/party_path_finder.cpp
+++ b/engines/ultima/nuvie/pathfinder/party_path_finder.cpp
@@ -26,6 +26,8 @@
#include "ultima/nuvie/pathfinder/seek_path.h"
#include "ultima/nuvie/pathfinder/actor_path_finder.h"
#include "ultima/nuvie/pathfinder/party_path_finder.h"
+#include "ultima/nuvie/core/game.h"
+#include "ultima/nuvie/core/u6_objects.h"
namespace Ultima {
namespace Nuvie {
@@ -64,15 +66,25 @@ bool PartyPathFinder::is_at_target(uint32 p) {
* (is_contiguous(member, member_loc) == "is member adjacent to another member
* whose following position is lower-numbered?") */
bool PartyPathFinder::is_contiguous(uint32 member_num, const MapCoord &from) {
+ const bool isU6 = Game::get_game()->get_game_type() == NUVIE_GAME_U6;
+ const Actor *inActor = get_member(member_num).actor;
+ const bool isMouse = isU6 && inActor->get_obj_n() == OBJ_U6_MOUSE;
+ bool retVal = false;
+
for (uint32 q = 0; q < member_num; q++) { // check lower-numbered members
const Actor *actor = get_member(q).actor;
+ const bool otherIsMouse = isU6 && actor->get_obj_n() == OBJ_U6_MOUSE;
if (actor && actor->is_immobile() == true) continue;
MapCoord loc = party->get_location(q);
- if (from.distance(loc) <= 1)
- return true;
+ if (!isMouse && !otherIsMouse && from.distance(loc) == 0)
+ return false; // Do not allow stacking (except for Sherry)
+ if (from.distance(loc) <= 1) {
+ retVal = true;
+ continue; // Stay in the loop to check if other party members are on the same tile
+ }
}
- return false;
+ return retVal;
}
/* Is member adjacent to another member whose following position is lower-numbered? */
@@ -413,7 +425,7 @@ bool PartyPathFinder::move_member(uint32 member_num, sint16 relx, sint16 rely, b
MapCoord target(member_loc);
target = member_loc.abs_coords(relx, rely);
Actor *actor = get_member(member_num).actor;
- ActorMoveFlags flags = ACTOR_IGNORE_MOVES;
+ ActorMoveFlags flags = ACTOR_IGNORE_MOVES | ACTOR_IGNORE_PARTY_MEMBERS;
if (!avoid_danger_tiles)
flags = flags | ACTOR_IGNORE_DANGER;
@@ -422,19 +434,22 @@ bool PartyPathFinder::move_member(uint32 member_num, sint16 relx, sint16 rely, b
actor->set_direction(relx, rely);
return true;
}
- if (actor->get_error()->err == ACTOR_BLOCKED_BY_ACTOR) {
- const Actor *blocking_actor = actor->get_error()->blocking_actor;
- sint8 blocking_member_num = -1;
- if (blocking_actor)
- blocking_member_num = party->get_member_num(blocking_actor);
- if (blocking_member_num < sint32(member_num))
- return false; // blocked by an actor not in the party
- if (bump_member(uint32(blocking_member_num), member_num)
- && actor->move(target.x, target.y, target.z, flags | ACTOR_IGNORE_MOVES)) {
- actor->set_direction(relx, rely);
- return true;
- }
- }
+ // Block commented out: It seems that, at least in Ultima 6, party members do not
+ // bump each other, so we now ignore them via ACTOR_IGNORE_PARTY_MEMBERS.
+ // Instead, is_contiguous() prevents them from stacking.
+ // if (actor->get_error()->err == ACTOR_BLOCKED_BY_ACTOR) {
+ // const Actor *blocking_actor = actor->get_error()->blocking_actor;
+ // sint8 blocking_member_num = -1;
+ // if (blocking_actor)
+ // blocking_member_num = party->get_member_num(blocking_actor);
+ // if (blocking_member_num < sint32(member_num))
+ // return false; // blocked by an actor not in the party
+ // if (bump_member(uint32(blocking_member_num), member_num)
+ // && actor->move(target.x, target.y, target.z, flags | ACTOR_IGNORE_MOVES)) {
+ // actor->set_direction(relx, rely);
+ // return true;
+ // }
+ // }
}
return false; // target is not contiguous, or move is blocked
}
Commit: 37db6d17304f4d0a65cf61d47890c6508660a856
https://github.com/scummvm/scummvm/commit/37db6d17304f4d0a65cf61d47890c6508660a856
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Allow dropping objects onto passable actors
Changed paths:
engines/ultima/nuvie/gui/widgets/map_window.cpp
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.cpp b/engines/ultima/nuvie/gui/widgets/map_window.cpp
index 630770097c7..67c4f68f844 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.cpp
+++ b/engines/ultima/nuvie/gui/widgets/map_window.cpp
@@ -1653,7 +1653,9 @@ CanDropOrMoveMsg MapWindow::can_drop_or_move_obj(uint16 x, uint16 y, Actor *acto
}
MapCoord actor_loc = actor->get_location();
- if (actor_manager->get_actor(x, y, actor_loc.z))
+
+ // Can only drop onto non-blocking actors
+ if (actor_manager->findActorAt(x, y, actor_loc.z, [](const Actor *a) {return !a->isNonBlocking();}, true, false))
return MSG_NOT_POSSIBLE;
Obj *dest_obj = nullptr;
Commit: 37502f406d189a37bafc367b096fcc4bbda66074
https://github.com/scummvm/scummvm/commit/37502f406d189a37bafc367b096fcc4bbda66074
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Allow pushing objects onto passable actors
Also display correct message when push is blocked.
Changed paths:
engines/ultima/nuvie/core/events.cpp
engines/ultima/nuvie/gui/widgets/map_window.cpp
diff --git a/engines/ultima/nuvie/core/events.cpp b/engines/ultima/nuvie/core/events.cpp
index 62397d6d774..276e017f28d 100644
--- a/engines/ultima/nuvie/core/events.cpp
+++ b/engines/ultima/nuvie/core/events.cpp
@@ -1343,7 +1343,7 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
to.x,
to.y,
to.z,
- LT_HitActors | LT_HitUnpassable,
+ LT_HitUnpassable,
lt,
0,
game->get_game_type() == NUVIE_GAME_U6 ? nullptr
@@ -1366,9 +1366,7 @@ bool Events::pushTo(sint16 rel_x, sint16 rel_y, bool push_from) {
}
} else {
Obj *obj = obj_manager->get_obj(to.x, to.y, to.z);
- if (map_window->get_interface() == INTERFACE_IGNORE_BLOCK
- && map->get_actor(to.x, to.y, to.z)) {} // don't allow moving under actor
- else if (obj && obj_manager->can_store_obj(obj, push_obj)) { //if we are moving onto a container.
+ if (obj && obj_manager->can_store_obj(obj, push_obj)) { //if we are moving onto a container.
can_move = obj_manager->moveto_container(push_obj, obj);
} else {
/* do normal move if no usecode or return from usecode was true */
diff --git a/engines/ultima/nuvie/gui/widgets/map_window.cpp b/engines/ultima/nuvie/gui/widgets/map_window.cpp
index 67c4f68f844..8dd0acbcccd 100644
--- a/engines/ultima/nuvie/gui/widgets/map_window.cpp
+++ b/engines/ultima/nuvie/gui/widgets/map_window.cpp
@@ -1655,8 +1655,9 @@ CanDropOrMoveMsg MapWindow::can_drop_or_move_obj(uint16 x, uint16 y, Actor *acto
MapCoord actor_loc = actor->get_location();
// Can only drop onto non-blocking actors
+ // Message: "Blocked" if pushing, "Not possible" if dropping
if (actor_manager->findActorAt(x, y, actor_loc.z, [](const Actor *a) {return !a->isNonBlocking();}, true, false))
- return MSG_NOT_POSSIBLE;
+ return in_inventory ? MSG_NOT_POSSIBLE : MSG_BLOCKED;
Obj *dest_obj = nullptr;
if (game_type == NUVIE_GAME_U6) {
Commit: 159b2084df3d0e0a8d4ddfa51acc7762fd6b0669
https://github.com/scummvm/scummvm/commit/159b2084df3d0e0a8d4ddfa51acc7762fd6b0669
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix softlock on drop to impassable location with actor
Remove unnecessary check. Prevents infnite pause mode when dropping
an object onto an actor that is at an impassable location.
To reproduce:
1. Start/load a game in non-enhanced mode
2. Get Sherry in your party
3. Drop a chest onto Sherry
4. Drop an item onto the chest
Changed paths:
engines/ultima/nuvie/core/anim_manager.cpp
diff --git a/engines/ultima/nuvie/core/anim_manager.cpp b/engines/ultima/nuvie/core/anim_manager.cpp
index cba32b579d2..c26e55ed173 100644
--- a/engines/ultima/nuvie/core/anim_manager.cpp
+++ b/engines/ultima/nuvie/core/anim_manager.cpp
@@ -614,12 +614,9 @@ bool TossAnim::update() {
Obj *hitObj = obj_manager->get_obj(new_loc.x, new_loc.y, mapwindow_level);
// blocking tile
- if (!map->is_passable(new_loc.x, new_loc.y, mapwindow_level)) {
- if (!hitActor) // NOTE: no effect if actor is also at location
- hit_blocking(MapCoord(new_loc.x, new_loc.y, mapwindow_level));
- else
- stop(); // this mimics U6 in appearance and results in no effect
- } else if (hitActor)
+ if (!map->is_passable(new_loc.x, new_loc.y, mapwindow_level))
+ hit_blocking(MapCoord(new_loc.x, new_loc.y, mapwindow_level));
+ else if (hitActor)
hit_actor(hitActor);
else if (hitObj)
hit_object(hitObj);
Commit: 6ca26ec1db360d57caa8a7719f1fbd0c8571ba1a
https://github.com/scummvm/scummvm/commit/6ca26ec1db360d57caa8a7719f1fbd0c8571ba1a
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Prevent moving some containers into containers on map
Changed paths:
engines/ultima/nuvie/core/obj_manager.cpp
diff --git a/engines/ultima/nuvie/core/obj_manager.cpp b/engines/ultima/nuvie/core/obj_manager.cpp
index f8bba3535e3..776300e72bd 100644
--- a/engines/ultima/nuvie/core/obj_manager.cpp
+++ b/engines/ultima/nuvie/core/obj_manager.cpp
@@ -742,6 +742,10 @@ bool ObjManager::can_store_obj(const Obj *target, Obj *src) const {
if (src->obj_n == OBJ_U6_TRAP)
return false;
+ if (!target->is_in_inventory() && (src->obj_n == OBJ_U6_CHEST
+ || src->obj_n == OBJ_U6_BARREL || src->obj_n == OBJ_U6_CRATE))
+ return false;
+
if (target->obj_n == OBJ_U6_BAG
|| target->obj_n == OBJ_U6_BACKPACK
|| target->obj_n == OBJ_U6_BASKET
Commit: e37d96aa194c1ef269c0df88179df584cd7d4a6a
https://github.com/scummvm/scummvm/commit/e37d96aa194c1ef269c0df88179df584cd7d4a6a
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Hide menu in save thumbnails
Changed paths:
engines/ultima/nuvie/menus/game_menu_dialog.cpp
diff --git a/engines/ultima/nuvie/menus/game_menu_dialog.cpp b/engines/ultima/nuvie/menus/game_menu_dialog.cpp
index 04b140100df..6c4bd34f1fb 100644
--- a/engines/ultima/nuvie/menus/game_menu_dialog.cpp
+++ b/engines/ultima/nuvie/menus/game_menu_dialog.cpp
@@ -145,6 +145,10 @@ GUI_status GameMenuDialog::callback(uint16 msg, GUI_CallBack *caller, void *data
close_dialog();
} else if (caller == save_button) {
close_dialog();
+ // Redraw so the dialog does not show in the save thumbnail
+ gui->force_full_redraw();
+ gui->Display();
+ gui->get_screen()->update();
g_engine->saveGameDialog();
} else if (caller == load_button) {
g_engine->loadGameDialog();
Commit: 704ca3c493400e703284d3b12fe9d951b2e375e2
https://github.com/scummvm/scummvm/commit/704ca3c493400e703284d3b12fe9d951b2e375e2
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix delete[] VS free
Changed paths:
engines/ultima/nuvie/core/magic.h
diff --git a/engines/ultima/nuvie/core/magic.h b/engines/ultima/nuvie/core/magic.h
index 4969e6b668c..ea2d26a1546 100644
--- a/engines/ultima/nuvie/core/magic.h
+++ b/engines/ultima/nuvie/core/magic.h
@@ -71,8 +71,8 @@ public: /* saves using dumb get / set functions */
reagents = new_reagents;
};
~Spell() {
- delete[] name;
- delete[] invocation;
+ free(name);
+ free(invocation);
}
};
Commit: 8f8b02e63fe6e949c0e6dbe4fe53c743c7b2fef1
https://github.com/scummvm/scummvm/commit/8f8b02e63fe6e949c0e6dbe4fe53c743c7b2fef1
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix memory leak
Changed paths:
engines/ultima/nuvie/views/spell_view_gump.cpp
diff --git a/engines/ultima/nuvie/views/spell_view_gump.cpp b/engines/ultima/nuvie/views/spell_view_gump.cpp
index 3424bdb14b0..4fbabb35615 100644
--- a/engines/ultima/nuvie/views/spell_view_gump.cpp
+++ b/engines/ultima/nuvie/views/spell_view_gump.cpp
@@ -152,11 +152,11 @@ void SpellViewGump::loadCircleString(const Common::Path &datadir) {
Common::sprintf_s(filename, "%d.bmp", level);
build_path(datadir, filename, imagefile);
- Graphics::ManagedSurface *s = bmp.getSdlSurface32(imagefile);
- if (s != nullptr) {
+ Common::ScopedPtr<Graphics::ManagedSurface> s(bmp.getSdlSurface32(imagefile));
+ if (s) {
Common::Rect dst;
dst = Common::Rect(70, 7, 74, 13);
- SDL_BlitSurface(s, nullptr, bg_image, &dst);
+ SDL_BlitSurface(s.get(), nullptr, bg_image, &dst);
}
switch (level) {
@@ -178,11 +178,11 @@ void SpellViewGump::loadCircleSuffix(const Common::Path &datadir, const Std::str
Common::Path imagefile;
build_path(datadir, image, imagefile);
- Graphics::ManagedSurface *s = bmp.getSdlSurface32(imagefile);
- if (s != nullptr) {
+ Common::ScopedPtr<Graphics::ManagedSurface> s(bmp.getSdlSurface32(imagefile));
+ if (s) {
Common::Rect dst;
dst = Common::Rect(75, 7, 82, 13);
- SDL_BlitSurface(s, nullptr, bg_image, &dst);
+ SDL_BlitSurface(s.get(), nullptr, bg_image, &dst);
}
}
Commit: e485255cc2ba76a70c7a65afbc18fa73f3db5c5b
https://github.com/scummvm/scummvm/commit/e485255cc2ba76a70c7a65afbc18fa73f3db5c5b
Author: PushmePullyu (127053144+PushmePullyu at users.noreply.github.com)
Date: 2024-02-17T13:10:46-10:00
Commit Message:
ULTIMA: NUVIE: Fix delete VS free
Changed paths:
engines/ultima/nuvie/sound/sound_manager.cpp
diff --git a/engines/ultima/nuvie/sound/sound_manager.cpp b/engines/ultima/nuvie/sound/sound_manager.cpp
index 3cb29db0635..764786de156 100644
--- a/engines/ultima/nuvie/sound/sound_manager.cpp
+++ b/engines/ultima/nuvie/sound/sound_manager.cpp
@@ -623,7 +623,7 @@ void SoundManager::musicStop() {
musicPause();
m_pCurrentSong = nullptr;
if (_musicData) {
- delete _musicData;
+ free(_musicData);
_musicData = nullptr;
}
}
More information about the Scummvm-git-logs
mailing list