Initial commit
This commit is contained in:
297
engines/icb/event_manager.cpp
Normal file
297
engines/icb/event_manager.cpp
Normal file
@@ -0,0 +1,297 @@
|
||||
/* 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.
|
||||
*
|
||||
* Additional copyright for this file:
|
||||
* Copyright (C) 1999-2000 Revolution Software Ltd.
|
||||
* This code is based on source code created by Revolution Software,
|
||||
* used with permission.
|
||||
*
|
||||
* 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 "engines/icb/event_manager.h"
|
||||
#include "engines/icb/global_objects.h"
|
||||
#include "engines/icb/mission.h"
|
||||
|
||||
#include "common/stream.h"
|
||||
|
||||
namespace ICB {
|
||||
|
||||
bool8 _event_manager::HasEventPending(int32 nObjectID) {
|
||||
// First check the ID is in range and the object is running.
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::HasEventPending()", nObjectID);
|
||||
|
||||
// If the object is not running, simply return false.
|
||||
if (!m_pbRunning[nObjectID] || m_pbSuspended[nObjectID])
|
||||
return (FALSE8);
|
||||
|
||||
// Return the flag for the object.
|
||||
return (m_pEventLists[nObjectID].HasEventPending());
|
||||
}
|
||||
|
||||
bool8 _event_manager::CheckEventWaitingForObject(int32 nObjectID, const char *pcEventName) {
|
||||
// First check the ID is in range and the object is running.
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::CheckEventWaitingForObject()", nObjectID);
|
||||
|
||||
// If the object is not running, simply return false.
|
||||
if (!m_pbRunning[nObjectID] || m_pbSuspended[nObjectID])
|
||||
return (FALSE8);
|
||||
|
||||
// Check the object's event list.
|
||||
return (m_pEventLists[nObjectID].CheckEventWaiting(pcEventName));
|
||||
}
|
||||
|
||||
void _event_manager::ShutDownEventProcessingForObject(int32 nObjectID) {
|
||||
// First check the ID is in range and the object is running.
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::ShutDownEventProcessingForObject()", nObjectID);
|
||||
|
||||
// Mark it shut down.
|
||||
m_pbRunning[nObjectID] = FALSE8;
|
||||
}
|
||||
|
||||
void _event_manager::RegisterForEvent(int32 nObjectID, const char *pcEventName) {
|
||||
// First check the ID is in range and the object is running.
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::RegisterForEvent()", nObjectID);
|
||||
|
||||
// Add the event for the object.
|
||||
if (m_pbRunning[nObjectID])
|
||||
m_pEventLists[nObjectID].AddEventForObject(pcEventName);
|
||||
}
|
||||
|
||||
void _event_manager::UnregisterForEvent(int32 nObjectID, const char *pcEventName) {
|
||||
// First check the ID is in range and the object is running.
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::UnregisterForEvent()", nObjectID);
|
||||
|
||||
// Make sure the object is running.
|
||||
if (m_pbRunning[nObjectID]) {
|
||||
// Remove event for the object.
|
||||
m_pEventLists[nObjectID].RemoveEventForObject(pcEventName);
|
||||
|
||||
// This is a useful opportunity to do some cleaning up. Having worked with the implementers, it
|
||||
// seems like desirable behaviour that all events get cleared when you unregister an object for one.
|
||||
m_pEventLists[nObjectID].ClearAllOutstandingEvents();
|
||||
}
|
||||
}
|
||||
|
||||
void _event_manager::ClearAllEventsForObject(int32 nObjectID) {
|
||||
// First check the ID is in range and the object is running.
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::ClearAllEventsForObject()", nObjectID);
|
||||
|
||||
// Clear the object's events.
|
||||
if (m_pbRunning[nObjectID])
|
||||
m_pEventLists[nObjectID].ClearAllOutstandingEvents();
|
||||
}
|
||||
|
||||
void _event_manager::SetSuspendFlagForObject(int32 nObjectID, bool8 bState) {
|
||||
// First check the ID is in range and the object is running.
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::SetSuspendFlagForObject()", nObjectID);
|
||||
|
||||
// Flag the object suspended or not.
|
||||
m_pbSuspended[nObjectID] = bState;
|
||||
}
|
||||
|
||||
bool8 _event_manager::DidObjectSendLastNamedEvent(int32 nCallerID, int32 nObjectID, const char *pcEventName) const {
|
||||
if ((nCallerID < 0) || ((uint32)nCallerID >= m_nNumObjects))
|
||||
Fatal_error("Caller ID %d out of range in _event_manager::DidObjectSendLastEvent()", nCallerID);
|
||||
|
||||
if ((nObjectID < 0) || ((uint32)nObjectID >= m_nNumObjects))
|
||||
Fatal_error("Object ID %d out of range in _event_manager::DidObjectSendLastEvent()", nObjectID);
|
||||
|
||||
// Get the ID of last poster of named event.
|
||||
if (!m_pbRunning[nCallerID] || m_pbSuspended[nCallerID])
|
||||
return (FALSE8);
|
||||
else
|
||||
return (m_pEventLists[nCallerID].DidObjectSendLastNamedEvent(nObjectID, pcEventName));
|
||||
}
|
||||
|
||||
int32 _event_manager::GetIDOfLastObjectToPostEvent(int32 nCallerID, const char *pcEventName) const {
|
||||
if ((nCallerID < 0) || ((uint32)nCallerID >= m_nNumObjects))
|
||||
Fatal_error("Caller ID %d out of range in _event_manager::GetIDOfLastObjectToPostEvent()", nCallerID);
|
||||
|
||||
// Get the ID of last poster of named event.
|
||||
if (!m_pbRunning[nCallerID] || m_pbSuspended[nCallerID])
|
||||
return (FALSE8);
|
||||
else
|
||||
return (m_pEventLists[nCallerID].GetIDOfLastObjectToPostEvent(pcEventName));
|
||||
}
|
||||
|
||||
void _event_manager::PostNamedEventToObject(const char *pcEventName, int32 nTargetID, int32 nSenderID) {
|
||||
if ((nSenderID < 0) || ((uint32)nSenderID >= m_nNumObjects))
|
||||
Fatal_error("Sender ID %d out of range in _event_manager::PostNamedEventToObject()", nSenderID);
|
||||
|
||||
if ((nTargetID < 0) || ((uint32)nTargetID >= m_nNumObjects))
|
||||
Fatal_error("Target ID %d out of range in _event_manager::PostNamedEventToObject()", nTargetID);
|
||||
|
||||
// Post the named event for one object only.
|
||||
if (m_pbRunning[nTargetID] || m_pbSuspended[nTargetID])
|
||||
m_pEventLists[nTargetID].PostNamedEvent(pcEventName, nSenderID);
|
||||
}
|
||||
|
||||
bool8 _event_manager::IsObjectRegisteredForEvent(int32 nCallerID, const char *pcEventName) {
|
||||
if ((nCallerID < 0) || ((uint32)nCallerID >= m_nNumObjects))
|
||||
Fatal_error("Sender ID %d out of range in _event_manager::IsObjectRegisteredForEvent()", nCallerID);
|
||||
|
||||
if (m_pbRunning[nCallerID])
|
||||
return (m_pEventLists[nCallerID].IsEventInList(pcEventName));
|
||||
else
|
||||
return (FALSE8);
|
||||
}
|
||||
|
||||
void _event_manager::Initialise() {
|
||||
uint32 i;
|
||||
|
||||
// Initialize the line-of-sight module.
|
||||
g_oLineOfSight->Initialise();
|
||||
|
||||
// Add an entry for each of the objects in this session.
|
||||
m_nNumObjects = (uint8)MS->total_objects;
|
||||
memset(m_pbRunning, 0, MAX_session_objects * sizeof(bool8));
|
||||
memset(m_pbSuspended, 0, MAX_session_objects * sizeof(bool8));
|
||||
|
||||
for (i = 0; i < m_nNumObjects; ++i) {
|
||||
// Create an event list for the object.
|
||||
m_pEventLists[i].SetNewObjectName(MS->logic_structs[i]->GetName());
|
||||
|
||||
// Flag it running or not.
|
||||
if (MS->logic_structs[i]->ob_status == OB_STATUS_HELD)
|
||||
m_pbRunning[i] = FALSE8;
|
||||
else
|
||||
m_pbRunning[i] = TRUE8;
|
||||
}
|
||||
|
||||
// To start with, no event timers are running.
|
||||
for (i = 0; i < EVENT_MANAGER_MAX_TIMERS; ++i)
|
||||
m_pbActiveTimers[i] = FALSE8;
|
||||
}
|
||||
|
||||
void _event_manager::PostNamedEvent(const char *pcEventName, int32 nSenderID) {
|
||||
uint32 i;
|
||||
|
||||
// Loop through each object in the session.
|
||||
for (i = 0; i < m_nNumObjects; ++i) {
|
||||
// Post the event only if the object is marked as running.
|
||||
if (m_pbRunning[i] && !m_pbSuspended[i])
|
||||
m_pEventLists[i].PostNamedEvent(pcEventName, nSenderID);
|
||||
}
|
||||
}
|
||||
|
||||
void _event_manager::CycleEventManager() {
|
||||
uint32 i;
|
||||
uint32 nElapsed;
|
||||
|
||||
// Loop for each timer.
|
||||
for (i = 0; i < EVENT_MANAGER_MAX_TIMERS; ++i) {
|
||||
// Watch out for unused slots.
|
||||
if (m_pbActiveTimers[i]) {
|
||||
// Process the timer.
|
||||
m_pEventTimers[i].SetEventTime(m_pEventTimers[i].GetEventTime() + 1);
|
||||
|
||||
// If it has gone past the end then it has expired and so needs removing.
|
||||
if (m_pEventTimers[i].GetEventTime() > m_pEventTimers[i].GetEnd()) {
|
||||
// Delete this expired timer.
|
||||
m_pbActiveTimers[i] = FALSE8;
|
||||
} else {
|
||||
// Timer has not expired but might not even have started.
|
||||
if (m_pEventTimers[i].GetEventTime() >= m_pEventTimers[i].GetEnd()) {
|
||||
// Yes, it has started and has not expired. So check if it matches some multiple of
|
||||
// the interval.
|
||||
nElapsed = m_pEventTimers[i].GetEventTime() - m_pEventTimers[i].GetStart();
|
||||
if ((m_pEventTimers[i].GetInterval() == 0) || ((nElapsed % m_pEventTimers[i].GetInterval()) == 0)) {
|
||||
// We need to generate an event.
|
||||
PostNamedEvent(m_pEventTimers[i].GetEventName(), m_pEventTimers[i].GetObjectID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _event_manager::PostRepeatingEvent(const char *pcEventName, uint32 nStart, uint32 nInterval, uint32 nEnd) {
|
||||
uint32 i;
|
||||
|
||||
// Look for a vacant slot.
|
||||
i = 0;
|
||||
while ((i < EVENT_MANAGER_MAX_TIMERS) && m_pbActiveTimers[i])
|
||||
++i;
|
||||
|
||||
// If we ran off the end, we failed to find a spare slot.
|
||||
if (i == EVENT_MANAGER_MAX_TIMERS)
|
||||
Fatal_error("Run out of event timer slots in _event_manager::PostRepeatingEvent()");
|
||||
|
||||
// Set up the timer.
|
||||
m_pEventTimers[i].SetEventName(pcEventName);
|
||||
m_pEventTimers[i].SetStart(nStart);
|
||||
m_pEventTimers[i].SetEnd(nEnd);
|
||||
m_pEventTimers[i].SetInterval(nInterval);
|
||||
m_pEventTimers[i].SetEventTime(0);
|
||||
|
||||
// Flag it as running.
|
||||
m_pbActiveTimers[i] = TRUE8;
|
||||
}
|
||||
|
||||
void _event_manager::Save(Common::WriteStream *stream) const {
|
||||
uint32 i;
|
||||
uint32 nNumActiveTimers = 0;
|
||||
|
||||
// First, work out how many timers we are going to write.
|
||||
for (i = 0; i < EVENT_MANAGER_MAX_TIMERS; ++i) {
|
||||
if (m_pbActiveTimers[i])
|
||||
++nNumActiveTimers;
|
||||
}
|
||||
|
||||
// Write the number of active event timers in the file.
|
||||
stream->writeUint32LE(nNumActiveTimers);
|
||||
|
||||
// Now write the actual active event timers.
|
||||
for (i = 0; i < EVENT_MANAGER_MAX_TIMERS; ++i) {
|
||||
if (m_pbActiveTimers[i])
|
||||
m_pEventTimers[i].Save(stream);
|
||||
}
|
||||
}
|
||||
|
||||
void _event_manager::Restore(Common::SeekableReadStream *stream) {
|
||||
uint32 i;
|
||||
uint32 nNumActiveTimers;
|
||||
_event_timer oEventTimer;
|
||||
|
||||
// Make sure all timers are currently deactivated. This is the same as overwriting them.
|
||||
for (i = 0; i < EVENT_MANAGER_MAX_TIMERS; ++i)
|
||||
m_pbActiveTimers[i] = FALSE8;
|
||||
|
||||
// Find out how many timers we are going to read in.
|
||||
nNumActiveTimers = stream->readUint32LE();
|
||||
|
||||
// Read them in.
|
||||
for (i = 0; i < nNumActiveTimers; ++i) {
|
||||
oEventTimer.Restore(stream);
|
||||
m_pEventTimers[i] = oEventTimer;
|
||||
m_pbActiveTimers[i] = TRUE8;
|
||||
}
|
||||
|
||||
if (stream->err())
|
||||
Fatal_error("Error restoring event timers from save file");
|
||||
}
|
||||
|
||||
} // End of namespace ICB
|
||||
Reference in New Issue
Block a user