scummvm/engines/icb/icon_list_manager.cpp
2020-10-06 09:51:20 +02:00

291 lines
9.5 KiB
C++

/* ResidualVM - A 3D game interpreter
*
* ResidualVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the AUTHORS
* 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 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 "engines/icb/icon_list_manager.h"
#include "engines/icb/global_objects.h"
#include "engines/icb/mission.h"
namespace ICB {
const char *global_icon_list_remora = "icon_list_remora";
const char *global_icon_list_inventory = "icon_list_inventory";
const char *global_icon_list_arms = "icon_list_arms";
_icon_list_manager::_icon_list_manager() {
// The icon lists for the inventory and Remora would get created automatically, but I do it here just so
// I know they always get the same slots, which will be useful in debugging.
m_pListOfLists[0].SetListName(ICON_LIST_INVENTORY);
m_pListOfLists[0].SetScope(GAME_WIDE);
m_pListOfLists[1].SetListName(ICON_LIST_REMORA);
m_pListOfLists[1].SetScope(SESSION_WIDE);
}
void _icon_list_manager::ActivateIconMenu(const char *pcListName, bool8 bAllowEscape, bool8 bDrawStatusIcons) {
uint32 i;
int32 nListIndex;
_icon_menu_duplicates sDuplicates;
uint32 nHash;
int32 nInitialSelected;
uint32 nNumClips, nNumMedi;
nListIndex = FindListByName(pcListName);
// The player object now 'owns' the count of medipacks and clips. To find out how many to draw,
// we need to get these counts here and add them to the inventory. Not in the Remora though.
if (bDrawStatusIcons) {
// Get number of clips and medipacks from the player object.
nNumClips = MS->player.GetNoAmmoClips();
nNumMedi = MS->player.GetNoMediPacks();
// Set this number in the icon menu.
m_pListOfLists[nListIndex].SetAbsoluteIconCount(ARMS_AMMO_NAME, nNumClips);
m_pListOfLists[nListIndex].SetAbsoluteIconCount(ARMS_HEALTH_NAME, nNumMedi);
// Find the medipacks position.
nInitialSelected = m_pListOfLists[nListIndex].GetIconPosition(ARMS_HEALTH_NAME);
// If we didn't find it, just set the 0 icon to be displayed.
if (nInitialSelected == -1)
nInitialSelected = 0;
} else {
// Just select first icon in the Remora.
nInitialSelected = 0;
// No clips or medipacks in the Remora.
m_pListOfLists[nListIndex].RemoveIcon(ARMS_AMMO_NAME, TRUE8);
m_pListOfLists[nListIndex].RemoveIcon(ARMS_HEALTH_NAME, TRUE8);
}
// We've found the list. If there are no icons in it, add the 'empty' one.
if (m_pListOfLists[nListIndex].GetIconCount() == 0) {
nHash = HashString(ICON_LIST_EMPTY_ICON);
m_pListOfLists[nListIndex].AddIcon(ICON_LIST_EMPTY_ICON, nHash);
}
// Build the information structure for the list.
sDuplicates.s_nNumItems = m_pListOfLists[nListIndex].GetIconCount();
for (i = 0; i < sDuplicates.s_nNumItems; ++i)
sDuplicates.s_pnItemCounts[i] = m_pListOfLists[nListIndex].GetDuplicateCount(i);
// Activate the menu.
g_oIconMenu->Activate(&m_pListOfLists[nListIndex], sDuplicates, bAllowEscape, nInitialSelected);
}
void _icon_list_manager::ResetToScopeLevel(IconListScope eScope) {
uint32 i;
// Go through the lists, removing them if they are out of scope.
for (i = 0; i < ICON_LIST_MANAGER_MAX_LISTS; ++i) {
// Watch out for deleted ones.
if (strcmp(m_pListOfLists[i].GetListName(), ICON_LIST_DELETED_PLACEHOLDER) && (m_pListOfLists[i].GetScope() <= eScope)) {
// This list needs killing.
m_pListOfLists[i].SetListName(ICON_LIST_DELETED_PLACEHOLDER);
}
}
}
void _icon_list_manager::AddIconToList(const char *pcListName, const char *pcIconName, const uint32 nHash) {
uint32 i;
int32 nListIndex;
// See if the list already exists.
nListIndex = FindListByName(pcListName);
// If it doesn't, we need to create a new one, reusing an empty slot if there is one.
if (nListIndex == ICON_LIST_NOT_FOUND) {
// Look for the next available slot.
i = 0;
while ((i < ICON_LIST_MANAGER_MAX_LISTS) && strcmp(m_pListOfLists[i].GetListName(), ICON_LIST_DELETED_PLACEHOLDER) &&
(strlen(m_pListOfLists[i].GetListName()) > 0)) {
++i;
}
// Check if we have run out of list slots.
if (i == ICON_LIST_MANAGER_MAX_LISTS)
Fatal_error("Run out of list slots adding an icon to list %s", pcListName);
// Whichever one of the other two loop conditions failed, we are now pointing at the slot for the new list. Because
// it is a new list, we must set its name.
m_pListOfLists[i].Reset();
m_pListOfLists[i].SetListName(pcListName);
m_pListOfLists[i].AddIcon(pcIconName, nHash);
} else {
// List was found, so just add the icon to it.
m_pListOfLists[nListIndex].AddIcon(pcIconName, nHash);
}
}
uint32 _icon_list_manager::GetList(const char *pcListName, char *pNames[ICON_LIST_MAX_ICONS], uint32 *pnHashes, uint32 *pnCounts) const {
uint32 i;
int32 nListIndex;
uint32 nNumIconsInList;
// See if the list already exists.
nListIndex = FindListByName(pcListName);
// If we failed to find the list, we'll treat this as an error.
if (nListIndex == ICON_LIST_NOT_FOUND)
Fatal_error("List %s not found in _icon_list_manager::GetList()", pcListName);
// Get the number of icons in the list.
nNumIconsInList = m_pListOfLists[nListIndex].GetIconCount();
// If there are none, then there is nothing to do.
if (nNumIconsInList == 0)
return (0);
// Loop for each icon in the list.
for (i = 0; i < nNumIconsInList; ++i) {
pNames[i] = const_cast<char *>(m_pListOfLists[nListIndex].GetIcon(i));
pnHashes[i] = m_pListOfLists[nListIndex].GetIconHash(i);
pnCounts[i] = m_pListOfLists[nListIndex].GetDuplicateCount(i);
}
// And return the count.
return (nNumIconsInList);
}
uint32 _icon_list_manager::GetItemCount(const char *pcListName) const {
int32 nListIndex;
nListIndex = FindListByName(pcListName);
if (nListIndex == ICON_LIST_NOT_FOUND)
Fatal_error("_icon_list_manager::GetItemCount(): list %s not found.", pcListName);
return (m_pListOfLists[nListIndex].GetIconCount());
}
bool8 _icon_list_manager::Carrying(const char *pcListName, const char *pcItem) const {
int32 nListIndex;
nListIndex = FindListByName(pcListName);
if (nListIndex == ICON_LIST_NOT_FOUND)
Fatal_error("_icon_list_manager::Carrying(): list %s not found.", pcListName);
if (m_pListOfLists[nListIndex].GetDuplicateCount(pcItem) > 0)
return (TRUE8);
else
return (FALSE8);
}
uint32 _icon_list_manager::CarryingHowMany(const char *pcListName, const char *pcItem) const {
int32 nListIndex;
nListIndex = FindListByName(pcListName);
if (nListIndex == ICON_LIST_NOT_FOUND)
Fatal_error("_icon_list_manager::CarryingHowMany(): list %s not found.", pcListName);
return (m_pListOfLists[nListIndex].GetDuplicateCount(pcItem));
}
bool8 _icon_list_manager::Holding(const char *pcItem) const {
uint32 nHoldingHash, nHash;
// Get the last selection.
nHoldingHash = g_oIconMenu->GetLastSelectionHash();
// Compute hash of item we're looking for.
nHash = HashString(pcItem);
// It is valid and in range, so check if the name of that list item matches the one we're checking.
if (nHash != nHoldingHash)
return (FALSE8);
else
return (TRUE8);
}
void _icon_list_manager::RemoveIconFromList(const char *pcListName, const char *pcIconName) {
int32 nListIndex;
nListIndex = FindListByName(pcListName);
if (nListIndex == ICON_LIST_NOT_FOUND)
Fatal_error("_icon_list_manager::RemoveIconFromList(): list %s not found.", pcListName);
m_pListOfLists[nListIndex].RemoveIcon(pcIconName, FALSE8);
}
void _icon_list_manager::SetListScope(const char *pcListName, IconListScope eScope) {
int32 nListIndex;
nListIndex = FindListByName(pcListName);
if (nListIndex == ICON_LIST_NOT_FOUND)
Fatal_error("_icon_list_manager::SetScope(): list %s not found.", pcListName);
m_pListOfLists[nListIndex].SetScope(eScope);
}
void _icon_list_manager::DestroyList(const char *pcListName) {
int32 nListIndex;
nListIndex = FindListByName(pcListName);
if (nListIndex == ICON_LIST_NOT_FOUND)
Fatal_error("_icon_list_manager::DestroyList(): list %s not found.", pcListName);
m_pListOfLists[nListIndex].SetListName(ICON_LIST_DELETED_PLACEHOLDER);
}
void _icon_list_manager::ResetList(const char *pcListName) {
int32 nListIndex;
nListIndex = FindListByName(pcListName);
if (nListIndex == ICON_LIST_NOT_FOUND)
return;
m_pListOfLists[nListIndex].Reset();
}
void _icon_list_manager::AddIconToList(const char *pcListName, const char *pcIconName) {
const uint32 nHash = HashString(pcIconName);
AddIconToList(pcListName, pcIconName, nHash);
}
int32 _icon_list_manager::FindListByName(const char *pcListName) const {
uint32 i;
// Look for the list.
i = 0;
while ((i < ICON_LIST_MANAGER_MAX_LISTS) && strcmp(m_pListOfLists[i].GetListName(), pcListName))
++i;
// See which loop condition failed.
if (i < ICON_LIST_MANAGER_MAX_LISTS)
return (i);
else
return (ICON_LIST_NOT_FOUND);
}
} // End of namespace ICB