569 lines
16 KiB
C++
569 lines
16 KiB
C++
/* ScummVM - Graphic Adventure Engine
|
|
*
|
|
* ScummVM is the legal property of its developers, whose names
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
* file distributed with this source distribution.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#include "titanic/star_control/base_stars.h"
|
|
#include "titanic/star_control/star_camera.h"
|
|
#include "titanic/star_control/star_closeup.h"
|
|
#include "titanic/star_control/star_ref.h"
|
|
#include "titanic/support/files_manager.h"
|
|
#include "titanic/support/simple_file.h"
|
|
#include "titanic/titanic.h"
|
|
|
|
namespace Titanic {
|
|
|
|
CBaseStarEntry::CBaseStarEntry() : _red(0), _value(0.0) {
|
|
Common::fill(&_data[0], &_data[5], 0);
|
|
}
|
|
|
|
void CBaseStarEntry::load(Common::SeekableReadStream &s) {
|
|
_red = s.readByte();
|
|
_green = s.readByte();
|
|
_blue = s.readByte();
|
|
_thickness = s.readByte();
|
|
_value = s.readFloatLE();
|
|
_position._x = s.readFloatLE();
|
|
_position._y = s.readFloatLE();
|
|
_position._z = s.readFloatLE();
|
|
|
|
for (int idx = 0; idx < 5; ++idx)
|
|
_data[idx] = s.readUint32LE();
|
|
}
|
|
|
|
bool CBaseStarEntry::operator==(const CBaseStarEntry &s) const {
|
|
return _red == s._red && _green == s._green
|
|
&& _blue == s._blue && _thickness == s._thickness
|
|
&& _value == s._value && _position == s._position
|
|
&& _data[0] == s._data[0] && _data[1] == s._data[1]
|
|
&& _data[2] == s._data[2] && _data[3] == s._data[3]
|
|
&& _data[4] == s._data[4];
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
CBaseStars::CBaseStars() : _minVal(0.0), _maxVal(1.0), _range(0.0),
|
|
_value1(0.0), _value2(0.0), _value3(0.0), _value4(0.0) {
|
|
}
|
|
|
|
void CBaseStars::clear() {
|
|
_data.clear();
|
|
}
|
|
|
|
void CBaseStars::initialize() {
|
|
_minVal = 9.9999998e10;
|
|
_maxVal = -9.9999998e10;
|
|
_minMax.reset();
|
|
|
|
for (uint idx = 0; idx < _data.size(); ++idx) {
|
|
const CBaseStarEntry *entry = getDataPtr(idx);
|
|
_minMax.expand(entry->_position);
|
|
|
|
if (entry->_value < _minVal)
|
|
_minVal = entry->_value;
|
|
if (entry->_value > _maxVal)
|
|
_maxVal = entry->_value;
|
|
}
|
|
|
|
_range = (_maxVal - _minVal) / 1.0;
|
|
}
|
|
|
|
const CBaseStarEntry *CBaseStars::getDataPtr(int index) const {
|
|
return (index >= 0 && index < (int)_data.size()) ? &_data[index] : nullptr;
|
|
}
|
|
|
|
void CBaseStars::loadData(Common::SeekableReadStream &s) {
|
|
uint headerId = s.readUint32LE();
|
|
uint count = s.readUint32LE();
|
|
if (headerId != 100 || count == 0)
|
|
error("Invalid star data");
|
|
|
|
// Initialize the data array
|
|
clear();
|
|
_data.resize(count);
|
|
|
|
// Iterate through reading the data for each entry
|
|
for (uint idx = 0; idx < count; ++idx)
|
|
_data[idx].load(s);
|
|
}
|
|
|
|
void CBaseStars::loadData(const CString &resName) {
|
|
// Get a stream to read the data from the DAT file
|
|
Common::SeekableReadStream *stream = g_vm->_filesManager->getResource(resName);
|
|
assert(stream);
|
|
|
|
// Load the stream
|
|
loadData(*stream);
|
|
delete stream;
|
|
}
|
|
|
|
void CBaseStars::resetEntry(CBaseStarEntry &entry) {
|
|
entry._red = 0xFF;
|
|
entry._green = 0xFF;
|
|
entry._blue = 0xFF;
|
|
entry._thickness = 0;
|
|
entry._position._x = 0;
|
|
entry._position._y = 0;
|
|
entry._position._z = 0;
|
|
for (int idx = 0; idx < 5; ++idx)
|
|
entry._data[idx] = 0;
|
|
}
|
|
|
|
void CBaseStars::draw(CSurfaceArea *surfaceArea, CStarCamera *camera, CStarCloseup *closeup) {
|
|
if (!_data.empty()) {
|
|
switch (camera->getStarColor()) {
|
|
case WHITE: // draw white, green, and red stars (mostly white)
|
|
switch (surfaceArea->_bpp) {
|
|
case 1:
|
|
draw1(surfaceArea, camera, closeup);
|
|
break;
|
|
case 2:
|
|
draw2(surfaceArea, camera, closeup);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case PINK: // draw pink stars
|
|
switch (surfaceArea->_bpp) {
|
|
case 1:
|
|
draw3(surfaceArea, camera, closeup);
|
|
break;
|
|
case 2:
|
|
draw4(surfaceArea, camera, closeup);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBaseStars::draw1(CSurfaceArea *surfaceArea, CStarCamera *camera, CStarCloseup *closeup) {
|
|
FPose pose = camera->getPose();
|
|
camera->getRelativeXCenterPixels(&_value1, &_value2, &_value3, &_value4);
|
|
|
|
const double MAX_VAL = 1.0e9 * 1.0e9;
|
|
FPoint centroid = surfaceArea->_centroid + FPoint(0.5, 0.5);
|
|
double threshold = camera->getThreshold();
|
|
double minVal = threshold - 9216.0;
|
|
int width1 = surfaceArea->_width - 1;
|
|
int height1 = surfaceArea->_height - 1;
|
|
double *v1Ptr = &_value1, *v2Ptr = &_value2;
|
|
double tempX, tempY, tempZ, total2;
|
|
|
|
for (uint idx = 0; idx < _data.size(); ++idx) {
|
|
CBaseStarEntry &entry = _data[idx];
|
|
const FVector &vector = entry._position;
|
|
tempZ = vector._x * pose._row1._z + vector._y * pose._row2._z
|
|
+ vector._z * pose._row3._z + pose._vector._z;
|
|
if (tempZ <= minVal)
|
|
continue;
|
|
|
|
tempY = vector._x * pose._row1._y + vector._y * pose._row2._y + vector._z * pose._row3._y + pose._vector._y;
|
|
tempX = vector._x * pose._row1._x + vector._y * pose._row2._x + vector._z * pose._row3._x + pose._vector._x;
|
|
total2 = tempY * tempY + tempX * tempX + tempZ * tempZ;
|
|
|
|
if (total2 < 1.0e12) {
|
|
closeup->draw(pose, vector, FVector(centroid._x, centroid._y, total2),
|
|
surfaceArea, camera);
|
|
continue;
|
|
}
|
|
|
|
if (tempZ <= threshold || total2 >= MAX_VAL)
|
|
continue;
|
|
|
|
int xStart = (int)(*v1Ptr * tempX / tempZ + centroid._x);
|
|
int yStart = (int)(*v2Ptr * tempY / tempZ + centroid._y);
|
|
if (xStart < 0 || xStart >= width1 || yStart < 0 || yStart >= height1)
|
|
continue;
|
|
|
|
double sVal = sqrt(total2);
|
|
sVal = (sVal < 100000.0) ? 1.0 : 1.0 - ((sVal - 100000.0) / 1.0e9);
|
|
double red = MIN((double)entry._red * sVal, (double)255.0);
|
|
double green = MIN((double)entry._green * sVal, (double)255.0);
|
|
double blue = MIN((double)entry._green * sVal, (double)255.0);
|
|
|
|
int skipCtr = 0;
|
|
if (red < 0.0) {
|
|
red = 0.0;
|
|
++skipCtr;
|
|
}
|
|
if (green < 0.0) {
|
|
green = 0.0;
|
|
++skipCtr;
|
|
}
|
|
if (blue < 0.0) {
|
|
blue = 0.0;
|
|
++skipCtr;
|
|
}
|
|
if (skipCtr == 3)
|
|
continue;
|
|
|
|
int r = (int)(red - 0.5) & 0xfff8;
|
|
int g = (int)(green - 0.5) & 0xfff8;
|
|
int b = (int)(blue - 0.5) & 0xfff8;
|
|
int rgb = ((g | (r << 5)) << 2) | ((b >> 3) & 0xfff8);
|
|
uint16 *pixelP = (uint16 *)(surfaceArea->_pixelsPtr + surfaceArea->_pitch * yStart + xStart * 2);
|
|
|
|
switch (entry._thickness) {
|
|
case 0:
|
|
*pixelP = rgb;
|
|
break;
|
|
|
|
case 1:
|
|
*pixelP = rgb;
|
|
*(pixelP + 1) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2 + 1) = rgb;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBaseStars::draw2(CSurfaceArea *surfaceArea, CStarCamera *camera, CStarCloseup *closeup) {
|
|
FPose pose = camera->getPose();
|
|
camera->getRelativeXCenterPixels(&_value1, &_value2, &_value3, &_value4);
|
|
|
|
const double MAX_VAL = 1.0e9 * 1.0e9;
|
|
FPoint centroid = surfaceArea->_centroid + FPoint(0.5, 0.5);
|
|
double threshold = camera->getThreshold();
|
|
double minVal = threshold - 9216.0;
|
|
int width1 = surfaceArea->_width - 1;
|
|
int height1 = surfaceArea->_height - 1;
|
|
double *v1Ptr = &_value1, *v2Ptr = &_value2;
|
|
double tempX, tempY, tempZ, total2;
|
|
|
|
for (uint idx = 0; idx < _data.size(); ++idx) {
|
|
CBaseStarEntry &entry = _data[idx];
|
|
const FVector &vector = entry._position;
|
|
tempZ = vector._x * pose._row1._z + vector._y * pose._row2._z
|
|
+ vector._z * pose._row3._z + pose._vector._z;
|
|
if (tempZ <= minVal)
|
|
continue;
|
|
|
|
tempY = vector._x * pose._row1._y + vector._y * pose._row2._y + vector._z * pose._row3._y + pose._vector._y;
|
|
tempX = vector._x * pose._row1._x + vector._y * pose._row2._x + vector._z * pose._row3._x + pose._vector._x;
|
|
total2 = tempY * tempY + tempX * tempX + tempZ * tempZ;
|
|
|
|
if (total2 < 1.0e12) {
|
|
closeup->draw(pose, vector, FVector(centroid._x, centroid._y, total2),
|
|
surfaceArea, camera);
|
|
continue;
|
|
}
|
|
|
|
if (tempZ <= threshold || total2 >= MAX_VAL)
|
|
continue;
|
|
|
|
int xStart = (int)(*v1Ptr * tempX / tempZ + centroid._x);
|
|
int yStart = (int)(*v2Ptr * tempY / tempZ + centroid._y);
|
|
if (xStart < 0 || xStart >= width1 || yStart < 0 || yStart >= height1)
|
|
continue;
|
|
|
|
double sVal = sqrt(total2);
|
|
sVal = (sVal < 100000.0) ? 1.0 : 1.0 - ((sVal - 100000.0) / 1.0e9);
|
|
double red = MIN((double)entry._red * sVal, (double)255.0);
|
|
double green = MIN((double)entry._green * sVal, (double)255.0);
|
|
double blue = MIN((double)entry._green * sVal, (double)255.0);
|
|
|
|
int skipCtr = 0;
|
|
if (red < 0.0) {
|
|
red = 0.0;
|
|
++skipCtr;
|
|
}
|
|
if (green < 0.0) {
|
|
green = 0.0;
|
|
++skipCtr;
|
|
}
|
|
if (blue < 0.0) {
|
|
blue = 0.0;
|
|
++skipCtr;
|
|
}
|
|
if (skipCtr == 3)
|
|
continue;
|
|
|
|
int r = (int)(red - 0.5) & 0xf8;
|
|
int g = (int)(green - 0.5) & 0xfc;
|
|
int b = (int)(blue - 0.5) & 0xfff8;
|
|
|
|
int rgb = ((g | (r << 5)) << 3) | (b >> 3);
|
|
uint16 *pixelP = (uint16 *)(surfaceArea->_pixelsPtr + surfaceArea->_pitch * yStart + xStart * 2);
|
|
|
|
switch (entry._thickness) {
|
|
case 0:
|
|
*pixelP = rgb;
|
|
break;
|
|
|
|
case 1:
|
|
*pixelP = rgb;
|
|
*(pixelP + 1) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2 + 1) = rgb;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBaseStars::draw3(CSurfaceArea *surfaceArea, CStarCamera *camera, CStarCloseup *closeup) {
|
|
FPose pose = camera->getPose();
|
|
camera->getRelativeXCenterPixels(&_value1, &_value2, &_value3, &_value4);
|
|
|
|
const double MAX_VAL = 1.0e9 * 1.0e9;
|
|
FPoint centroid = surfaceArea->_centroid + FPoint(0.5, 0.5);
|
|
double threshold = camera->getThreshold();
|
|
double minVal = threshold - 9216.0;
|
|
int width1 = surfaceArea->_width - 1;
|
|
int height1 = surfaceArea->_height - 1;
|
|
double *v1Ptr = &_value1, *v2Ptr = &_value2;
|
|
double *v3Ptr = &_value3, *v4Ptr = &_value4;
|
|
double tempX, tempY, tempZ, total2, sVal;
|
|
int xStart, yStart, rgb;
|
|
uint16 *pixelP;
|
|
|
|
for (uint idx = 0; idx < _data.size(); ++idx) {
|
|
CBaseStarEntry &entry = _data[idx];
|
|
const FVector &vector = entry._position;
|
|
tempZ = vector._x * pose._row1._z + vector._y * pose._row2._z
|
|
+ vector._z * pose._row3._z + pose._vector._z;
|
|
if (tempZ <= minVal)
|
|
continue;
|
|
|
|
tempY = vector._x * pose._row1._y + vector._y * pose._row2._y + vector._z * pose._row3._y + pose._vector._y;
|
|
tempX = vector._x * pose._row1._x + vector._y * pose._row2._x + vector._z * pose._row3._x + pose._vector._x;
|
|
total2 = tempY * tempY + tempX * tempX + tempZ * tempZ;
|
|
|
|
if (total2 < 1.0e12) {
|
|
closeup->draw(pose, vector, FVector(centroid._x, centroid._y, total2),
|
|
surfaceArea, camera);
|
|
continue;
|
|
}
|
|
|
|
if (tempZ <= threshold || total2 >= MAX_VAL)
|
|
continue;
|
|
|
|
// First pixel
|
|
xStart = (int)((tempX + *v3Ptr) * *v1Ptr / tempZ + centroid._x);
|
|
yStart = (int)(tempY * *v2Ptr / tempZ + centroid._y);
|
|
if (xStart < 0 || xStart >= width1 || yStart < 0 || yStart >= height1)
|
|
continue;
|
|
|
|
sVal = sqrt(total2);
|
|
sVal = (sVal < 100000.0) ? 1.0 : 1.0 - ((sVal - 100000.0) / 1.0e9);
|
|
sVal *= 255.0;
|
|
|
|
if (sVal > 255.0)
|
|
sVal = 255.0;
|
|
|
|
if (sVal > 2.0) {
|
|
pixelP = (uint16 *)(surfaceArea->_pixelsPtr + surfaceArea->_pitch * yStart + xStart * 2);
|
|
rgb = ((int)(sVal - 0.5) & 0xf8) << 7;
|
|
|
|
switch (entry._thickness) {
|
|
case 0:
|
|
*pixelP = rgb;
|
|
break;
|
|
|
|
case 1:
|
|
*pixelP = rgb;
|
|
*(pixelP + 1) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2 + 1) = rgb;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Second pixel
|
|
xStart = (int)((tempX + *v4Ptr) * *v1Ptr / tempZ + centroid._x);
|
|
yStart = (int)(tempY * *v2Ptr / tempZ + centroid._y);
|
|
if (xStart < 0 || xStart >= width1 || yStart < 0 || yStart >= height1)
|
|
continue;
|
|
|
|
sVal = sqrt(total2);
|
|
sVal = (sVal < 100000.0) ? 1.0 : 1.0 - ((sVal - 100000.0) / 1.0e9);
|
|
sVal *= 255.0;
|
|
|
|
if (sVal > 255.0)
|
|
sVal = 255.0;
|
|
|
|
if (sVal > 2.0) {
|
|
pixelP = (uint16 *)(surfaceArea->_pixelsPtr + surfaceArea->_pitch * yStart + xStart * 2);
|
|
rgb = ((int)(sVal - 0.5) & 0xf8) << 7;
|
|
|
|
switch (entry._thickness) {
|
|
case 0:
|
|
*pixelP |= rgb;
|
|
break;
|
|
|
|
case 1:
|
|
*pixelP |= rgb;
|
|
*(pixelP + 1) |= rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2) |= rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2 + 1) |= rgb;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CBaseStars::draw4(CSurfaceArea *surfaceArea, CStarCamera *camera, CStarCloseup *closeup) {
|
|
FPose pose = camera->getPose();
|
|
camera->getRelativeXCenterPixels(&_value1, &_value2, &_value3, &_value4);
|
|
|
|
const double MAX_VAL = 1.0e9 * 1.0e9;
|
|
FPoint centroid = surfaceArea->_centroid + FPoint(0.5, 0.5);
|
|
double threshold = camera->getThreshold();
|
|
double minVal = threshold - 9216.0;
|
|
int width1 = surfaceArea->_width - 1;
|
|
int height1 = surfaceArea->_height - 1;
|
|
double *v1Ptr = &_value1, *v2Ptr = &_value2, *v3Ptr = &_value3, *v4Ptr = &_value4;
|
|
double tempX, tempY, tempZ, total2, sVal;
|
|
int xStart, yStart, rgb;
|
|
uint16 *pixelP;
|
|
|
|
for (uint idx = 0; idx < _data.size(); ++idx) {
|
|
const CBaseStarEntry &entry = _data[idx];
|
|
const FVector &vector = entry._position;
|
|
|
|
tempZ = vector._x * pose._row1._z + vector._y * pose._row2._z
|
|
+ vector._z * pose._row3._z + pose._vector._z;
|
|
if (tempZ <= minVal)
|
|
continue;
|
|
|
|
tempY = vector._x * pose._row1._y + vector._y * pose._row2._y + vector._z * pose._row3._y + pose._vector._y;
|
|
tempX = vector._x * pose._row1._x + vector._y * pose._row2._x + vector._z * pose._row3._x + pose._vector._x;
|
|
total2 = tempY * tempY + tempX * tempX + tempZ * tempZ;
|
|
|
|
if (total2 < 1.0e12) {
|
|
// We're in close proximity to the given star, so draw a closeup of it
|
|
closeup->draw(pose, vector, FVector(centroid._x, centroid._y, total2),
|
|
surfaceArea, camera);
|
|
continue;
|
|
}
|
|
|
|
if (tempZ <= threshold || total2 >= MAX_VAL)
|
|
continue;
|
|
|
|
// First pixel
|
|
xStart = (int)((tempX + *v3Ptr) * *v1Ptr / tempZ + centroid._x);
|
|
yStart = (int)(tempY * *v2Ptr / tempZ + centroid._y);
|
|
if (xStart < 0 || xStart >= width1 || yStart < 0 || yStart >= height1)
|
|
continue;
|
|
|
|
sVal = sqrt(total2);
|
|
sVal = (sVal < 100000.0) ? 1.0 : 1.0 - ((sVal - 100000.0) / 1.0e9);
|
|
sVal *= 255.0;
|
|
|
|
if (sVal > 255.0)
|
|
sVal = 255.0;
|
|
|
|
if (sVal > 2.0) {
|
|
pixelP = (uint16 *)(surfaceArea->_pixelsPtr + surfaceArea->_pitch * yStart + xStart * 2);
|
|
rgb = ((int)(sVal - 0.5) & 0xf8) << 8;
|
|
|
|
switch (entry._thickness) {
|
|
case 0:
|
|
*pixelP = rgb;
|
|
break;
|
|
|
|
case 1:
|
|
*pixelP = rgb;
|
|
*(pixelP + 1) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2) = rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2 + 1) = rgb;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Second pixel
|
|
xStart = (int)((tempX + *v4Ptr) * *v1Ptr / tempZ + centroid._x);
|
|
yStart = (int)((tempY * *v2Ptr) / tempZ + centroid._y);
|
|
if (xStart < 0 || xStart >= width1 || yStart < 0 || yStart >= height1)
|
|
continue;
|
|
|
|
sVal = sqrt(total2);
|
|
sVal = (sVal < 100000.0) ? 1.0 : 1.0 - ((sVal - 100000.0) / 1.0e9);
|
|
sVal *= 255.0;
|
|
|
|
if (sVal > 255.0)
|
|
sVal = 255.0;
|
|
|
|
if (sVal > 2.0) {
|
|
pixelP = (uint16 *)(surfaceArea->_pixelsPtr + surfaceArea->_pitch * yStart + xStart * 2);
|
|
rgb = ((int)(sVal - 0.5) >> 3) & 0xff;
|
|
|
|
switch (entry._thickness) {
|
|
case 0:
|
|
*pixelP |= rgb;
|
|
break;
|
|
|
|
case 1:
|
|
*pixelP |= rgb;
|
|
*(pixelP + 1) |= rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2) |= rgb;
|
|
*(pixelP + surfaceArea->_pitch / 2 + 1) |= rgb;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int CBaseStars::findStar(CSurfaceArea *surfaceArea, CStarCamera *camera,
|
|
const Common::Point &pt) {
|
|
CStarRef1 ref(this, pt);
|
|
ref.process(surfaceArea, camera);
|
|
return ref._index;
|
|
}
|
|
|
|
int CBaseStars::baseFn2(CSurfaceArea *surfaceArea, CStarCamera *camera) {
|
|
CStarRef3 ref(this);
|
|
ref.process(surfaceArea, camera);
|
|
return ref._index;
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
void CStarVector::apply() {
|
|
_owner->addLockedStar(_vector);
|
|
}
|
|
|
|
} // End of namespace Titanic
|