mirror of
https://github.com/scummvm/scummvm.git
synced 2025-04-02 10:52:32 -04:00
But, pump mouse messages as fast as we can to make the game feel better. This is more accurate to how the original games work. We stop pumping if a mouse click event happens, but that should work petty well. This fixes a number of bugs in the way Willy Beamish was playing.
204 lines
6 KiB
C++
204 lines
6 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 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 "dgds/clock.h"
|
|
#include "dgds/globals.h"
|
|
#include "dgds/dgds.h"
|
|
#include "dgds/font.h"
|
|
#include "dgds/includes.h"
|
|
#include "dgds/request.h"
|
|
|
|
namespace Dgds {
|
|
|
|
class DragonTimeGlobal : public ReadWriteGlobal<int16> {
|
|
public:
|
|
DragonTimeGlobal(uint16 num, int16 *val, Clock &clock) : ReadWriteGlobal<int16>(num, val), _clock(clock) {}
|
|
int16 set(int16 val) override {
|
|
if (val != ReadWriteGlobal::get()) {
|
|
ReadWriteGlobal::set(val);
|
|
// notify that the time changed
|
|
_clock.addGameTime(0);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
private:
|
|
Clock &_clock;
|
|
};
|
|
|
|
Clock::Clock() : _visibleUser(true), _visibleScript(false), _days(0), _days2(0),
|
|
_hours(0), _mins(0), _gameMinsAdded(0), _gameTicksUp(0), _gameTicksDown(0),
|
|
_lastPlayTime(0), _millis(0)
|
|
{
|
|
}
|
|
|
|
Global *Clock::getDaysGlobal(uint16 num) {
|
|
return new DragonTimeGlobal(num, &_days, *this);
|
|
}
|
|
|
|
Global *Clock::getDays2Global(uint16 num) {
|
|
return new ReadWriteGlobal<int16>(num, &_days2);
|
|
}
|
|
|
|
Global *Clock::getHoursGlobal(uint16 num) {
|
|
return new DragonTimeGlobal(num, &_hours, *this);
|
|
}
|
|
|
|
Global *Clock::getMinsGlobal(uint16 num) {
|
|
return new DragonTimeGlobal(num, &_mins, *this);
|
|
}
|
|
|
|
Global *Clock::getGameMinsAddedGlobal(uint16 num) {
|
|
return new ReadOnlyGlobal<int16>(num, &_gameMinsAdded);
|
|
}
|
|
|
|
Global *Clock::getGameTicksUpGlobal(uint16 num) {
|
|
return new ReadOnlyGlobal<int16>(num, &_gameTicksUp);
|
|
}
|
|
|
|
Global *Clock::getGameTicksDownGlobal(uint16 num) {
|
|
return new ReadOnlyGlobal<int16>(num, &_gameTicksDown);
|
|
}
|
|
|
|
static int16 DAYS_PER_MONTH[] = {
|
|
31, 28, 31, 30,
|
|
31, 30, 31, 31,
|
|
30, 31, 30, 31
|
|
};
|
|
|
|
void Clock::addGameTime(int mins) {
|
|
_gameMinsAdded += mins;
|
|
int nhours = (_mins + mins) / 60;
|
|
_mins = (_mins + mins) % 60;
|
|
if (_mins < 0) {
|
|
_mins += 0x3c;
|
|
nhours--;
|
|
}
|
|
int ndays = (_hours + nhours) / 24;
|
|
_hours = (_hours + nhours) % 24;
|
|
if (_hours < 0) {
|
|
_hours += 24;
|
|
_days -= 1;
|
|
}
|
|
_days += ndays;
|
|
// TODO: if any change was made to days/hours/mins..
|
|
//if (plusmins + nhours + ndays != 0)
|
|
// UINT_39e5_0ffa = 0;
|
|
}
|
|
|
|
Common::String Clock::getTimeStr() const {
|
|
int month = 0;
|
|
int day = _days + _days2 + 1;
|
|
while (day > DAYS_PER_MONTH[month]) {
|
|
day -= DAYS_PER_MONTH[month];
|
|
month++;
|
|
if (month == ARRAYSIZE(DAYS_PER_MONTH))
|
|
month = 0;
|
|
}
|
|
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
|
|
if (engine->getGameId() == GID_WILLY) {
|
|
return Common::String::format("DAY %d, %2d:%02d", day - 1, _hours, _mins);
|
|
} else if (engine->getGameLang() == Common::EN_ANY) {
|
|
return Common::String::format("%2d/%02d %2d:%02d", month + 1, day, _hours, _mins);
|
|
} else if (engine->getGameLang() == Common::DE_DEU) {
|
|
return Common::String::format("%2d.%d %2d.%02d", day, month + 1, _hours, _mins);
|
|
} else {
|
|
error("Unsupported language %d", DgdsEngine::getInstance()->getGameLang());
|
|
}
|
|
}
|
|
|
|
void Clock::draw(Graphics::ManagedSurface &surf) {
|
|
DgdsEngine *engine = DgdsEngine::getInstance();
|
|
if (!_visibleUser || !_visibleScript || engine->getGameId() != GID_DRAGON)
|
|
return;
|
|
|
|
const Common::String clockStr = getTimeStr();
|
|
|
|
const FontManager *fontman = engine->getFontMan();
|
|
const DgdsFont *font = fontman->getFont(FontManager::k4x5Font);
|
|
int width = font->getMaxCharWidth() * 12 + 3;
|
|
_drawPos.top = 0;
|
|
_drawPos.bottom = font->getFontHeight() + 6;
|
|
_drawPos.right = SCREEN_WIDTH;
|
|
_drawPos.left = SCREEN_WIDTH - width;
|
|
|
|
RequestData::fillBackground(&surf, _drawPos.left + 2, _drawPos.top + 2, _drawPos.width() - 4, _drawPos.height() - 4, 65);
|
|
font->drawString(&surf, clockStr, _drawPos.left + 3, _drawPos.top + 3, _drawPos.width(), 0);
|
|
}
|
|
|
|
// Confirmed by timing the clock tick up in the inventory of Dragon and Willy Beamish
|
|
// - 5 game minutes are exactly 25 real time seconds.
|
|
static const int MILLIS_PER_GAME_MIN = 5000;
|
|
static const int MILLIS_PER_TIMER_TICK = 60; // ~16.667 ticks per second.
|
|
|
|
void Clock::update(bool gameRunning) {
|
|
uint32 playTimeNow = DgdsEngine::getInstance()->getThisFrameMs();
|
|
// These timers are updated whether or not the game is running
|
|
_gameTicksUp = playTimeNow / MILLIS_PER_TIMER_TICK;
|
|
|
|
// Is there any reason to make this variable anything other than negative the other one??
|
|
// There seems to be no other way to set them as they are RO globals.
|
|
_gameTicksDown = -_gameTicksUp;
|
|
|
|
uint32 lastLastPlayTime = _lastPlayTime;
|
|
_lastPlayTime = playTimeNow;
|
|
|
|
if (lastLastPlayTime == 0 || !gameRunning)
|
|
return;
|
|
|
|
_millis += playTimeNow - lastLastPlayTime;
|
|
int16 mins_to_add = _millis / MILLIS_PER_GAME_MIN;
|
|
_millis = _millis % MILLIS_PER_GAME_MIN;
|
|
|
|
if (mins_to_add)
|
|
addGameTime(mins_to_add);
|
|
}
|
|
|
|
Common::String Clock::dump() const {
|
|
return Common::String::format("days %d hours %d mins %d", _days, _mins, _hours);
|
|
}
|
|
|
|
Common::Error Clock::syncState(Common::Serializer &s) {
|
|
s.syncAsUint32LE(_lastPlayTime);
|
|
s.syncAsUint32LE(_millis);
|
|
|
|
s.syncAsSint16LE(_gameMinsAdded);
|
|
s.syncAsSint16LE(_gameTicksUp);
|
|
s.syncAsSint16LE(_gameTicksDown);
|
|
s.syncAsSint16LE(_days);
|
|
s.syncAsSint16LE(_days2);
|
|
s.syncAsSint16LE(_hours);
|
|
s.syncAsSint16LE(_mins);
|
|
|
|
s.syncAsSint16LE(_drawPos.left);
|
|
s.syncAsSint16LE(_drawPos.top);
|
|
s.syncAsSint16LE(_drawPos.right);
|
|
s.syncAsSint16LE(_drawPos.bottom);
|
|
|
|
s.syncAsByte(_visibleScript);
|
|
s.syncAsByte(_visibleUser);
|
|
|
|
return Common::kNoError;
|
|
}
|
|
|
|
} // end namespace Dgds
|