Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,45 @@
/* 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/>.
*
*/
#ifndef FREESCAPE_CONNECTIONS_H
#define FREESCAPE_CONNECTIONS_H
#include "freescape/objects/object.h"
namespace Freescape {
class AreaConnections : public Object {
public:
Common::Array<byte> _connections;
AreaConnections(const Common::Array<byte> connections_) {
_objectID = 254;
_connections = connections_;
}
ObjectType getType() override { return ObjectType::kEntranceType; };
void draw(Freescape::Renderer *gfx, float offset = 0.0) override { error("cannot render AreaConnections"); };
void scale(int factor) override { /* Nothing */ };
Object *duplicate() override { error("cannot duplicate AreaConnections"); };
};
} // End of namespace Freescape
#endif // FREESCAPE_CONNECTIONS_H

View File

@@ -0,0 +1,74 @@
/* 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/>.
*
*/
// Based on Phantasma code by Thomas Harte (2013),
// available at https://github.com/TomHarte/Phantasma/ (MIT)
#ifndef FREESCAPE_ENTRANCE_H
#define FREESCAPE_ENTRANCE_H
#include "freescape/objects/object.h"
namespace Freescape {
extern FCLInstructionVector *duplicateCondition(FCLInstructionVector *condition);
class Entrance : public Object {
public:
Entrance(
uint16 objectID_,
const Math::Vector3d &origin_,
const Math::Vector3d &rotation_,
FCLInstructionVector conditionInstructions_,
Common::String conditionSource_) {
_objectID = objectID_;
_origin = origin_;
_rotation = rotation_;
_condition = conditionInstructions_;
_conditionSource = conditionSource_;
_flags = 0;
}
virtual ~Entrance() {}
bool isDrawable() override { return false; }
bool isPlanar() override { return true; }
void scale(int factor) override { _origin = _origin / factor; };
Object *duplicate() override {
FCLInstructionVector *conditionCopy = duplicateCondition(&_condition);
assert(conditionCopy);
Entrance *entrance = new Entrance(_objectID, _origin, _rotation, *conditionCopy, _conditionSource);
delete conditionCopy;
return entrance;
};
ObjectType getType() override { return ObjectType::kEntranceType; };
Math::Vector3d getRotation() { return _rotation; }
Common::String _conditionSource;
FCLInstructionVector _condition;
void draw(Freescape::Renderer *gfx, float offset = 0.0) override { error("cannot render Entrance"); };
};
} // End of namespace Freescape
#endif // FREESCAPE_ENTRANCE_H

View File

@@ -0,0 +1,481 @@
/* 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/>.
*
*/
// Based on Phantasma code by Thomas Harte (2013),
// available at https://github.com/TomHarte/Phantasma/ (MIT)
#include "common/system.h"
#include "freescape/objects/geometricobject.h"
namespace Freescape {
extern FCLInstructionVector *duplicateCondition(FCLInstructionVector *condition);
int GeometricObject::numberOfColoursForObjectOfType(ObjectType type) {
switch (type) {
default:
case kEntranceType:
case kGroupType:
case kSensorType:
return 0;
case kLineType:
return 2;
case kRectangleType:
case kTriangleType:
case kQuadrilateralType:
case kPentagonType:
case kHexagonType:
return 2;
case kCubeType:
case kEastPyramidType:
case kWestPyramidType:
case kUpPyramidType:
case kDownPyramidType:
case kNorthPyramidType:
case kSouthPyramidType:
return 6;
}
}
int GeometricObject::numberOfOrdinatesForType(ObjectType type) {
switch (type) {
default:
case kEntranceType:
case kGroupType:
case kRectangleType:
case kSensorType:
return 0;
case kEastPyramidType:
case kWestPyramidType:
case kUpPyramidType:
case kDownPyramidType:
case kNorthPyramidType:
case kSouthPyramidType:
return 4;
case kLineType:
case kTriangleType:
case kQuadrilateralType:
case kPentagonType:
case kHexagonType:
return 3 * (2 + type - kLineType);
}
}
bool GeometricObject::isPyramid(ObjectType type) {
switch (type) {
default:
return false;
case kEastPyramidType:
case kWestPyramidType:
case kUpPyramidType:
case kDownPyramidType:
case kNorthPyramidType:
case kSouthPyramidType:
return true;
}
}
bool GeometricObject::isPolygon(ObjectType type) {
switch (type) {
default:
return false;
case kLineType:
case kTriangleType:
case kQuadrilateralType:
case kPentagonType:
case kHexagonType:
return true;
}
}
GeometricObject::GeometricObject(
ObjectType type_,
uint16 objectID_,
uint16 flags_,
const Math::Vector3d &origin_,
const Math::Vector3d &size_,
Common::Array<uint8> *colours_,
Common::Array<uint8> *ecolours_,
Common::Array<float> *ordinates_,
FCLInstructionVector conditionInstructions_,
Common::String conditionSource_) {
_type = type_;
assert(_type != kGroupType);
_flags = flags_;
if (isDestroyed()) // If the object is destroyed, restore it
restore();
if (isInitiallyInvisible())
makeInvisible();
else
makeVisible();
_objectID = objectID_;
_origin = origin_;
_size = size_;
_colours = nullptr;
if (colours_)
_colours = colours_;
_ecolours = nullptr;
if (ecolours_)
_ecolours = ecolours_;
_cyclingColors = false; // This needs to be set manually
_ordinates = nullptr;
_initialOrdinates = nullptr;
if (ordinates_) {
_ordinates = ordinates_;
_initialOrdinates = new Common::Array<float>(*_ordinates);
}
_condition = conditionInstructions_;
_conditionSource = conditionSource_;
if (_type == kRectangleType) {
if ((_size.x() == 0 && _size.y() == 0) ||
(_size.y() == 0 && _size.z() == 0) ||
(_size.x() == 0 && _size.z() == 0)) {
_type = kLineType;
assert(!_ordinates);
_ordinates = new Common::Array<float>();
_ordinates->push_back(_origin.x());
_ordinates->push_back(_origin.y());
_ordinates->push_back(_origin.z());
_ordinates->push_back(_origin.x() + _size.x());
_ordinates->push_back(_origin.y() + _size.y());
_ordinates->push_back(_origin.z() + _size.z());
}
} else if (isPyramid(_type))
assert(_size.x() > 0 && _size.y() > 0 && _size.z() > 0);
computeBoundingBox();
}
void GeometricObject::setOrigin(Math::Vector3d origin_) {
_origin = origin_;
computeBoundingBox();
}
void GeometricObject::offsetOrigin(Math::Vector3d origin_) {
if (isPolygon(_type)) {
Math::Vector3d offset = origin_ - _origin;
for (int i = 0; i < int(_ordinates->size()); i = i + 3) {
float ordinate = 0;
ordinate = (*_ordinates)[i];
ordinate += offset.x();
assert(ordinate >= 0);
(*_ordinates)[i] = ordinate;
ordinate = (*_ordinates)[i + 1];
ordinate += offset.y();
assert(ordinate >= 0);
(*_ordinates)[i + 1] = ordinate;
ordinate = (*_ordinates)[i + 2];
ordinate += offset.z();
assert(ordinate >= 0);
(*_ordinates)[i + 2] = ordinate;
}
}
setOrigin(origin_);
}
void GeometricObject::scale(int factor) {
_origin = _origin / factor;
_size = _size / factor;
if (_ordinates) {
for (uint i = 0; i < _ordinates->size(); i++) {
(*_ordinates)[i] = (*_ordinates)[i] / factor;
if (_initialOrdinates)
(*_initialOrdinates)[i] = (*_initialOrdinates)[i] / factor;
}
}
computeBoundingBox();
}
void GeometricObject::restoreOrdinates() {
if (!isPolygon(_type))
return;
for (uint i = 0; i < _ordinates->size(); i++)
(*_ordinates)[i] = (*_initialOrdinates)[i];
computeBoundingBox();
}
Object *GeometricObject::duplicate() {
Common::Array<uint8> *coloursCopy = nullptr;
Common::Array<uint8> *ecoloursCopy = nullptr;
Common::Array<float> *ordinatesCopy = nullptr;
FCLInstructionVector *conditionCopy = nullptr;
if (_colours)
coloursCopy = new Common::Array<uint8>(*_colours);
if (_ecolours)
ecoloursCopy = new Common::Array<uint8>(*_ecolours);
if (_ordinates)
ordinatesCopy = new Common::Array<float>(*_ordinates);
conditionCopy = duplicateCondition(&_condition);
assert(conditionCopy);
GeometricObject *copy = new GeometricObject(
_type,
_objectID,
_flags,
_origin,
_size,
coloursCopy,
ecoloursCopy,
ordinatesCopy,
*conditionCopy,
_conditionSource
);
copy->_cyclingColors = _cyclingColors;
return copy;
}
void GeometricObject::computeBoundingBox() {
_boundingBox = Math::AABB();
Math::Vector3d v;
switch (_type) {
default:
break;
case kCubeType:
_boundingBox.expand(_origin);
for (int i = 0; i < 3; i++) {
v = _origin;
v.setValue(i, v.getValue(i) + _size.getValue(i));
_boundingBox.expand(v);
}
for (int i = 0; i < 3; i++) {
v = _origin + _size;
v.setValue(i, v.getValue(i) - _size.getValue(i));
_boundingBox.expand(v);
}
_boundingBox.expand(_origin + _size);
assert(_boundingBox.isValid());
break;
case kRectangleType:
_boundingBox.expand(_origin);
_boundingBox.expand(_origin + _size);
break;
case kLineType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
for (uint i = 0; i < _ordinates->size(); i = i + 3) {
_boundingBox.expand(Math::Vector3d((*_ordinates)[i], (*_ordinates)[i + 1], (*_ordinates)[i + 2]));
}
int dx, dy, dz;
dx = dy = dz = 0;
if (_size.x() == 0 && _size.y() == 0) {
dx = 2;
dy = 2;
} else if (_size.x() == 0 && _size.z() == 0) {
dx = 2;
dz = 2;
} else if (_size.y() == 0 && _size.z() == 0) {
dy = 2;
dz = 2;
}
for (uint i = 0; i < _ordinates->size(); i = i + 3) {
_boundingBox.expand(Math::Vector3d((*_ordinates)[i] + dx, (*_ordinates)[i + 1] + dy, (*_ordinates)[i + 2] + dz));
}
break;
case kTriangleType:
case kQuadrilateralType:
case kPentagonType:
case kHexagonType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
for (uint i = 0; i < _ordinates->size(); i = i + 3) {
_boundingBox.expand(Math::Vector3d((*_ordinates)[i], (*_ordinates)[i + 1], (*_ordinates)[i + 2]));
}
break;
case kEastPyramidType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
_boundingBox.expand(_origin + Math::Vector3d(0, 0, _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(0, _size.y(), _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(0, _size.y(), 0));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), (*_ordinates)[0], (*_ordinates)[3]));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), (*_ordinates)[2], (*_ordinates)[3]));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), (*_ordinates)[2], (*_ordinates)[1]));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), (*_ordinates)[0], (*_ordinates)[1]));
break;
case kWestPyramidType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), 0, 0));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), _size.y(), 0));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), _size.y(), _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), 0, _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(0, (*_ordinates)[0], (*_ordinates)[1]));
_boundingBox.expand(_origin + Math::Vector3d(0, (*_ordinates)[2], (*_ordinates)[1]));
_boundingBox.expand(_origin + Math::Vector3d(0, (*_ordinates)[2], (*_ordinates)[3]));
_boundingBox.expand(_origin + Math::Vector3d(0, (*_ordinates)[0], (*_ordinates)[3]));
break;
case kUpPyramidType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), 0, 0));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), 0, _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(0, 0, _size.z()));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], _size.y(), (*_ordinates)[1]));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], _size.y(), (*_ordinates)[1]));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], _size.y(), (*_ordinates)[3]));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], _size.y(), (*_ordinates)[3]));
break;
case kDownPyramidType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), _size.y(), 0));
_boundingBox.expand(_origin + Math::Vector3d(0, _size.y(), 0));
_boundingBox.expand(_origin + Math::Vector3d(0, _size.y(), _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), _size.y(), _size.z()));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], 0, (*_ordinates)[1]));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], 0, (*_ordinates)[1]));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], 0, (*_ordinates)[3]));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], 0, (*_ordinates)[3]));
break;
case kNorthPyramidType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
_boundingBox.expand(_origin + Math::Vector3d(0, _size.y(), 0));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), _size.y(), 0));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), 0, 0));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], (*_ordinates)[3], _size.z()));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], (*_ordinates)[3], _size.z()));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], (*_ordinates)[1], _size.z()));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], (*_ordinates)[1], _size.z()));
break;
case kSouthPyramidType:
if (!_ordinates)
error("Ordinates needed to compute bounding box!");
_boundingBox.expand(_origin + Math::Vector3d(0, 0, _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), 0, _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(_size.x(), _size.y(), _size.z()));
_boundingBox.expand(_origin + Math::Vector3d(0, _size.y(), _size.z()));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], (*_ordinates)[1], 0));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], (*_ordinates)[1], 0));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[2], (*_ordinates)[3], 0));
_boundingBox.expand(_origin + Math::Vector3d((*_ordinates)[0], (*_ordinates)[3], 0));
break;
}
}
GeometricObject::~GeometricObject() {
delete _colours;
delete _ordinates;
delete _initialOrdinates;
}
// This function returns when the object is a line, but it is not a straight line
bool GeometricObject::isLineButNotStraight() {
if (_type != kLineType)
return false;
if (!_ordinates)
return false;
if (_ordinates->size() != 6)
return false;
// At least two coordinates should be the same to be a straight line
if ((*_ordinates)[0] == (*_ordinates)[3] && (*_ordinates)[1] == (*_ordinates)[4])
return false;
if ((*_ordinates)[0] == (*_ordinates)[3] && (*_ordinates)[2] == (*_ordinates)[5])
return false;
if ((*_ordinates)[1] == (*_ordinates)[4] && (*_ordinates)[2] == (*_ordinates)[5])
return false;
return true;
}
bool GeometricObject::isDrawable() { return true; }
bool GeometricObject::isPlanar() {
ObjectType t = this->getType();
return (t >= kLineType) || t == kRectangleType || !_size.x() || !_size.y() || !_size.z();
}
bool GeometricObject::collides(const Math::AABB &boundingBox_) {
if (isDestroyed() || isInvisible() || !_boundingBox.isValid() || !boundingBox_.isValid())
return false;
return _boundingBox.collides(boundingBox_);
}
void GeometricObject::draw(Renderer *gfx, float offset) {
if (_cyclingColors) {
assert(_colours);
if (g_system->getMillis() % 10 == 0)
for (uint i = 0; i < _colours->size(); i++) {
(*_colours)[i] = ((*_colours)[i] + 1) % 0xf;
if (_ecolours)
(*_ecolours)[i] = ((*_ecolours)[i] + 1) % 0xf;
}
}
if (this->getType() == kCubeType) {
gfx->renderCube(_origin, _size, _colours, _ecolours, offset);
} else if (this->getType() == kRectangleType) {
gfx->renderRectangle(_origin, _size, _colours, _ecolours, offset);
} else if (isPyramid(this->getType())) {
gfx->renderPyramid(_origin, _size, _ordinates, _colours, _ecolours, this->getType());
} else if (this->isPlanar() && _type <= 14) {
if (this->getType() == kTriangleType)
assert(_ordinates->size() == 9);
gfx->renderPolygon(_origin, _size, _ordinates, _colours, _ecolours, offset);
}
}
} // End of namespace Freescape

View File

@@ -0,0 +1,80 @@
/* 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/>.
*
*/
// Based on Phantasma code by Thomas Harte (2013),
// available at https://github.com/TomHarte/Phantasma/ (MIT)
#ifndef FREESCAPE_GEOMETRICOBJECT_H
#define FREESCAPE_GEOMETRICOBJECT_H
#include "freescape/language/instruction.h"
#include "freescape/objects/group.h"
#include "freescape/objects/object.h"
namespace Freescape {
class GeometricObject : public Object {
public:
static int numberOfColoursForObjectOfType(ObjectType type);
static int numberOfOrdinatesForType(ObjectType type);
static bool isPyramid(ObjectType type);
static bool isPolygon(ObjectType type);
GeometricObject(
ObjectType type,
uint16 objectID,
uint16 flags,
const Math::Vector3d &origin,
const Math::Vector3d &size,
Common::Array<uint8> *colours,
Common::Array<uint8> *ecolours,
Common::Array<float> *ordinates,
FCLInstructionVector conditionInstructions,
Common::String conditionSource = "");
virtual ~GeometricObject();
void setOrigin(Math::Vector3d origin) override;
void offsetOrigin(Math::Vector3d origin_);
void restoreOrdinates();
Object *duplicate() override;
void scale(int factor) override;
void computeBoundingBox();
bool collides(const Math::AABB &boundingBox);
void draw(Freescape::Renderer *gfx, float offset = 0.0) override;
bool isDrawable() override;
bool isPlanar() override;
bool _cyclingColors;
bool isLineButNotStraight();
Common::String _conditionSource;
FCLInstructionVector _condition;
private:
Common::Array<uint8> *_colours;
Common::Array<uint8> *_ecolours;
Common::Array<float> *_ordinates;
Common::Array<float> *_initialOrdinates;
};
} // End of namespace Freescape
#endif // FREESCAPE_GEOMETRICOBJECT_H

View File

@@ -0,0 +1,45 @@
/* 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/>.
*
*/
#ifndef FREESCAPE_GLOBAL_H
#define FREESCAPE_GLOBAL_H
#include "freescape/objects/object.h"
namespace Freescape {
class GlobalStructure : public Object {
public:
Common::Array<byte> _structure;
GlobalStructure(const Common::Array<byte> structure_) {
_objectID = 255;
_structure = structure_;
}
ObjectType getType() override { return ObjectType::kEntranceType; };
void draw(Freescape::Renderer *gfx, float offset = 0.0) override { error("cannot render GlobalStructure"); };
void scale(int factor) override { /* Nothing */ };
Object *duplicate() override { error("cannot duplicate GlobalStructure"); };
};
} // End of namespace Freescape
#endif // FREESCAPE_GLOBAL_H

View File

@@ -0,0 +1,226 @@
/* 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 "freescape/freescape.h"
#include "freescape/objects/group.h"
#include "freescape/objects/geometricobject.h"
#include "freescape/language/8bitDetokeniser.h"
namespace Freescape {
Group::Group(uint16 objectID_, uint16 flags_,
const Common::Array<uint16> objectIds_,
const Math::Vector3d offset1_,
const Math::Vector3d offset2_,
const Common::Array<AnimationOpcode *> operations_) {
_type = kGroupType;
_objectID = objectID_;
_flags = flags_;
_scale = 0;
_active = true;
_step = 0;
_offset1 = offset1_;
_offset2 = offset2_;
for (int i = 0; i < 3; i++) { // three is the maximum number of objects in a group
if (objectIds_[i] == 0 || objectIds_[i] == 0xffff)
break;
_objectIds.push_back(objectIds_[i]);
}
_operations = operations_;
if (isDestroyed()) // If the object is destroyed, restore it
restore();
makeInitiallyVisible();
makeVisible();
}
Group::~Group() {
for (int i = 0; i < int(_operations.size()); i++)
delete _operations[i];
}
Object *Group::duplicate() {
return new Group(
_objectID,
_flags,
_objectIds,
_offset1,
_offset2,
_operations
);
}
void Group::linkObject(Object *obj) {
int objectIndex = -1;
for (int i = 0; i < int(_objectIds.size()) ; i++) {
if (_objectIds[i] == obj->getObjectID()) {
objectIndex = i;
break;
}
}
if (objectIndex == -1)
return;
debugC(1, kFreescapeDebugParser, "Linking object: %d to group %d", obj->getObjectID(), this->getObjectID());
_origins.push_back(obj->getOrigin());
debugC(1, kFreescapeDebugParser, "Origin %f, %f %f", obj->getOrigin().x(), obj->getOrigin().y(), obj->getOrigin().z());
obj->_partOfGroup = this;
_objects.push_back(obj);
}
void Group::assemble(int index) {
GeometricObject *gobj = (GeometricObject *)_objects[index];
Math::Vector3d position = _operations[_step]->position;
Math::Vector3d offset = _origins[index] - _origins[0];
/*if (index == 0)
; // offset is always zero
else if (index == 1)
offset = _offset1;
else if (index == 2)
offset = _offset1 + _offset2;
else
error("Invalid index: %d", index);
offset = 32 * offset / _scale;*/
position = 32 * position / _scale;
debugC(1, kFreescapeDebugGroup, "Group %d: Assembling object %d originally at %f, %f, %f", _objectID, gobj->getObjectID(), gobj->getOrigin().x(), gobj->getOrigin().y(), gobj->getOrigin().z());
gobj->offsetOrigin(position + offset);
debugC(1, kFreescapeDebugGroup, "Group %d: Assembling object %d moved to %f, %f, %f", _objectID, gobj->getObjectID(), gobj->getOrigin().x(), gobj->getOrigin().y(), gobj->getOrigin().z());
}
void Group::run() {
if (!_active)
return;
int opcode = _operations[_step]->opcode;
debugC(1, kFreescapeDebugGroup, "Executing opcode 0x%x at step %d", opcode, _step);
if (opcode == 0x80 || opcode == 0xff) {
debugC(1, kFreescapeDebugGroup, "Executing group rewind");
_active = true;
_step = -1;
if (opcode == 0xff)
return;
//reset();
}
if (opcode & 0x01) {
debugC(1, kFreescapeDebugGroup, "Executing group condition %s", _operations[_step]->conditionSource.c_str());
g_freescape->executeCode(_operations[_step]->condition, false, true, false, false);
}
if (opcode & 0x10) {
uint32 groupSize = _objects.size();
for (uint32 i = 0; i < groupSize ; i++)
assemble(i);
_active = false;
_step++;
}
if (opcode == 0x0) {
debugC(1, kFreescapeDebugGroup, "Executing group assemble");
uint32 groupSize = _objects.size();
for (uint32 i = 0; i < groupSize ; i++)
assemble(i);
}
if (opcode & 0x08) {
uint32 groupSize = _objects.size();
for (uint32 i = 0; i < groupSize ; i++)
_objects[i]->makeVisible();
if (opcode & 0x20) {
for (uint32 i = 0; i < groupSize ; i++)
_objects[i]->destroy();
}
if (opcode & 0x40) {
for (uint32 i = 0; i < groupSize ; i++)
_objects[i]->makeInvisible();
}
}
}
void Group::start() {
makeVisible();
_active = true;
}
void Group::reset() {
uint32 groupSize = _objects.size();
for (uint32 i = 0; i < groupSize ; i++) {
GeometricObject *gobj = (GeometricObject *)_objects[i];
if (GeometricObject::isPolygon(_objects[i]->getType())) {
gobj->setOrigin(_origins[i]);
gobj->restoreOrdinates();
//gobj->makeInvisible();
}
}
}
void Group::draw(Renderer *gfx, float offset) {
if (!_active)
return;
uint32 groupSize = _objects.size();
for (uint32 i = 0; i < groupSize ; i++) {
if (!_objects[i]->isDestroyed() && !_objects[i]->isInvisible())
_objects[i]->draw(gfx);
}
}
void Group::step() {
if (!_active)
return;
debugC(1, kFreescapeDebugGroup, "Stepping group %d", _objectID);
if (_step < int(_operations.size() - 1))
_step++;
else {
_active = false;
_step = -1;
}
}
bool Group::collides(const Math::AABB &aabb) {
uint32 groupSize = _objects.size();
for (uint32 i = 0; i < groupSize ; i++) {
if (!_objects[i]->isInvisible() && !_objects[i]->isDestroyed() && _objects[i]->isDrawable()) {
GeometricObject *gobj = (GeometricObject *)_objects[i];
if (gobj->collides(aabb))
return true;
}
}
return false;
}
void Group::makePartsInvisible() {
uint32 groupSize = _objects.size();
for (uint32 i = 0; i < groupSize ; i++) {
_objects[i]->makeInvisible();
}
}
} // End of namespace Freescape

View File

@@ -0,0 +1,78 @@
/* 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/>.
*
*/
#ifndef FREESCAPE_GROUP_H
#define FREESCAPE_GROUP_H
#include "freescape/gfx.h"
#include "freescape/objects/object.h"
namespace Freescape {
struct AnimationOpcode {
AnimationOpcode(uint16 opcode_) {
opcode = opcode_;
}
uint16 opcode;
Math::Vector3d position;
Common::String conditionSource;
FCLInstructionVector condition;
};
class Group : public Object {
public:
Group(uint16 objectID_, uint16 flags_,
const Common::Array<uint16> objectIds_,
const Math::Vector3d offset1_,
const Math::Vector3d offset2_,
const Common::Array<AnimationOpcode *> operations);
~Group();
void linkObject(Object *obj);
void assemble(int index);
void step();
void run();
void run(int index);
void reset();
void start();
bool collides(const Math::AABB &aabb);
void makePartsInvisible();
Common::Array<Object *> _objects;
Common::Array<Math::Vector3d> _origins;
Math::Vector3d _offset1;
Math::Vector3d _offset2;
Common::Array<AnimationOpcode *> _operations;
Common::Array<uint16> _objectIds;
int _scale;
int _step;
bool _active;
ObjectType getType() override { return ObjectType::kGroupType; };
bool isDrawable() override { return true; }
void draw(Renderer *gfx, float offset = 0.0) override;
void scale(int scale_) override { _scale = scale_; };
bool isActive() { return !isDestroyed() && !isInvisible() && _step > 0 && _active; };
Object *duplicate() override;
};
} // End of namespace Freescape
#endif // FREESCAPE_GLOBAL_H

View File

@@ -0,0 +1,99 @@
/* 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/>.
*
*/
// Based on Phantasma code by Thomas Harte (2013),
// available at https://github.com/TomHarte/Phantasma/ (MIT)
#ifndef FREESCAPE_OBJECT_H
#define FREESCAPE_OBJECT_H
#include "math/aabb.h"
#include "freescape/gfx.h"
namespace Freescape {
enum ObjectType {
kEntranceType = 0,
kCubeType = 1,
kSensorType = 2,
kRectangleType = 3,
kEastPyramidType = 4,
kWestPyramidType = 5,
kUpPyramidType = 6,
kDownPyramidType = 7,
kNorthPyramidType = 8,
kSouthPyramidType = 9,
kLineType = 10,
kTriangleType = 11,
kQuadrilateralType = 12,
kPentagonType = 13,
kHexagonType = 14,
kGroupType = 15
};
class Object {
public:
virtual ObjectType getType() { return _type; }
uint16 getObjectID() { return _objectID; }
uint16 getObjectFlags() { return _flags; }
bool isGeometric() {
return _type != kEntranceType && _type != kGroupType && _type != kSensorType;
}
void setObjectFlags(uint32 flags_) { _flags = flags_; }
Math::Vector3d getOrigin() { return _origin; }
virtual void setOrigin(Math::Vector3d origin_) { _origin = origin_; };
Math::Vector3d getSize() { return _size; }
virtual bool isDrawable() { return false; }
virtual bool isPlanar() { return false; }
virtual void scale(int factor) = 0;
bool isInvisible() { return _flags & 0x40; }
void makeInvisible() { _flags = _flags | 0x40; }
void makeVisible() { _flags = _flags & ~0x40; }
bool isInitiallyInvisible() { return _flags & 0x80; }
void makeInitiallyInvisible() { _flags = _flags | 0x80; }
void makeInitiallyVisible() { _flags = _flags & ~0x80; }
bool isDestroyed() { return _flags & 0x20; }
void destroy() { _flags = _flags | 0x20; }
void restore() { _flags = _flags & ~0x20; }
void toggleVisibility() { _flags = _flags ^ 0x40; }
virtual ~Object() {}
virtual Object *duplicate() = 0;
virtual void draw(Freescape::Renderer *gfx, float offset = 0.0) = 0;
uint16 _flags;
ObjectType _type;
uint16 _objectID;
Math::Vector3d _origin, _size, _rotation;
Math::AABB _boundingBox;
Object *_partOfGroup = nullptr;
};
} // End of namespace Freescape
#endif // FREESCAPE_OBJECT_H

View File

@@ -0,0 +1,114 @@
/* 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 "freescape/objects/sensor.h"
namespace Freescape {
Sensor::Sensor(
uint16 objectID_,
const Math::Vector3d &origin_,
const Math::Vector3d &rotation_,
byte color_,
byte firingInterval_,
uint16 firingRange_,
uint16 axis_,
uint8 flags_,
FCLInstructionVector condition_,
Common::String conditionSource_) {
_type = kSensorType;
_objectID = objectID_;
_origin = origin_;
_rotation = rotation_;
if (axis_ == 0x01 || axis_ == 0x02)
_size = Math::Vector3d(0, 3, 3);
else if (axis_ == 0x04 || axis_ == 0x08)
_size = Math::Vector3d(3, 0, 3);
else if (axis_ == 0x10 || axis_ == 0x20)
_size = Math::Vector3d(3, 3, 0);
else
_size = Math::Vector3d(3, 3, 3);
_colours = new Common::Array<uint8>;
for (int i = 0; i < 6; i++)
_colours->push_back(color_);
_firingInterval = firingInterval_;
_firingRange = firingRange_;
_axis = axis_;
_flags = flags_;
if (isInitiallyInvisible())
makeInvisible();
else
makeVisible();
_conditionSource = conditionSource_;
_condition = condition_;
_isShooting = false;
}
void Sensor::scale(int factor) {
_origin = _origin / factor;
_size = _size / factor;
}
Object *Sensor::duplicate() {
Sensor *sensor = new Sensor(_objectID, _origin, _rotation, (*_colours)[0], _firingInterval, _firingRange, _axis, _flags, _condition, _conditionSource);
return sensor;
}
void Sensor::draw(Freescape::Renderer *gfx, float offset) {
gfx->renderCube(_origin, _size, _colours, nullptr, offset);
}
bool Sensor::playerDetected(const Math::Vector3d &position, Area *area) {
if (isDestroyed() || isInvisible())
return false;
Math::Vector3d diff = _origin - position;
bool detected = false;
if (_axis == 0x01 && diff.x() >= 0)
detected = true;
else if (_axis == 0x02 && diff.x() <= 0)
detected = true;
else if (_axis == 0x04 && diff.y() >= 0)
detected = true;
else if (_axis == 0x08 && diff.y() <= 0)
detected = true;
else if (_axis == 0x10 && diff.z() >= 0)
detected = true;
else if (_axis == 0x20 && diff.z() <= 0)
detected = true;
if (detected) {
Math::Ray sight(_origin, -diff);
detected = area->checkInSight(sight, diff.length());
}
if (detected) {
detected = ABS(diff.x() + ABS(diff.y())) + ABS(diff.z()) <= _firingRange;
}
return detected;
}
} // End of namespace Freescape

View File

@@ -0,0 +1,77 @@
/* 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/>.
*
*/
// Based on Phantasma code by Thomas Harte (2013),
// available at https://github.com/TomHarte/Phantasma/ (MIT)
#ifndef FREESCAPE_SENSOR_H
#define FREESCAPE_SENSOR_H
#include "freescape/area.h"
#include "freescape/objects/object.h"
#include "freescape/language/instruction.h"
namespace Freescape {
class Sensor : public Object {
public:
Sensor(
uint16 objectID_,
const Math::Vector3d &origin_,
const Math::Vector3d &rotation_,
byte color_,
byte firingInterval_,
uint16 firingRange_,
uint16 axis_,
uint8 flags_,
FCLInstructionVector condition_,
Common::String conditionSource_);
byte _firingInterval;
uint16 _firingRange;
uint16 _axis;
bool _isShooting;
Common::String _conditionSource;
FCLInstructionVector _condition;
virtual ~Sensor() { delete _colours; }
bool isDrawable() override { return true; }
bool isPlanar() override { return true; }
bool isShooting() { return _isShooting; }
void scale(int factor) override;
Object *duplicate() override;
ObjectType getType() override { return kSensorType; };
Math::Vector3d getRotation() { return _rotation; }
void shouldShoot(bool shooting) { _isShooting = shooting; }
void draw(Freescape::Renderer *gfx, float offset = 0.0) override;
bool playerDetected(const Math::Vector3d &position, Area *area);
private:
Common::Array<uint8> *_colours;
};
} // End of namespace Freescape
#endif // FREESCAPE_SENSOR_H