mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-07 10:21:31 +00:00
280 lines
8.3 KiB
C++
280 lines
8.3 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/>.
|
|
*
|
|
*
|
|
* Based on the original sources
|
|
* Faery Tale II -- The Halls of the Dead
|
|
* (c) 1993-1996 The Wyrmkeep Entertainment Co.
|
|
*/
|
|
|
|
#include "saga2/saga2.h"
|
|
#include "saga2/calendar.h"
|
|
#include "saga2/intrface.h"
|
|
#include "saga2/localize.h"
|
|
#include "saga2/saveload.h"
|
|
|
|
|
|
namespace Saga2 {
|
|
|
|
/* ===================================================================== *
|
|
FrameAlarm member functions
|
|
* ===================================================================== */
|
|
|
|
void CalendarTime::read(Common::InSaveFile *in) {
|
|
_years = in->readUint16LE();
|
|
_weeks = in->readUint16LE();
|
|
_days = in->readUint16LE();
|
|
_dayInYear = in->readUint16LE();
|
|
_dayInWeek = in->readUint16LE();
|
|
_hour = in->readUint16LE();
|
|
_frameInHour = in->readUint16LE();
|
|
|
|
debugC(3, kDebugSaveload, "... _years = %d", _years);
|
|
debugC(3, kDebugSaveload, "... _weeks = %d", _weeks);
|
|
debugC(3, kDebugSaveload, "... _days = %d", _days);
|
|
debugC(3, kDebugSaveload, "... _dayInYear = %d", _dayInYear);
|
|
debugC(3, kDebugSaveload, "... _dayInWeek = %d", _dayInWeek);
|
|
debugC(3, kDebugSaveload, "... _hour = %d", _hour);
|
|
debugC(3, kDebugSaveload, "... _frameInHour = %d", _frameInHour);
|
|
}
|
|
|
|
void CalendarTime::write(Common::MemoryWriteStreamDynamic *out) {
|
|
out->writeUint16LE(_years);
|
|
out->writeUint16LE(_weeks);
|
|
out->writeUint16LE(_days);
|
|
out->writeUint16LE(_dayInYear);
|
|
out->writeUint16LE(_dayInWeek);
|
|
out->writeUint16LE(_hour);
|
|
out->writeUint16LE(_frameInHour);
|
|
|
|
debugC(3, kDebugSaveload, "... _years = %d", _years);
|
|
debugC(3, kDebugSaveload, "... _weeks = %d", _weeks);
|
|
debugC(3, kDebugSaveload, "... _days = %d", _days);
|
|
debugC(3, kDebugSaveload, "... _dayInYear = %d", _dayInYear);
|
|
debugC(3, kDebugSaveload, "... _dayInWeek = %d", _dayInWeek);
|
|
debugC(3, kDebugSaveload, "... _hour = %d", _hour);
|
|
debugC(3, kDebugSaveload, "... _frameInHour = %d", _frameInHour);
|
|
}
|
|
|
|
void CalendarTime::update() {
|
|
const char *text = nullptr;
|
|
|
|
if (++_frameInHour >= kFramesPerHour) {
|
|
_frameInHour = 0;
|
|
|
|
if (++_hour >= kHoursPerDay) {
|
|
_hour = 0;
|
|
|
|
_days++;
|
|
|
|
if (++_dayInWeek >= kDaysPerWeek) {
|
|
_dayInWeek = 0;
|
|
_weeks++;
|
|
}
|
|
|
|
if (++_dayInYear >= kDaysPerYear) {
|
|
_dayInYear = 0;
|
|
_years++;
|
|
}
|
|
}
|
|
|
|
switch (_hour) {
|
|
case 0:
|
|
text = HOUR00_TIME;
|
|
break;
|
|
case 2:
|
|
text = HOUR02_TIME;
|
|
break;
|
|
case 6:
|
|
text = HOUR06_TIME;
|
|
break;
|
|
case 12:
|
|
text = HOUR12_TIME;
|
|
break;
|
|
case 18:
|
|
text = HOUR18_TIME;
|
|
break;
|
|
case 22:
|
|
text = HOUR22_TIME;
|
|
break;
|
|
}
|
|
|
|
if (text)
|
|
StatusMsg(CALENDAR_STATUS, text, _dayInWeek + 1, _weeks + 1);
|
|
}
|
|
}
|
|
|
|
int CalendarTime::lightLevel(int maxLevel) {
|
|
int16 solarAngle,
|
|
season,
|
|
solarLevel;
|
|
|
|
// solarAngle equals starts at 0 at midnight, then linearly
|
|
// grows to 'kFramesAtNoon' at noon, then shrinks
|
|
// back to 0 at midnight again.
|
|
solarAngle = kFramesAtNoon
|
|
- ABS(frameInDay() - kFramesAtNoon);
|
|
|
|
// Just for fun, we'll make the days longer in the summer,
|
|
// and shorter the winter. The calculation produces a number
|
|
// which equals kDaysPerYear/4 in summer, and -daysperYear/4
|
|
// in winter.
|
|
season = kDaysPerYear / 4 - ABS(_dayInYear - kDaysPerYear / 2);
|
|
|
|
// Convert season to an extra hour of daylight in summer,
|
|
// and an extra hour of night in winter. (That's an extra
|
|
// hour in the morning AND in the evening.
|
|
season = season * kFramesPerHour / (kDaysPerYear / 4);
|
|
|
|
// This produces a triangle wave that goes from -kFramesAtNoon/3
|
|
// to kFramesAtNoon*2/3. Then we clip off the part of the
|
|
// curve below zero, and above 1/3, giving 1/3 night,
|
|
// 1/6 morning, 1/3 day, and 1/6 evening.
|
|
solarLevel = clamp(g_vm->_showNight ? /* 0 */ (kDayBias * 5 / 4) : (kFramesAtNoon / 3),
|
|
solarAngle * 2 + season - kFramesAtNoon / 3 + kDayBias * 2,
|
|
kFramesAtNoon / 3);
|
|
|
|
return (solarLevel * maxLevel) / (kFramesAtNoon / 3);
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
FrameAlarm member functions
|
|
* ===================================================================== */
|
|
|
|
void FrameAlarm::write(Common::MemoryWriteStreamDynamic *out) {
|
|
out->writeUint16LE(_baseFrame);
|
|
out->writeUint16LE(_duration);
|
|
}
|
|
|
|
void FrameAlarm::read(Common::InSaveFile *in) {
|
|
_baseFrame = in->readUint16LE();
|
|
_duration = in->readUint16LE();
|
|
}
|
|
|
|
void FrameAlarm::set(uint16 dur) {
|
|
_baseFrame = g_vm->_calendar->frameInDay();
|
|
_duration = dur;
|
|
}
|
|
|
|
bool FrameAlarm::check() {
|
|
uint16 frameInDay = g_vm->_calendar->frameInDay();
|
|
|
|
return _baseFrame + _duration < CalendarTime::kFramesPerDay
|
|
? frameInDay >= _baseFrame + _duration
|
|
: frameInDay < _baseFrame
|
|
&& frameInDay >= _baseFrame
|
|
+ _duration
|
|
- CalendarTime::kFramesPerDay;
|
|
}
|
|
|
|
// time elapsed since alarm set
|
|
|
|
uint16 FrameAlarm::elapsed() {
|
|
uint16 frameInDay = g_vm->_calendar->frameInDay();
|
|
|
|
return _baseFrame + _duration < CalendarTime::kFramesPerDay
|
|
? frameInDay - _baseFrame
|
|
: frameInDay >= _baseFrame
|
|
? frameInDay - _baseFrame
|
|
: frameInDay + CalendarTime::kFramesPerDay - _baseFrame;
|
|
}
|
|
|
|
/* ===================================================================== *
|
|
Calendar management functions
|
|
* ===================================================================== */
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Pause the global calendar
|
|
|
|
void pauseCalendar() {
|
|
g_vm->_calendar->_calendarPaused = true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Restart the paused global calendar
|
|
|
|
void resumeCalendar() {
|
|
g_vm->_calendar->_calendarPaused = false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Update the global calendar
|
|
|
|
void updateCalendar() {
|
|
if (!g_vm->_calendar->_calendarPaused) g_vm->_calendar->update();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// CalendarTime subtraction operator
|
|
|
|
uint32 operator - (const CalendarTime &time1, const CalendarTime &time2) {
|
|
uint32 time1Frame,
|
|
time2Frame;
|
|
|
|
time1Frame = time1._days * CalendarTime::kFramesPerDay
|
|
+ time1._hour * CalendarTime::kFramesPerHour
|
|
+ time1._frameInHour;
|
|
time2Frame = time2._days * CalendarTime::kFramesPerDay
|
|
+ time2._hour * CalendarTime::kFramesPerHour
|
|
+ time2._frameInHour;
|
|
|
|
return time1Frame - time2Frame;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Initialize the game calendar
|
|
|
|
void initCalendar() {
|
|
g_vm->_calendar->_calendarPaused = false;
|
|
g_vm->_calendar->_years = 0;
|
|
g_vm->_calendar->_weeks = 0;
|
|
g_vm->_calendar->_days = 0;
|
|
g_vm->_calendar->_dayInYear = 0;
|
|
g_vm->_calendar->_dayInWeek = 0;
|
|
g_vm->_calendar->_hour = CalendarTime::kGameStartHour;
|
|
g_vm->_calendar->_frameInHour = 0;
|
|
}
|
|
|
|
void saveCalendar(Common::OutSaveFile *outS) {
|
|
debugC(2, kDebugSaveload, "Saving calendar");
|
|
|
|
outS->write("CALE", 4);
|
|
CHUNK_BEGIN;
|
|
out->writeUint16LE(g_vm->_calendar->_calendarPaused);
|
|
debugC(3, kDebugSaveload, "... _calendarPaused = %d", g_vm->_calendar->_calendarPaused);
|
|
g_vm->_calendar->write(out);
|
|
CHUNK_END;
|
|
}
|
|
|
|
void loadCalendar(Common::InSaveFile *in) {
|
|
debugC(2, kDebugSaveload, "Loading calendar");
|
|
|
|
g_vm->_calendar->_calendarPaused = in->readUint16LE();
|
|
|
|
debugC(3, kDebugSaveload, "... _calendarPaused = %d", g_vm->_calendar->_calendarPaused);
|
|
|
|
g_vm->_calendar->read(in);
|
|
}
|
|
|
|
bool isDayTime() {
|
|
return g_vm->_calendar->lightLevel(MAX_LIGHT) >= (MAX_LIGHT / 2);
|
|
}
|
|
|
|
}
|