Initial commit
This commit is contained in:
276
engines/prince/mob.cpp
Normal file
276
engines/prince/mob.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
/* 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 "prince/prince.h"
|
||||
|
||||
#include "prince/mob.h"
|
||||
#include "prince/animation.h"
|
||||
#include "prince/font.h"
|
||||
|
||||
namespace Prince {
|
||||
|
||||
bool Mob::loadFromStream(Common::SeekableReadStream &stream) {
|
||||
int32 pos = stream.pos();
|
||||
|
||||
uint16 visible = stream.readUint16LE();
|
||||
|
||||
if (visible == 0xFFFF)
|
||||
return false;
|
||||
|
||||
_visible = visible;
|
||||
_type = stream.readUint16LE();
|
||||
_rect.left = stream.readUint16LE();
|
||||
_rect.top = stream.readUint16LE();
|
||||
_rect.right = stream.readUint16LE();
|
||||
_rect.bottom = stream.readUint16LE();
|
||||
|
||||
_mask = stream.readUint16LE();
|
||||
|
||||
_examPosition.x = stream.readUint16LE();
|
||||
_examPosition.y = stream.readUint16LE();
|
||||
_examDirection = (Direction)stream.readUint16LE();
|
||||
|
||||
_usePosition.x = stream.readByte();
|
||||
_usePosition.y = stream.readByte();
|
||||
_useDirection = (Direction)stream.readUint16LE();
|
||||
|
||||
uint32 nameOffset = stream.readUint32LE();
|
||||
uint32 examTextOffset = stream.readUint32LE();
|
||||
|
||||
byte c;
|
||||
stream.seek(nameOffset);
|
||||
_name.clear();
|
||||
while ((c = stream.readByte()))
|
||||
_name += c;
|
||||
|
||||
stream.seek(examTextOffset);
|
||||
_examText.clear();
|
||||
c = stream.readByte();
|
||||
if (c) {
|
||||
_examText += c;
|
||||
do {
|
||||
c = stream.readByte();
|
||||
_examText += c;
|
||||
} while (c != 255);
|
||||
}
|
||||
stream.seek(pos + 32);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mob::setData(AttrId dataId, uint16 value) {
|
||||
switch (dataId) {
|
||||
case kMobExamDir:
|
||||
_examDirection = (Direction)value;
|
||||
break;
|
||||
case kMobExamX:
|
||||
_examPosition.x = value;
|
||||
break;
|
||||
case kMobExamY:
|
||||
_examPosition.y = value;
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
uint16 Mob::getData(AttrId dataId) {
|
||||
switch (dataId) {
|
||||
case kMobVisible:
|
||||
return _visible;
|
||||
case kMobExamDir:
|
||||
return _examDirection;
|
||||
case kMobExamX:
|
||||
return _examPosition.x;
|
||||
case kMobExamY:
|
||||
return _examPosition.y;
|
||||
default:
|
||||
assert(false);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int PrinceEngine::getMob(Common::Array<Mob> &mobList, bool usePriorityList, int posX, int posY) {
|
||||
|
||||
Common::Point pointPos(posX, posY);
|
||||
|
||||
int mobListSize;
|
||||
if (usePriorityList) {
|
||||
mobListSize = _mobPriorityList.size();
|
||||
} else {
|
||||
mobListSize = mobList.size();
|
||||
}
|
||||
|
||||
for (int mobNumber = 0; mobNumber < mobListSize; mobNumber++) {
|
||||
Mob *mob = nullptr;
|
||||
if (usePriorityList) {
|
||||
mob = &mobList[_mobPriorityList[mobNumber]];
|
||||
} else {
|
||||
mob = &mobList[mobNumber];
|
||||
}
|
||||
|
||||
if (mob->_visible) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int type = mob->_type & 7;
|
||||
switch (type) {
|
||||
case 0:
|
||||
case 1:
|
||||
//normal_mob
|
||||
if (!mob->_rect.contains(pointPos)) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
//mob_obj
|
||||
if (mob->_mask < kMaxObjects) {
|
||||
int nr = _objSlot[mob->_mask];
|
||||
if (nr != 0xFF) {
|
||||
Object &obj = *_objList[nr];
|
||||
Common::Rect objectRect(obj._x, obj._y, obj._x + obj._width, obj._y + obj._height);
|
||||
if (objectRect.contains(pointPos)) {
|
||||
Graphics::Surface *objSurface = obj.getSurface();
|
||||
byte *pixel = (byte *)objSurface->getBasePtr(posX - obj._x, posY - obj._y);
|
||||
if (*pixel != 255) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
//check_ba_mob
|
||||
if (!_backAnimList[mob->_mask].backAnims.empty()) {
|
||||
int currentAnim = _backAnimList[mob->_mask]._seq._currRelative;
|
||||
Anim &backAnim = _backAnimList[mob->_mask].backAnims[currentAnim];
|
||||
if (backAnim._animData != nullptr) {
|
||||
if (!backAnim._state) {
|
||||
Common::Rect backAnimRect(backAnim._currX, backAnim._currY, backAnim._currX + backAnim._currW, backAnim._currY + backAnim._currH);
|
||||
if (backAnimRect.contains(pointPos)) {
|
||||
int phase = backAnim._showFrame;
|
||||
int phaseFrameIndex = backAnim._animData->getPhaseFrameIndex(phase);
|
||||
Graphics::Surface *backAnimSurface = backAnim._animData->getFrame(phaseFrameIndex);
|
||||
byte pixel = *(byte *)backAnimSurface->getBasePtr(posX - backAnim._currX, posY - backAnim._currY);
|
||||
if (pixel != 255) {
|
||||
if (type == 5) {
|
||||
if (mob->_rect.contains(pointPos)) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
//not_part_ba
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if (usePriorityList) {
|
||||
return _mobPriorityList[mobNumber];
|
||||
} else {
|
||||
return mobNumber;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int PrinceEngine::checkMob(Graphics::Surface *screen, Common::Array<Mob> &mobList, bool usePriorityList) {
|
||||
if (_mouseFlag == 0 || _mouseFlag == 3) {
|
||||
return -1;
|
||||
}
|
||||
Common::Point mousePos = _system->getEventManager()->getMousePos();
|
||||
int mobNumber = getMob(mobList, usePriorityList, mousePos.x + _picWindowX, mousePos.y);
|
||||
|
||||
if (mobNumber != -1) {
|
||||
Common::String mobName = mobList[mobNumber]._name;
|
||||
|
||||
if (getLanguage() == Common::DE_DEU) {
|
||||
for (uint i = 0; i < mobName.size(); i++) {
|
||||
switch (mobName[i]) {
|
||||
case '\xc4':
|
||||
mobName.setChar('\x83', i);
|
||||
break;
|
||||
case '\xd6':
|
||||
mobName.setChar('\x84', i);
|
||||
break;
|
||||
case '\xdc':
|
||||
mobName.setChar('\x85', i);
|
||||
break;
|
||||
case '\xdf':
|
||||
mobName.setChar('\x7f', i);
|
||||
break;
|
||||
case '\xe4':
|
||||
mobName.setChar('\x80', i);
|
||||
break;
|
||||
case '\xf6':
|
||||
mobName.setChar('\x81', i);
|
||||
break;
|
||||
case '\xfc':
|
||||
mobName.setChar('\x82', i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// _selectedMob can't be used here, as it gets reset when the player clicks, causing the mob
|
||||
// name to be voiced again
|
||||
if (mobNumber != _previousMob) {
|
||||
setTTSVoice(kHeroTextColor);
|
||||
sayText(mobName, false);
|
||||
}
|
||||
|
||||
uint16 textW = getTextWidth(mobName.c_str());
|
||||
|
||||
uint16 x = mousePos.x - textW / 2;
|
||||
if (x > screen->w) {
|
||||
x = 0;
|
||||
}
|
||||
|
||||
if (x + textW > screen->w) {
|
||||
x = screen->w - textW;
|
||||
}
|
||||
|
||||
uint16 y = mousePos.y - _font->getFontHeight();
|
||||
if (y > screen->h) {
|
||||
y = _font->getFontHeight() - 2;
|
||||
}
|
||||
|
||||
_font->drawString(screen, mobName, x, y, screen->w, 216);
|
||||
}
|
||||
|
||||
_previousMob = mobNumber;
|
||||
|
||||
return mobNumber;
|
||||
}
|
||||
|
||||
} // End of namespace Prince
|
||||
Reference in New Issue
Block a user