Initial commit
This commit is contained in:
326
engines/ultima/nuvie/core/obj.cpp
Normal file
326
engines/ultima/nuvie/core/obj.cpp
Normal file
@@ -0,0 +1,326 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ultima/nuvie/core/nuvie_defs.h"
|
||||
#include "ultima/nuvie/core/obj_manager.h"
|
||||
#include "ultima/nuvie/core/game.h"
|
||||
#include "ultima/nuvie/core/u6_objects.h"
|
||||
|
||||
namespace Ultima {
|
||||
namespace Nuvie {
|
||||
|
||||
Obj::Obj() : obj_n(0), status(0), nuvie_status(0), frame_n(0), qty(0),
|
||||
quality(0), parent(nullptr), container(nullptr), x(0), y(0), z(0) {
|
||||
}
|
||||
|
||||
Obj::Obj(Obj *sobj) {
|
||||
memcpy(this, sobj, sizeof(Obj));
|
||||
|
||||
parent = nullptr;
|
||||
container = nullptr;
|
||||
}
|
||||
|
||||
void Obj::make_container() {
|
||||
if (container == nullptr)
|
||||
container = new U6LList();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Obj *Obj::get_container_obj(bool recursive) {
|
||||
Obj *obj = (is_in_container() ? (Obj *)parent : nullptr);
|
||||
|
||||
if (recursive) {
|
||||
while (obj && obj->is_in_container())
|
||||
obj = (Obj *)obj->parent;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void Obj::set_on_map(U6LList *map_list) {
|
||||
parent = map_list;
|
||||
nuvie_status &= NUVIE_OBJ_STATUS_LOC_MASK_SET;
|
||||
nuvie_status |= OBJ_LOC_MAP;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::set_in_container(Obj *container_obj) {
|
||||
parent = (void *)container_obj;
|
||||
nuvie_status &= NUVIE_OBJ_STATUS_LOC_MASK_SET;
|
||||
nuvie_status |= OBJ_LOC_CONT;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::set_invisible(bool flag) {
|
||||
if (flag)
|
||||
status |= OBJ_STATUS_INVISIBLE;
|
||||
else if (is_invisible())
|
||||
status ^= OBJ_STATUS_INVISIBLE;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::set_temporary(bool flag) {
|
||||
if (flag)
|
||||
status |= OBJ_STATUS_TEMPORARY;
|
||||
else if (is_temporary())
|
||||
status ^= OBJ_STATUS_TEMPORARY;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::set_ok_to_take(bool flag, bool recursive) {
|
||||
if (flag)
|
||||
status |= OBJ_STATUS_OK_TO_TAKE;
|
||||
else if (is_ok_to_take())
|
||||
status ^= OBJ_STATUS_OK_TO_TAKE;
|
||||
|
||||
if (recursive && container) {
|
||||
for (U6Link *link = container->start(); link != nullptr; link = link->next) {
|
||||
Obj *obj = (Obj *)link->data;
|
||||
obj->set_ok_to_take(flag, recursive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Obj::set_in_inventory() {
|
||||
nuvie_status &= NUVIE_OBJ_STATUS_LOC_MASK_SET;
|
||||
nuvie_status |= OBJ_LOC_INV;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::readied() { //set_readied() ??
|
||||
nuvie_status &= NUVIE_OBJ_STATUS_LOC_MASK_SET;
|
||||
nuvie_status |= OBJ_LOC_READIED;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::set_noloc() {
|
||||
parent = nullptr;
|
||||
nuvie_status &= NUVIE_OBJ_STATUS_LOC_MASK_SET; //clear location bits 0 = no loc
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::set_in_script(bool flag) {
|
||||
if (flag)
|
||||
nuvie_status |= NUVIE_OBJ_STATUS_SCRIPTING;
|
||||
else if (is_script_obj())
|
||||
nuvie_status ^= NUVIE_OBJ_STATUS_SCRIPTING;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::set_actor_obj(bool flag) {
|
||||
if (flag)
|
||||
nuvie_status |= NUVIE_OBJ_STATUS_ACTOR_OBJ;
|
||||
else if (is_actor_obj())
|
||||
nuvie_status ^= NUVIE_OBJ_STATUS_ACTOR_OBJ;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Returns true if an object is in an actor inventory, including containers and readied items. */
|
||||
|
||||
bool Obj::is_in_inventory(bool check_parent) const {
|
||||
switch (get_engine_loc()) {
|
||||
case OBJ_LOC_INV :
|
||||
case OBJ_LOC_READIED :
|
||||
return true;
|
||||
case OBJ_LOC_CONT :
|
||||
if (check_parent)
|
||||
return ((Obj *)parent)->is_in_inventory(check_parent);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 Obj::get_engine_loc() const {
|
||||
return (nuvie_status & NUVIE_OBJ_STATUS_LOC_MASK_GET);
|
||||
}
|
||||
|
||||
Actor *Obj::get_actor_holding_obj() {
|
||||
switch (get_engine_loc()) {
|
||||
case OBJ_LOC_INV :
|
||||
case OBJ_LOC_READIED :
|
||||
return (Actor *)this->parent;
|
||||
|
||||
case OBJ_LOC_CONT :
|
||||
return ((Obj *)parent)->get_actor_holding_obj();
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//Add child object into container, stacking if required
|
||||
void Obj::add(Obj *obj, bool stack, bool addAtTail) {
|
||||
if (container == nullptr)
|
||||
make_container();
|
||||
|
||||
if (stack && Game::get_game()->get_obj_manager()->is_stackable(obj))
|
||||
add_and_stack(obj, addAtTail);
|
||||
else
|
||||
if (!addAtTail)
|
||||
container->addAtPos(0, obj);
|
||||
else
|
||||
container->add(obj);
|
||||
|
||||
obj->set_in_container(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Obj::add_and_stack(Obj *obj, bool addAtTail) {
|
||||
U6Link *link;
|
||||
Obj *cont_obj;
|
||||
|
||||
//should we recurse through nested containers?
|
||||
for (link = container->start(); link != nullptr;) {
|
||||
cont_obj = (Obj *)link->data;
|
||||
link = link->next;
|
||||
//match on obj_n, frame_n and quality.
|
||||
if (obj->obj_n == cont_obj->obj_n && obj->frame_n == cont_obj->frame_n && obj->quality == cont_obj->quality) {
|
||||
obj->qty += cont_obj->qty;
|
||||
container->replace(cont_obj, obj); //replace cont_obj with obj in container list. should we do this to link->data directly?
|
||||
delete_obj(cont_obj);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!addAtTail)
|
||||
container->addAtPos(0, obj); // add the object as we couldn't find another object to stack with.
|
||||
else
|
||||
container->add(obj);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//Remove child object from container.
|
||||
bool Obj::remove(Obj *obj) {
|
||||
if (container == nullptr)
|
||||
return false;
|
||||
|
||||
if (container->remove(obj) == false)
|
||||
return false;
|
||||
if (Game::get_game()->get_game_type() == NUVIE_GAME_SE) {
|
||||
if (obj_n == OBJ_SE_JAR)
|
||||
frame_n = 0; // empty jar frame
|
||||
}
|
||||
obj->x = 0;
|
||||
obj->y = 0;
|
||||
obj->z = 0;
|
||||
|
||||
obj->set_noloc();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (container == nullptr)
|
||||
return nullptr;
|
||||
|
||||
for (link = container->start(); link != nullptr; link = link->next) {
|
||||
obj = (Obj *)link->data;
|
||||
if (obj) {
|
||||
if (obj->obj_n == objN && (match_quality == false || obj->quality == quality_) && (match_frame_n == false || obj->frame_n == frameN)) {
|
||||
if (prev_obj != nullptr && obj == *prev_obj)
|
||||
prev_obj = nullptr;
|
||||
else {
|
||||
if (prev_obj == nullptr || *prev_obj == nullptr)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->container) {
|
||||
obj = obj->find_in_container(objN, quality_, match_quality, frameN, match_frame_n, prev_obj);
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32 Obj::get_total_qty(uint16 match_obj_n) {
|
||||
U6Link *link;
|
||||
Obj *obj;
|
||||
uint16 total_qty = 0;
|
||||
|
||||
if (obj_n == match_obj_n) {
|
||||
if (qty == 0)
|
||||
total_qty += 1;
|
||||
else
|
||||
total_qty += qty;
|
||||
}
|
||||
|
||||
if (container != nullptr) {
|
||||
for (link = container->start(); link != nullptr; link = link->next) {
|
||||
obj = (Obj *)link->data;
|
||||
if (obj) {
|
||||
if (obj->container)
|
||||
total_qty += obj->get_total_qty(match_obj_n);
|
||||
else if (obj->obj_n == match_obj_n) {
|
||||
if (obj->qty == 0)
|
||||
total_qty += 1;
|
||||
else
|
||||
total_qty += obj->qty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return total_qty;
|
||||
}
|
||||
|
||||
uint32 Obj::container_count_objects() const {
|
||||
uint32 count = 0;
|
||||
U6Link *link;
|
||||
|
||||
if (container != nullptr) {
|
||||
for (link = container->start(); link != nullptr; link = link->next) {
|
||||
++count;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
bool Obj::is_ok_to_take() const {
|
||||
return ((status & OBJ_STATUS_OK_TO_TAKE) || Game::get_game()->using_hackmove());
|
||||
}
|
||||
|
||||
} // End of namespace Nuvie
|
||||
} // End of namespace Ultima
|
||||
Reference in New Issue
Block a user