scummvm/engines/hpl1/penumbra-overture/Inventory.cpp
2023-03-29 21:23:19 +02:00

1802 lines
56 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/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of Penumbra Overture.
*/
#include "hpl1/penumbra-overture/Inventory.h"
#include "hpl1/penumbra-overture/EffectHandler.h"
#include "hpl1/penumbra-overture/GameItem.h"
#include "hpl1/penumbra-overture/GameItemType.h"
#include "hpl1/penumbra-overture/GameMessageHandler.h"
#include "hpl1/penumbra-overture/Init.h"
#include "hpl1/penumbra-overture/Notebook.h"
#include "hpl1/penumbra-overture/Player.h"
#include "hpl1/penumbra-overture/RadioHandler.h"
#include "hpl1/penumbra-overture/SaveHandler.h"
#include "hpl1/algorithms.h"
#include "hpl1/penumbra-overture/GlobalInit.h"
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cInventory::cInventory(cInit *apInit) : iUpdateable("Inventory") {
mpInit = apInit;
mpDrawer = apInit->mpGame->GetGraphics()->GetDrawer();
mpGfxBackground = mpDrawer->CreateGfxObject("inventory_background.bmp", "diffalpha2d");
// mpBatteryMeter = mpDrawer->CreateGfxObject("inventory_battery_meter.bmp","diffalpha2d");
// mpBatteryMeterBar = mpDrawer->CreateGfxObject("inventory_battery_meter_bar.bmp","diffalpha2d");
// mpBagpack = mpDrawer->CreateGfxObject("inventory_backpack.bmp","diffalpha2d");
// mpHealthFrame = mpDrawer->CreateGfxObject("inventory_health_frame.bmp","diffalpha2d");
// mpHealthBack = mpDrawer->CreateGfxObject("inventory_health_background.bmp","diffalpha2d");
// mpHealthMan_Fine = mpDrawer->CreateGfxObject("inventory_health_fine.bmp","diffalpha2d");
// mpHealthMan_Caution = mpDrawer->CreateGfxObject("inventory_health_caution.bmp","diffalpha2d");
// mpHealthMan_Danger = mpDrawer->CreateGfxObject("inventory_health_danger.bmp","diffalpha2d");
// mpHealthTextFrame = mpDrawer->CreateGfxObject("inventory_health_text_slot.bmp","diffalpha2d");
mpFont = mpInit->mpGame->GetResources()->GetFontManager()->CreateFontData("verdana.fnt");
mpContext = hplNew(cInventoryContext, (mpInit));
mbMessageActive = false;
msMessage = _W("");
mfMessageAlpha = 0;
mpMessageBackground = mpDrawer->CreateGfxObject("effect_black.bmp", "diffalpha2d");
///////////////////////////////////
// Init normal slots
cInventorySlot *pSlot = NULL;
int lCount = 0;
cVector2f vSlotBegin(400 - 77 * 2.5f, 15 + 69 + 5);
for (float y = 0; y < 4; ++y)
for (float x = 0; x < 6; ++x) {
pSlot = hplNew(cInventorySlot, (mpInit, vSlotBegin + cVector2f(x * 77, y * 69), false, lCount++));
AddWidget(pSlot);
mlstSlots.push_back(pSlot);
}
///////////////////////////////////
// Init equip slots
int lEquipSlot = 0;
// cVector2f vEquipSlotBegin = cVector2f(400 - 77*5,10);
cVector2f vEquipSlotBegin = cVector2f(400 - 77 * 4.5f, 15);
for (float x = 0; x < 9; ++x) {
pSlot = hplNew(cInventorySlot, (mpInit, vEquipSlotBegin + cVector2f(x * 77, 0), true, lCount++));
AddWidget(pSlot);
mlstSlots.push_back(pSlot);
pSlot->SetEquipIndex(lEquipSlot++);
mvEquipSlots.push_back(pSlot);
}
///////////////////////////////////
// Init other widgests
cInventoryBattery *pBattery = hplNew(cInventoryBattery, (mpInit,
cRect2f(400 - 77 * 3.5f, 15 + 69 + 5, 77, 135),
NULL, 30.0f));
AddWidget(pBattery);
cInventoryHealth *pHealth = hplNew(cInventoryHealth, (mpInit,
cRect2f(400 - 77 * 3.5f, 15 + 69 * 3 + 5,
77, 135),
NULL, 30.0f));
AddWidget(pHealth);
///////////////////////////////////
// Init items types
Hpl1::resizeAndFill(mvItemTypes, eGameItemType_LastEnum, nullptr);
mvItemTypes[eGameItemType_Normal] = hplNew(cGameItemType_Normal, (mpInit));
mvItemTypes[eGameItemType_Notebook] = hplNew(cGameItemType_Notebook, (mpInit));
mvItemTypes[eGameItemType_Note] = hplNew(cGameItemType_Note, (mpInit));
mvItemTypes[eGameItemType_Battery] = hplNew(cGameItemType_Battery, (mpInit));
mvItemTypes[eGameItemType_Flashlight] = hplNew(cGameItemType_Flashlight, (mpInit));
mvItemTypes[eGameItemType_GlowStick] = hplNew(cGameItemType_GlowStick, (mpInit));
mvItemTypes[eGameItemType_Flare] = hplNew(cGameItemType_Flare, (mpInit));
mvItemTypes[eGameItemType_Painkillers] = hplNew(cGameItemType_Painkillers, (mpInit));
mvItemTypes[eGameItemType_WeaponMelee] = hplNew(cGameItemType_WeaponMelee, (mpInit));
mvItemTypes[eGameItemType_Throw] = hplNew(cGameItemType_Throw, (mpInit));
Reset();
}
cInventory::~cInventory(void) {
hplDelete(mpContext);
ClearCallbacks();
for (size_t i = 0; i < mvItemTypes.size(); ++i) {
if (mvItemTypes[i])
hplDelete(mvItemTypes[i]);
}
STLDeleteAll(mlstWidgets);
STLMapDeleteAll(m_mapItems);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC WIDGET METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
iInventoryWidget::iInventoryWidget(cInit *apInit, const cRect2f &aRect, cGfxObject *apGfxObject, float afZ) {
mpInit = apInit;
mRect = aRect;
mpGfxObject = apGfxObject;
mfZ = afZ;
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
}
void iInventoryWidget::Draw() {
if (mpGfxObject == NULL)
return;
cVector2l vSize = mpGfxObject->GetMaterial()->GetImage(eMaterialTexture_Diffuse)->GetSize();
mpDrawer->DrawGfxObject(mpGfxObject, cVector3f(mRect.x, mRect.y, mfZ),
cVector2f((float)vSize.x, (float)vSize.y),
cColor(1, mpInit->mpInventory->GetAlpha()));
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// INVENTORY SLOT METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cInventorySlot::cInventorySlot(cInit *apInit, const cVector2f &avPos, bool abEquip, int alIndex)
: iInventoryWidget(apInit, cRect2f(avPos.x, avPos.y, 77, 66), NULL, 10.0f) {
mpGfxObject = mpDrawer->CreateGfxObject("inventory_slot.bmp", "diffalpha2d");
mpItem = NULL;
mbEquip = abEquip;
mlIndex = alIndex;
mpGfxBack = NULL;
mpFont = mpInit->mpGame->GetResources()->GetFontManager()->CreateFontData("verdana.fnt");
}
//-----------------------------------------------------------------------
void cInventorySlot::OnDraw() {
if (mpItem) {
cVector3f vPos(mRect.x + 4, mRect.y + 4, 5);
cVector2l vSize = mpItem->GetGfxObject()->GetMaterial()->GetImage(eMaterialTexture_Diffuse)->GetSize();
mpDrawer->DrawGfxObject(mpItem->GetGfxObject(), vPos,
cVector2f((float)vSize.x, (float)vSize.y),
cColor(1, mpInit->mpInventory->GetAlpha()));
cGameItemType *pType = mpInit->mpInventory->GetItemType(mpItem->GetItemType());
if (pType && pType->GetString(mpItem) != _W("")) {
tWString sString = pType->GetString(mpItem);
mpFont->draw(vPos + cVector3f(0, 0, 1), 12, cColor(1, mpInit->mpInventory->GetAlpha()), eFontAlign_Left,
sString);
} else if (mpItem->HasCount()) {
mpFont->draw(vPos + cVector3f(0, 0, 1), 12, cColor(1, mpInit->mpInventory->GetAlpha()), eFontAlign_Left,
Common::U32String::format("%d", mpItem->GetCount()));
}
}
// Equip slot specifics
if (mbEquip) {
if (mpGfxBack == NULL) {
mpGfxBack = mpDrawer->CreateGfxObject("inventory_slot_equip" + cString::ToString(mlEquipIndex + 1) + ".bmp", "diffalpha2d");
}
mpDrawer->DrawGfxObject(mpGfxBack, cVector3f(mRect.x, mRect.y, 1), cVector2f(77, 66),
cColor(1, mpInit->mpInventory->GetAlpha() * 0.23f));
/*cVector3f vPos(mRect.x + 2,mRect.y + 3 ,11);
tString sString = cString::ToString(mlEquipIndex+1);
cColor Col(1,1,1,mpInit->mpInventory->GetAlpha());
//mpFont->Draw(vPos,13,Col,eFontAlign_Center,sString.c_str());
//Col = cColor(0,0,0,mpInit->mpInventory->GetAlpha());
mpFont->Draw(vPos+cVector3f(1,1,-1),13,Col,eFontAlign_Center,sString.c_str());
mpFont->Draw(vPos+cVector3f(-1,-1,-1),13,Col,eFontAlign_Center,sString.c_str());*/
}
}
//-----------------------------------------------------------------------
void cInventorySlot::OnMouseOver() {
/////////////////////////////
// Moving item
if (mpInit->mpInventory->GetCurrentItem()) {
cInventoryItem *pCurrentItem = mpInit->mpInventory->GetCurrentItem();
if (mpInit->mpInventory->GetCurrentSlot() == this) {
cGameItemType *pType = mpInit->mpInventory->GetItemType(pCurrentItem->GetItemType());
tString sShortcutAction = pType->GetShortCutAction(pCurrentItem);
if (sShortcutAction != "") {
tWString wsName = pCurrentItem->GetGameName();
iAction *pAction = mpInit->mpGame->GetInput()->GetAction(sShortcutAction);
if (pAction)
wsName = wsName + _W(" (") + cString::To16Char(pAction->GetInputName()) + _W(")");
mpInit->mpInventory->SetItemName(wsName);
} else {
mpInit->mpInventory->SetItemName(pCurrentItem->GetGameName());
}
mpInit->mpInventory->SetItemDesc(pCurrentItem->GetDescription());
} else if (mpItem) {
mpInit->mpInventory->SetItemDesc(_W(""));
tWString sDesc = kTranslate("Inventory", "Combine") + _W(" ") + pCurrentItem->GetGameName() + _W(" ") +
kTranslate("Inventory", "with") + _W(" ") + mpItem->GetGameName();
mpInit->mpInventory->SetItemName(sDesc);
}
}
/////////////////////////////
// Not moving item
else {
if (mpItem) {
cGameItemType *pType = mpInit->mpInventory->GetItemType(mpItem->GetItemType());
tString sShortcutAction = pType->GetShortCutAction(mpItem);
if (sShortcutAction != "") {
tWString wsName = mpItem->GetGameName();
iAction *pAction = mpInit->mpGame->GetInput()->GetAction(sShortcutAction);
if (pAction)
wsName = wsName + _W(" (") + cString::To16Char(pAction->GetInputName()) + _W(")");
mpInit->mpInventory->SetItemName(wsName);
} else {
mpInit->mpInventory->SetItemName(mpItem->GetGameName());
}
mpInit->mpInventory->SetItemDesc(mpItem->GetDescription());
}
}
}
//-----------------------------------------------------------------------
void cInventorySlot::OnMouseDown(eMButton aButton) {
/////////////////////////////////
// Left button
if (aButton == eMButton_Left) {
if (mpItem != NULL) {
mpInit->mpInventory->SetCurrentItem(mpItem);
mpInit->mpInventory->SetCurrentSlot(this);
mpItem = NULL;
cVector2f vOffset = cVector2f(mRect.x + 4, mRect.y + 4) -
mpInit->mpInventory->GetMousePos();
mpInit->mpInventory->SetCurrentItemOffset(vOffset);
}
}
/////////////////////////////////
// Right button
else if (aButton == eMButton_Right) {
if (mpItem) {
mpInit->mpInventory->GetContext()->SetActive(true);
mpInit->mpInventory->GetContext()->Setup(mpItem, mpInit->mpInventory->GetMousePos());
}
}
}
//-----------------------------------------------------------------------
void cInventorySlot::OnMouseUp(eMButton aButton) {
/////////////////////////////////
// Left mouse
if (aButton == eMButton_Left) {
if (mpInit->mpInventory->GetCurrentItem()) {
if (mpItem == NULL) {
mpItem = mpInit->mpInventory->GetCurrentItem();
} else {
tString sCurrentItemName = mpInit->mpInventory->GetCurrentItem()->GetName();
if (mpInit->mpInventory->CheckCombineCallback(mpItem->GetName(), sCurrentItemName, mlIndex)) {
// mpInit->mpInventory->RemoveItem(mpInit->mpInventory->GetCurrentItem());
if (mpInit->mpInventory->GetItem(sCurrentItemName))
mpInit->mpInventory->GetCurrentSlot()->SetItem(mpInit->mpInventory->GetCurrentItem());
} else {
mpInit->mpInventory->GetCurrentSlot()->SetItem(mpInit->mpInventory->GetCurrentItem());
}
}
mpInit->mpInventory->SetCurrentItem(NULL);
mpInit->mpInventory->SetCurrentSlot(NULL);
mpInit->mpInventory->SetDroppedInSlot(true);
}
}
}
//-----------------------------------------------------------------------
void cInventorySlot::OnDoubleClick(eMButton aButton) {
/////////////////////////////////
// Left mouse
if (aButton == eMButton_Left) {
// The player might be holding the item when double clicking.
cInventoryItem *pItem = mpItem;
if (pItem == NULL && mpInit->mpInventory->GetCurrentSlot() == this) {
pItem = mpInit->mpInventory->GetCurrentItem();
if (pItem) {
mpInit->mpInventory->GetCurrentSlot()->SetItem(mpInit->mpInventory->GetCurrentItem());
mpInit->mpInventory->SetCurrentItem(NULL);
mpInit->mpInventory->SetCurrentSlot(NULL);
}
}
if (pItem) {
cGameItemType *pItemType = mpInit->mpInventory->GetItemType(pItem->GetItemType());
if (pItemType == NULL) {
Warning("Itemtype %d does not exist\n", pItem->GetItemType());
return;
}
// Check there is a callback for the item with object = ""
if (mpInit->mpInventory->CheckUseCallback(pItem->GetName(), "")) {
mpInit->mpInventory->SetActive(false);
}
// Use the action of the item
else if (pItemType->OnAction(pItem, 0) == false) {
mpInit->mpInventory->SetActive(false);
}
}
}
}
//-----------------------------------------------------------------------
void cInventorySlot::OnShortcutDown(int alNum) {
if (mpItem) {
cInventorySlot *pSlot = mpInit->mpInventory->GetEquipSlot(alNum);
if (pSlot == this)
return;
cInventoryItem *pThisItem = mpItem;
if (pSlot->mpItem)
SetItem(pSlot->mpItem);
else
SetItem(NULL);
pSlot->SetItem(pThisItem);
}
}
//-----------------------------------------------------------------------
void cInventorySlot::OnUpdate(float afTimeStep) {
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC ITEM METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cInventoryItem::cInventoryItem(cInit *apInit) {
mpInit = apInit;
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
mpGfxObject = NULL;
mpGfxObjectAdditive = NULL;
}
cInventoryItem::~cInventoryItem() {
if (mpGfxObject)
mpDrawer->DestroyGfxObject(mpGfxObject);
if (mpGfxObjectAdditive)
mpDrawer->DestroyGfxObject(mpGfxObjectAdditive);
}
//-----------------------------------------------------------------------
bool cInventoryItem::Init(cGameItem *apGameItem) {
// Init all stuff
msName = apGameItem->GetName();
if (apGameItem->GetImageFile() != "") {
mpGfxObject = mpDrawer->CreateGfxObject(apGameItem->GetImageFile(), "diffalpha2d");
mpGfxObjectAdditive = mpDrawer->CreateGfxObject(apGameItem->GetImageFile(), "diffadditive2d");
} else
mpGfxObject = NULL;
msDescription = apGameItem->GetDescription();
msGameName = apGameItem->GetGameName();
mItemType = apGameItem->GetItemType();
msSubType = apGameItem->GetSubType();
msHudModelFile = apGameItem->GetHudModelFile();
msHudModelName = apGameItem->GetHudModelName();
mbCanBeDropped = apGameItem->CanBeDropped();
mbHasCount = apGameItem->HasCount();
mlCount = apGameItem->GetCount();
msEntityFile = apGameItem->GetMeshEntity()->GetSourceFile();
return true;
}
//-----------------------------------------------------------------------
bool cInventoryItem::InitFromFile(const tString &asFile) {
tString sEntityFile = cString::SetFileExt(asFile, "ent");
tString sPath = mpInit->mpGame->GetResources()->GetFileSearcher()->GetFilePath(sEntityFile);
if (sPath != "") {
TiXmlDocument *pEntityDoc = hplNew(TiXmlDocument, ());
if (pEntityDoc->LoadFile(sPath.c_str()) == false) {
Error("Couldn't load '%s'!\n", sPath.c_str());
return false;
} else {
TiXmlElement *pRootElem = pEntityDoc->FirstChildElement();
TiXmlElement *pMainElem = pRootElem->FirstChildElement("MAIN");
TiXmlElement *pGameElem = pRootElem->FirstChildElement("GAME");
msSubType = cString::ToString(pMainElem->Attribute("Subtype"), "");
tString sImageFile = cString::ToString(pGameElem->Attribute("ImageFile"), "");
mbCanBeDropped = cString::ToBool(pGameElem->Attribute("CanBeDropped"), true);
mbHasCount = cString::ToBool(pGameElem->Attribute("HasCount"), false);
mlCount = cString::ToInt(pGameElem->Attribute("Count"), 1);
msHudModelFile = cString::ToString(pGameElem->Attribute("HudModelFile"), "");
msHudModelName = cString::ToString(pGameElem->Attribute("HudModelName"), "");
tString sNameCat = cString::ToString(pGameElem->Attribute("NameCat"), "");
tString sNameEntry = cString::ToString(pGameElem->Attribute("NameEntry"), "");
tString sDescCat = cString::ToString(pGameElem->Attribute("DescCat"), "");
tString sDescEntry = cString::ToString(pGameElem->Attribute("DescEntry"), "");
msGameName = kTranslate(sNameCat, sNameEntry);
msDescription = kTranslate(sDescCat, sDescEntry);
mItemType = cEntityLoader_GameItem::ToItemType(pGameElem->Attribute("ItemType"));
if (sImageFile != "") {
mpGfxObject = mpDrawer->CreateGfxObject(sImageFile, "diffalpha2d");
mpGfxObjectAdditive = mpDrawer->CreateGfxObject(sImageFile, "diffadditive2d");
} else
mpGfxObject = NULL;
msEntityFile = sEntityFile;
}
hplDelete(pEntityDoc);
} else {
Error("Entity file '%s' was not found!\n", asFile.c_str());
return false;
}
return true;
}
//-----------------------------------------------------------------------
void cInventoryItem::Drop() {
cWorld3D *pWorld = mpInit->mpGame->GetScene()->GetWorld3D();
cCamera3D *pCamera = mpInit->mpPlayer->GetCamera();
cMatrixf mtxItem = cMatrixf::Identity;
mtxItem.SetTranslation(pCamera->GetPosition());
iEntity3D *pEntity = pWorld->CreateEntity(msName, mtxItem, msEntityFile, true);
if (pEntity) {
cMeshEntity *pMesh = static_cast<cMeshEntity *>(pEntity);
if (pMesh->GetBody()) {
pMesh->GetBody()->AddImpulse(pCamera->GetForward() * 3.2f);
}
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// INVENTORY BATTERY
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cInventoryBattery::cInventoryBattery(cInit *apInit, const cRect2f &aRect, cGfxObject *apGfxObject,
float afZ)
: iInventoryWidget(apInit, aRect, apGfxObject, afZ) {
mpGfxObject = mpDrawer->CreateGfxObject("inventory_slot_double.bmp", "diffalpha2d");
mpGfxBatteryMeter = mpDrawer->CreateGfxObject("inventory_battery_meter.bmp", "diffalpha2d");
mpGfxBatteryMeterBar = mpDrawer->CreateGfxObject("inventory_battery_meter_bar.bmp", "diffalpha2d");
}
cInventoryBattery::~cInventoryBattery() {
mpDrawer->DestroyGfxObject(mpGfxBatteryMeter);
mpDrawer->DestroyGfxObject(mpGfxBatteryMeterBar);
}
void cInventoryBattery::OnDraw() {
cVector3f vPos = cVector3f(mRect.x, mRect.y, mfZ + 1);
cVector2f vSize(mRect.w, mRect.h);
float fAlpha = mpInit->mpInventory->GetAlpha();
float fPercent = mpInit->mpPlayer->GetPower() / 100.0f;
mpDrawer->DrawGfxObject(mpGfxBatteryMeter, vPos, vSize, cColor(1, fAlpha));
mpDrawer->DrawGfxObject(mpGfxBatteryMeterBar, cVector3f(vPos.x + 26, vPos.y + 16, 4),
cVector2f(21, 102),
cColor(0, 0, 0, fAlpha));
mpDrawer->DrawGfxObject(mpGfxBatteryMeterBar,
cVector3f(vPos.x + 26, vPos.y + 16 + (102 * (1 - fPercent)), 5),
cVector2f(21, 102 * fPercent),
cColor(1.0f - fPercent, fPercent, 0, fAlpha));
// mpFont->Draw(cVector3f(vBatteryPos.x+50, vBatteryPos.y+6,10),20,cColor(0.91f,1,0.91f,mfAlpha),eFontAlign_Left,
//_W("%.0f%%"),mpInit->mpPlayer->GetPower());
}
void cInventoryBattery::OnMouseOver() {
char sPercent[256];
snprintf(sPercent, 256, " %.0f%% ", mpInit->mpPlayer->GetPower());
mpInit->mpInventory->SetItemName(kTranslate("Inventory", "BatteryLevel"));
mpInit->mpInventory->SetItemDesc(kTranslate("Inventory", "BatteryLevelDesc1") +
cString::To16Char(sPercent) +
kTranslate("Inventory", "BatteryLevelDesc2"));
}
void cInventoryBattery::OnUpdate(float afTimeStep) {
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// INVENTORY HEALTH
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cInventoryHealth::cInventoryHealth(cInit *apInit, const cRect2f &aRect, cGfxObject *apGfxObject,
float afZ)
: iInventoryWidget(apInit, aRect, apGfxObject, afZ) {
mpGfxObject = mpDrawer->CreateGfxObject("inventory_slot_double.bmp", "diffalpha2d");
mpGfxFine = mpDrawer->CreateGfxObject("inventory_health_fine.bmp", "diffalpha2d");
mpGfxCaution = mpDrawer->CreateGfxObject("inventory_health_caution.bmp", "diffalpha2d");
mpGfxDanger = mpDrawer->CreateGfxObject("inventory_health_danger.bmp", "diffalpha2d");
}
cInventoryHealth::~cInventoryHealth() {
mpDrawer->DestroyGfxObject(mpGfxFine);
mpDrawer->DestroyGfxObject(mpGfxCaution);
mpDrawer->DestroyGfxObject(mpGfxDanger);
}
void cInventoryHealth::OnDraw() {
cVector3f vPos = cVector3f(mRect.x, mRect.y, mfZ + 1);
cVector2f vSize(mRect.w, mRect.h);
float fAlpha = mpInit->mpInventory->GetAlpha();
float fPercent = mpInit->mpPlayer->GetHealth() / 100.0f;
cGfxObject *pGfxMan;
if (fPercent > 0.75f) {
pGfxMan = mpGfxFine;
} else if (fPercent > 0.3f) {
pGfxMan = mpGfxCaution;
} else {
pGfxMan = mpGfxDanger;
}
mpDrawer->DrawGfxObject(pGfxMan, cVector3f(vPos.x + 6, vPos.y + 6, 2), cVector2f(mRect.w - 12, mRect.h - 12),
cColor(1.0f - fPercent, fPercent, 0, fAlpha));
}
void cInventoryHealth::OnMouseOver() {
float fPercent = mpInit->mpPlayer->GetHealth() / 100.0f;
tWString wsText;
if (fPercent > 0.75f) {
wsText = kTranslate("Inventory", "HealthFine");
} else if (fPercent > 0.3f) {
wsText = kTranslate("Inventory", "HealthCaution");
} else {
wsText = kTranslate("Inventory", "HealthDanger");
}
mpInit->mpInventory->SetItemName(kTranslate("Inventory", "Health"));
mpInit->mpInventory->SetItemDesc(wsText);
}
void cInventoryHealth::OnUpdate(float afTimeStep) {
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// INVENTORY CONTEXT METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cInventoryContext::cInventoryContext(cInit *apInit) {
mpInit = apInit;
mpDrawer = mpInit->mpGame->GetGraphics()->GetDrawer();
mbActive = false;
mpGfxBack = mpDrawer->CreateGfxObject("inventory_context_back.bmp", "diffalpha2d");
mpGfxCorner11 = mpDrawer->CreateGfxObject("inventory_context_11.bmp", "diffalpha2d");
mpGfxCorner12 = mpDrawer->CreateGfxObject("inventory_context_12.bmp", "diffalpha2d");
mpGfxCorner21 = mpDrawer->CreateGfxObject("inventory_context_21.bmp", "diffalpha2d");
mpGfxCorner22 = mpDrawer->CreateGfxObject("inventory_context_22.bmp", "diffalpha2d");
mpGfxRight = mpDrawer->CreateGfxObject("inventory_context_right.bmp", "diffalpha2d");
mpGfxLeft = mpDrawer->CreateGfxObject("inventory_context_left.bmp", "diffalpha2d");
mpGfxTop = mpDrawer->CreateGfxObject("inventory_context_top.bmp", "diffalpha2d");
mpGfxBottom = mpDrawer->CreateGfxObject("inventory_context_bottom.bmp", "diffalpha2d");
mvPos.z = 40.0f;
mpFont = mpInit->mpGame->GetResources()->GetFontManager()->CreateFontData("verdana.fnt");
mfRowStart = 0;
mfRowSize = 15;
mfColLength = 100;
mlSelectedRow = -1;
mfAlpha = 0.0f;
mpActionVec = NULL;
}
//-----------------------------------------------------------------------
cInventoryContext::~cInventoryContext() {
}
//-----------------------------------------------------------------------
void cInventoryContext::SetActive(bool abX) {
mbActive = abX;
if (mbActive) {
} else {
}
}
//-----------------------------------------------------------------------
void cInventoryContext::Draw() {
if (mfAlpha <= 0.0f || mpActionVec == NULL)
return;
float fTotalAlpha = mfAlpha * mpInit->mpInventory->GetAlpha();
mpDrawer->DrawGfxObject(mpGfxBack, mvPos, mvSize, cColor(1, fTotalAlpha));
// Corners
cVector2f vCornerSize(3, 3);
mpDrawer->DrawGfxObject(mpGfxCorner11, mvPos - vCornerSize, vCornerSize, cColor(1, fTotalAlpha));
mpDrawer->DrawGfxObject(mpGfxCorner21, mvPos + cVector3f(mfColLength, -vCornerSize.y, 0),
vCornerSize, cColor(1, fTotalAlpha));
mpDrawer->DrawGfxObject(mpGfxCorner12, mvPos + cVector3f(-vCornerSize.x, mvSize.y, 0),
vCornerSize, cColor(1, fTotalAlpha));
mpDrawer->DrawGfxObject(mpGfxCorner22, mvPos + cVector3f(mvSize.x, mvSize.y, 0),
vCornerSize, cColor(1, fTotalAlpha));
// Sides
mpDrawer->DrawGfxObject(mpGfxLeft, mvPos + cVector3f(-vCornerSize.x, 0, 0),
cVector2f(vCornerSize.x, mvSize.y), cColor(1, fTotalAlpha));
mpDrawer->DrawGfxObject(mpGfxRight, mvPos + cVector3f(mvSize.x, 0, 0),
cVector2f(vCornerSize.x, mvSize.y), cColor(1, fTotalAlpha));
mpDrawer->DrawGfxObject(mpGfxTop, mvPos + cVector3f(0, -vCornerSize.y, 0),
cVector2f(mvSize.x, vCornerSize.y), cColor(1, fTotalAlpha));
mpDrawer->DrawGfxObject(mpGfxTop, mvPos + cVector3f(0, mvSize.y, 0),
cVector2f(mvSize.x, vCornerSize.y), cColor(1, fTotalAlpha));
for (int i = 0; i < (int)mpActionVec->size(); i++) {
/*cColor Col = */ mlSelectedRow == i ? cColor(0.2f, 1.0f, 0.2f, mfAlpha) : cColor(0.65f, 0.65f, 0.65f, fTotalAlpha);
// mpFont->Draw(mvPos + cVector3f(2.0f,(float)i*mfRowSize,1),14,Col,
// eFontAlign_Left,(*mpActionVec)[i].c_str());
}
}
//-----------------------------------------------------------------------
void cInventoryContext::Update(float afTimeStep) {
////////////////////////////////
// Change alpha
if (mbActive == false) {
mfAlpha -= 2.5f * afTimeStep;
if (mfAlpha < 0)
mfAlpha = 0;
return;
} else {
mfAlpha += 2.3f * afTimeStep;
if (mfAlpha > 1)
mfAlpha = 1;
}
mpInit->mpInventory->SetItemDesc(mpItem->GetDescription());
mpInit->mpInventory->SetItemName(mpItem->GetGameName());
///////////////////////////////////////
// Check if the mouse is over any row
cVector2f vMousePos = mpInit->mpInventory->GetMousePos();
mlSelectedRow = -1;
for (int i = 0; i < (int)mpActionVec->size(); i++) {
cRect2f Rect(mvPos.x, mvPos.y + mfRowStart + (float)i * mfRowSize,
mfColLength, mfRowSize);
if (cMath::PointBoxCollision(vMousePos, Rect)) {
mlSelectedRow = i;
break;
}
}
}
//-----------------------------------------------------------------------
void cInventoryContext::OnMouseDown(eMButton aButton) {
/////////////////////////////////
// Left button
if (aButton == eMButton_Left) {
if (mlSelectedRow != -1) {
cGameItemType *pItemType = mpInit->mpInventory->GetItemType(mpItem->GetItemType());
if (pItemType->OnAction(mpItem, mlSelectedRow) == false) {
mpInit->mpInventory->SetActive(false);
}
}
mbActive = false;
}
/////////////////////////////////
// Right button
else if (aButton == eMButton_Right) {
mbActive = false;
}
}
//-----------------------------------------------------------------------
void cInventoryContext::OnMouseUp(eMButton aButton) {
}
//-----------------------------------------------------------------------
void cInventoryContext::Setup(cInventoryItem *apItem, const cVector2f &avPos) {
mpItem = apItem;
mvPos = avPos;
cGameItemType *pItemType = mpInit->mpInventory->GetItemType(apItem->GetItemType());
mpActionVec = pItemType->GetActions(apItem->CanBeDropped());
mvSize = cVector2f(mfColLength, (float)mpActionVec->size() * mfRowSize + 8);
mRect = cRect2f(mvPos.x, mvPos.y, mvSize.x, mvSize.y);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cInventory::OnStart() {
}
//-----------------------------------------------------------------------
void cInventory::Update(float afTimeStep) {
////////////////////////////////
// Change alpha
if (mbActive == false) {
mfAlpha -= 2.5f * afTimeStep;
if (mfAlpha < 0)
mfAlpha = 0;
mfMessageAlpha -= 3.1f * afTimeStep;
if (mfMessageAlpha < 0)
mfMessageAlpha = 0;
return;
} else {
mfAlpha += 2.3f * afTimeStep;
if (mfAlpha > 1)
mfAlpha = 1;
}
///////////////////////////////
// Iterate widgets
if (mpContext->IsActive() == false) {
mbDrawText = false;
tInventoryWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iInventoryWidget *pWidget = *it;
pWidget->OnUpdate(afTimeStep);
if (cMath::PointBoxCollision(mvMousePos, pWidget->GetRect())) {
pWidget->OnMouseOver();
}
}
}
/////////////////////
// Context Menu
mpContext->Update(afTimeStep);
/////////////////////
// Inventory message
if (mbMessageActive) {
mfMessageAlpha += 2.7f * afTimeStep;
if (mfMessageAlpha > 1)
mfMessageAlpha = 1;
} else {
mfMessageAlpha -= 3.1f * afTimeStep;
if (mfMessageAlpha < 0)
mfMessageAlpha = 0;
}
/////////////////////
// Text alpha
if (mbDrawText) {
mfTextAlpha += 2.8f * afTimeStep;
if (mfTextAlpha > 1.0f)
mfTextAlpha = 1.0f;
} else {
mfTextAlpha -= 3.1f * afTimeStep;
if (mfTextAlpha < 0.0f)
mfTextAlpha = 0.0f;
}
}
//-----------------------------------------------------------------------
void cInventory::Reset() {
// reset variables
mLastCrossHairState = eCrossHairState_Active;
mbActive = false;
mfAlpha = 0.0f;
mfTextAlpha = 0.0f;
msItemName = _W("");
msItemDesc = _W("");
mpCurrentItem = NULL;
mpCurrentSlot = NULL;
mbCheckingCombineItems = false;
mbMessageActive = false;
mbNoteBookIsActive = false;
// Remove all callbacks
ClearCallbacks();
// Clear all the slots
// Normal
tInventorySlotListIt it = mlstSlots.begin();
for (; it != mlstSlots.end(); ++it) {
cInventorySlot *pSlot = *it;
pSlot->SetItem(NULL);
}
// Equip
for (size_t i = 0; i < mvEquipSlots.size(); ++i) {
mvEquipSlots[i]->SetItem(NULL);
}
STLMapDeleteAll(m_mapItems);
}
//-----------------------------------------------------------------------
void cInventory::OnDraw() {
if (mfAlpha <= 0.0f)
return;
///////////////////////////////
// Draw background
mpDrawer->DrawGfxObject(mpGfxBackground, cVector3f(0, 0, 0), cVector2f(800, 600), cColor(1, mfAlpha));
// Draw backpack and hands
// mpDrawer->DrawGfxObject(mpBagpack,cVector3f(0,600 - (160*sqrt(mfAlpha)),-1),cVector2f(800,160),cColor(1,mfAlpha));
///////////////////////////////
// Draw power remaining:
///////////////////////////////
// Draw health
/*fPercent = mpInit->mpPlayer->GetHealth()/100.0f;
cVector2f vManPos(640,120);
mpDrawer->DrawGfxObject(mpHealthFrame,cVector3f(vManPos.x,vManPos.y,2),cVector2f(150,266),cColor(1,mfAlpha));
mpDrawer->DrawGfxObject(mpHealthBack,cVector3f(vManPos.x,vManPos.y,2),cVector2f(150,266),
cColor((1-fPercent)*0.7f + 0.3f,fPercent*0.7f + 0.3f, 0.3f, mfAlpha));
cGfxObject *pGfxMan;
tWString wsText;
if(fPercent > 0.75f){ pGfxMan = mpHealthMan_Fine;
wsText = kTranslate("Inventory","HealthFine");
}
else if(fPercent > 0.3f){ pGfxMan = mpHealthMan_Caution;
wsText = kTranslate("Inventory","HealthCaution");
}
else{ pGfxMan = mpHealthMan_Danger;
wsText = kTranslate("Inventory","HealthDanger");
}
mpDrawer->DrawGfxObject(pGfxMan,cVector3f(vManPos.x,vManPos.y,2),cVector2f(150,266),cColor(1,mfAlpha));
mpDrawer->DrawGfxObject(mpHealthTextFrame,cVector3f(vManPos.x,vManPos.y+266+10,2),cVector2f(150,66),cColor(1,mfAlpha));
mpFont->Draw(cVector3f(vManPos.x+75,vManPos.y+266+10+4,10),20,cColor(0.91f,1,0.91f,mfAlpha),eFontAlign_Center,
wsText.c_str());*/
///////////////////////////////
// Draw Widgets
tInventoryWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iInventoryWidget *pWidget = *it;
pWidget->Draw();
pWidget->OnDraw();
}
//////////////////////////////
// Draw Selected item
if (mpCurrentItem) {
cVector3f vPos(mvMousePos.x + mvCurrentItemOffset.x,
mvMousePos.y + mvCurrentItemOffset.y, 15);
cVector2l vSize = mpCurrentItem->GetGfxObject()->GetMaterial()->GetImage(eMaterialTexture_Diffuse)->GetSize();
mpDrawer->DrawGfxObject(mpCurrentItem->GetGfxObject(), vPos,
cVector2f((float)vSize.x, (float)vSize.y),
cColor(1, mpInit->mpInventory->GetAlpha()));
}
//////////////////////////
// Draw context
mpContext->Draw();
//////////////////////////
// Draw message
if (mfMessageAlpha > 0) {
float fMessAlpha = mfAlpha * mfMessageAlpha;
cVector3f vMessPos = cVector3f(40, 275, 110);
mpDrawer->DrawGfxObject(mpMessageBackground, cVector3f(0, vMessPos.y - 8, vMessPos.z - 2),
cVector2f(800, 17 * 4 + 8 * 2), cColor(1, 1, 1, fMessAlpha * 0.92f));
mpFont->drawWordWrap(vMessPos + cVector3f(0, 0, 0), 720, 16, 17, cColor(1, 1, 1, fMessAlpha), eFontAlign_Left,
msMessage);
mpFont->drawWordWrap(vMessPos + cVector3f(0, 1, -1), 720, 16, 17, cColor(0, 0, 0, fMessAlpha), eFontAlign_Left,
msMessage);
}
//////////////////////////
// Draw text
if (mpInit->mpRadioHandler->IsActive() == false || mpInit->mbSubtitles == false) {
float fTextAlpha = mfAlpha * mfTextAlpha * (1 - mfMessageAlpha);
mpFont->draw(cVector3f(400, 460, 10), 19, cColor(1, 1, 1, fTextAlpha), eFontAlign_Center,
msItemName);
mpFont->draw(cVector3f(400 + 1, 460 + 1, 9), 19, cColor(0, 0, 0, fTextAlpha), eFontAlign_Center,
msItemName);
mpFont->drawWordWrap(cVector3f(80, 480, 10), 640, 16, 17, cColor(1, 1, 1, fTextAlpha), eFontAlign_Left,
msItemDesc);
mpFont->drawWordWrap(cVector3f(80 + 1, 480 + 1, 9), 640, 16, 17, cColor(0, 0, 0, fTextAlpha), eFontAlign_Left,
msItemDesc);
}
}
//-----------------------------------------------------------------------
void cInventory::SetActive(bool abX) {
if (mbActive == abX)
return;
mbActive = abX;
if (mbActive) {
mLastCrossHairState = mpInit->mpPlayer->GetCrossHairState();
mvMousePos = cVector2f(400, 300);
mpInit->mpPlayer->SetCrossHairPos(mvMousePos);
mpInit->mpPlayer->SetCrossHairState(eCrossHairState_Pointer);
} else {
mpInit->mpPlayer->SetCrossHairState(mLastCrossHairState);
mbMessageActive = false;
}
}
//-----------------------------------------------------------------------
bool cInventory::IsActive() {
return mbActive;
}
//-----------------------------------------------------------------------
void cInventory::OnInventoryDown() {
if (mbMessageActive) {
mbMessageActive = false;
mpInit->mpPlayer->SetCrossHairState(eCrossHairState_Pointer);
return;
}
SetActive(false);
mpInit->mpPlayer->SetCrossHairPos(cVector2f(400, 300));
mvMousePos = cVector2f(400, 300);
}
//-----------------------------------------------------------------------
void cInventory::AddWidget(iInventoryWidget *apWidget) {
mlstWidgets.push_back(apWidget);
}
//-----------------------------------------------------------------------
void cInventory::AddItem(cGameItem *apGameItem) {
tWString sMessage = apGameItem->GetGameName(); // kTranslate("Inventory","YouPickedUp") + _W(" ")+apGameItem->GetGameName();
mpInit->mpEffectHandler->GetSubTitle()->Add(sMessage, 2.0f, true);
//////////////////////////
// If the item has a count, check if it exists
if (apGameItem->HasCount()) {
cInventoryItem *pFoundItem = NULL;
tInventoryItemMapIt it = m_mapItems.begin();
for (; it != m_mapItems.end(); ++it) {
cInventoryItem *pItem = it->second;
if (pItem->GetItemType() == apGameItem->GetItemType() &&
pItem->GetSubType() == apGameItem->GetSubType()) {
pFoundItem = pItem;
break;
}
}
if (pFoundItem) {
pFoundItem->AddCount(apGameItem->GetCount());
CheckPickupCallback(apGameItem->GetName());
return;
}
}
//////////////////////////
// Create item
cInventoryItem *pItem = hplNew(cInventoryItem, (mpInit));
pItem->Init(apGameItem);
cGameItemType *pType = GetItemType(pItem->GetItemType());
if (pType->OnPickUp(pItem, true) == false) {
CheckPickupCallback(pItem->GetName());
hplDelete(pItem);
return;
}
m_mapItems.insert(tInventoryItemMap::value_type(pItem->GetName(), pItem));
tInventorySlotListIt it = mlstSlots.begin();
for (; it != mlstSlots.end(); ++it) {
cInventorySlot *pSlot = *it;
if (pSlot->GetItem() == NULL) {
pSlot->SetItem(pItem);
CheckPickupCallback(pItem->GetName());
return;
}
}
// TODO: Show message that there is no room for the item.
}
//-----------------------------------------------------------------------
void cInventory::AddItemFromFile(const tString &asName, const tString &asFile, int alSlotIndex) {
/////////////////////////////////
// Create Item
cInventoryItem *pItem = hplNew(cInventoryItem, (mpInit));
pItem->SetName(asName);
pItem->InitFromFile(asFile);
cGameItemType *pType = GetItemType(pItem->GetItemType());
if (pType->OnPickUp(pItem, false) == false) {
CheckPickupCallback(pItem->GetName());
hplDelete(pItem);
return;
}
//////////////////////////
// If the item has a count, check if it exists
if (pItem->HasCount()) {
cInventoryItem *pFoundItem = NULL;
tInventoryItemMapIt it = m_mapItems.begin();
for (; it != m_mapItems.end(); ++it) {
cInventoryItem *pTempItem = it->second;
if (pTempItem->GetItemType() == pItem->GetItemType() &&
pItem->GetSubType() == pTempItem->GetSubType()) {
pFoundItem = pTempItem;
break;
}
}
if (pFoundItem) {
pFoundItem->AddCount(pItem->GetCount());
CheckPickupCallback(pItem->GetName());
hplDelete(pItem);
return;
}
}
//////////////////////////
// Add to inventory
m_mapItems.insert(tInventoryItemMap::value_type(pItem->GetName(), pItem));
int lCount = 0;
// int lCurrentSlot = -1;
tInventorySlotListIt it = mlstSlots.begin();
for (; it != mlstSlots.end(); ++it) {
cInventorySlot *pSlot = *it;
if ((alSlotIndex < 0 && pSlot->GetItem() == NULL && (mpCurrentItem == NULL || mpCurrentSlot != pSlot)) ||
(alSlotIndex == lCount)) {
pSlot->SetItem(pItem);
CheckPickupCallback(pItem->GetName());
break;
}
lCount++;
}
}
//-----------------------------------------------------------------------
void cInventory::RemoveItem(cInventoryItem *apItem) {
tInventorySlotListIt SlotIt = mlstSlots.begin();
for (; SlotIt != mlstSlots.end(); SlotIt++) {
cInventorySlot *pSlot = *SlotIt;
if (pSlot->GetItem() == apItem) {
pSlot->SetItem(NULL);
}
}
tInventoryItemMapIt it = m_mapItems.begin();
for (; it != m_mapItems.end(); ++it) {
if (it->second == apItem) {
m_mapItems.erase(it);
break;
}
}
if (mpCurrentItem == apItem) {
mpCurrentItem = NULL;
}
hplDelete(apItem);
}
//-----------------------------------------------------------------------
cInventoryItem *cInventory::GetItem(const tString &asName) {
tInventoryItemMapIt it = m_mapItems.find(asName);
if (it != m_mapItems.end()) {
return it->second;
}
return NULL;
}
//-----------------------------------------------------------------------
void cInventory::OnMouseDown(eMButton aButton) {
if (mbMessageActive) {
mbMessageActive = false;
mpInit->mpPlayer->SetCrossHairState(eCrossHairState_Pointer);
return;
}
// To this to remove context temporarly.
if (aButton == eMButton_Right)
return;
/////////////////////////////////
// Context is active
if (mpContext->IsActive()) {
mpContext->OnMouseDown(aButton);
}
/////////////////////////////////
// Normal
else {
tInventoryWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iInventoryWidget *pWidget = *it;
if (cMath::PointBoxCollision(mvMousePos, pWidget->GetRect())) {
pWidget->OnMouseDown(aButton);
}
}
}
}
void cInventory::OnMouseUp(eMButton aButton) {
/////////////////////////////////
// Context is active
if (mpContext->IsActive()) {
mpContext->OnMouseUp(aButton);
}
/////////////////////////////////
// Normal
else {
mbDroppedInSlot = false;
tInventoryWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iInventoryWidget *pWidget = *it;
if (cMath::PointBoxCollision(mvMousePos, pWidget->GetRect())) {
pWidget->OnMouseUp(aButton);
}
}
/////////////////////////////////////////
// Item is dropped outside of slots or returned to its previous slot.
if (mpCurrentItem && mbDroppedInSlot == false && aButton == eMButton_Left) {
if (mpCurrentItem->CanBeDropped() && mpCurrentItem->HasCount() == false) {
mpCurrentItem->Drop();
RemoveItem(mpCurrentItem);
} else {
mpInit->mpInventory->GetCurrentSlot()->SetItem(mpInit->mpInventory->GetCurrentItem());
}
mpCurrentItem = NULL;
mpCurrentSlot = NULL;
}
}
}
//-----------------------------------------------------------------------
void cInventory::OnDoubleClick(eMButton aButton) {
if (mbMessageActive)
return;
if (mpContext->IsActive() == false) {
tInventoryWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iInventoryWidget *pWidget = *it;
if (cMath::PointBoxCollision(mvMousePos, pWidget->GetRect())) {
pWidget->OnDoubleClick(aButton);
}
}
}
}
//-----------------------------------------------------------------------
void cInventory::AddMousePos(const cVector2f &avRel) {
if (mbMessageActive)
return;
mvMousePos += avRel;
if (mvMousePos.x < 0)
mvMousePos.x = 0;
if (mvMousePos.x >= 800)
mvMousePos.x = 800;
if (mvMousePos.y < 0)
mvMousePos.y = 0;
if (mvMousePos.y >= 600)
mvMousePos.y = 600;
mpInit->mpPlayer->SetCrossHairPos(mvMousePos);
}
void cInventory::SetMousePos(const cVector2f &avPos) {
if (mbMessageActive)
return;
mvMousePos = avPos;
mpInit->mpPlayer->SetCrossHairPos(mvMousePos);
}
//-----------------------------------------------------------------------
void cInventory::OnShortcutDown(int alNum) {
if (mbMessageActive)
return;
if (mbActive) {
tInventoryWidgetListIt it = mlstWidgets.begin();
for (; it != mlstWidgets.end(); ++it) {
iInventoryWidget *pWidget = *it;
if (cMath::PointBoxCollision(mvMousePos, pWidget->GetRect())) {
pWidget->OnShortcutDown(alNum);
}
}
} else {
cInventoryItem *pItem = mvEquipSlots[alNum]->GetItem();
if (pItem != NULL) {
// Check there is a callback for the item with object = ""
if (mpInit->mpInventory->CheckUseCallback(pItem->GetName(), "")) {
return;
}
cGameItemType *pType = mpInit->mpInventory->GetItemType(mvEquipSlots[alNum]->GetItem()->GetItemType());
pType->OnAction(mvEquipSlots[alNum]->GetItem(), 0);
}
}
}
//-----------------------------------------------------------------------
void cInventory::SetMessage(const tWString &asMessage) {
mbMessageActive = true;
msMessage = asMessage;
mpInit->mpPlayer->SetCrossHairState(eCrossHairState_None);
}
//-----------------------------------------------------------------------
void cInventory::AddPickupCallback(const tString &asItem, const tString &asFunction) {
// Log("Adding callback %s %s\n",asItem.c_str(),asFunction.c_str());
cInventoryPickupCallback *pCallback = hplNew(cInventoryPickupCallback, ());
pCallback->msFunction = asFunction;
pCallback->msItem = asItem;
m_mapPickupCallbacks.insert(tInventoryPickupCallbackMap::value_type(asItem, pCallback));
}
//-----------------------------------------------------------------------
void cInventory::AddUseCallback(const tString &asItem, const tString &asObject, const tString &asFunction) {
// Check if the item - object combo already exist.
tInventoryUseCallbackMapIt it = m_mapUseCallbacks.find(asItem);
if (it != m_mapUseCallbacks.end()) {
int lCount = (int)m_mapUseCallbacks.count(asItem);
for (int i = 0; i < lCount; ++i) {
cInventoryUseCallback *pCallback = it->second;
if (pCallback->msObject == asObject) {
pCallback->msFunction = asFunction;
return;
}
}
}
// Add new.
cInventoryUseCallback *pCallback = hplNew(cInventoryUseCallback, ());
pCallback->msFunction = asFunction;
pCallback->msItem = asItem;
pCallback->msObject = asObject;
m_mapUseCallbacks.insert(tInventoryUseCallbackMap::value_type(asItem, pCallback));
}
//-----------------------------------------------------------------------
void cInventory::AddCombineCallback(const tString &asItem1, const tString &asItem2, const tString &asFunction) {
cInventoryCombineCallback *pCallback = hplNew(cInventoryCombineCallback, ());
pCallback->msFunction = asFunction;
pCallback->msItem1 = asItem1;
pCallback->msItem2 = asItem2;
pCallback->bKillMe = false;
mlstCombineCallbacks.push_back(pCallback);
}
//-----------------------------------------------------------------------
template<typename Map>
void removeCallbacks(Map &callbackMap, const tString &fn) {
auto newEnd = Hpl1::removeIf(callbackMap.begin(), callbackMap.end(), [&](typename Map::value_type &p) -> bool {
if (p.second->msFunction == fn) {
hplDelete(p.second);
return true;
}
return false;
});
callbackMap.erase(newEnd, callbackMap.end());
}
void cInventory::RemovePickupCallback(const tString &asFunction) {
removeCallbacks(m_mapPickupCallbacks, asFunction);
}
void cInventory::RemoveUseCallback(const tString &asFunction) {
removeCallbacks(m_mapUseCallbacks, asFunction);
}
void cInventory::RemoveCombineCallback(const tString &asFunction) {
tInventoryCombineCallbackListIt it = mlstCombineCallbacks.begin();
for (; it != mlstCombineCallbacks.end(); ++it) {
cInventoryCombineCallback *pCallback = *it;
if (pCallback->msFunction == asFunction) {
if (mbCheckingCombineItems) {
pCallback->bKillMe = true;
} else {
mlstCombineCallbacks.erase(it);
hplDelete(pCallback);
}
return;
}
}
}
//-----------------------------------------------------------------------
void cInventory::CheckPickupCallback(const tString &asItem) {
tInventoryPickupCallbackMapIt it = m_mapPickupCallbacks.find(asItem);
if (it == m_mapPickupCallbacks.end())
return;
cInventoryPickupCallback *pCallback = it->second;
tString sCommand = pCallback->msFunction + "(\"" + asItem + "\")";
mpInit->RunScriptCommand(sCommand);
}
//-----------------------------------------------------------------------
bool cInventory::CheckUseCallback(const tString &asItem, const tString &asObject) {
tInventoryUseCallbackMapIt it = m_mapUseCallbacks.find(asItem);
if (it == m_mapUseCallbacks.end())
return false;
int lItemCount = (int)m_mapUseCallbacks.count(asItem);
tString sCommand = "";
for (int i = 0; i < lItemCount; ++i) {
cInventoryUseCallback *pCallback = it->second;
if (pCallback->msObject == asObject) {
sCommand = pCallback->msFunction + "(\"" + asItem + "\", \"" + asObject + "\")";
break;
}
++it;
}
if (sCommand != "") {
mpInit->RunScriptCommand(sCommand);
return true;
}
return false;
}
//-----------------------------------------------------------------------
bool cInventory::CheckCombineCallback(const tString &asItem1, const tString &asItem2, int alSlotIndex) {
cInventoryCombineCallback *pFinalCallback = NULL;
mbCheckingCombineItems = true;
tInventoryCombineCallbackListIt it = mlstCombineCallbacks.begin();
for (; it != mlstCombineCallbacks.end(); ++it) {
cInventoryCombineCallback *pCallback = *it;
if ((pCallback->msItem1 == asItem1 && pCallback->msItem2 == asItem2) ||
(pCallback->msItem1 == asItem2 && pCallback->msItem2 == asItem1)) {
pFinalCallback = pCallback;
break;
}
}
mbCheckingCombineItems = false;
if (pFinalCallback) {
char sString[30];
snprintf(sString, 30, "%d", alSlotIndex);
tString sCommand = pFinalCallback->msFunction + "(\"" + asItem1 + "\", \"" + asItem2 + "\", " +
cString::ToString(sString, "") + ")";
mpInit->RunScriptCommand(sCommand);
return true;
} else {
// SetActive(false);
tString sEntry = "CannotCombineItems" + cString::ToString(cMath::RandRectl(1, 5));
// mpInit->mpGameMessageHandler->Add(kTranslate("Inventory", sEntry));
SetMessage(kTranslate("Inventory", sEntry));
}
// Check if any callbacks should be killed
for (; it != mlstCombineCallbacks.end();) {
cInventoryCombineCallback *pCallback = *it;
if (pCallback->bKillMe) {
it = mlstCombineCallbacks.erase(it);
hplDelete(pCallback);
} else {
++it;
}
}
return false;
}
//-----------------------------------------------------------------------
void cInventory::ClearCallbacks() {
STLMapDeleteAll(m_mapPickupCallbacks);
STLMapDeleteAll(m_mapUseCallbacks);
STLDeleteAll(mlstCombineCallbacks);
}
//-----------------------------------------------------------------------
void cInventory::SaveToGlobal(cInventory_GlobalSave *apSave) {
apSave->mbNoteBookActive = mbNoteBookIsActive;
////////////////////////////
// Items
tInventoryItemMapIt ItemIt = m_mapItems.begin();
for (; ItemIt != m_mapItems.end(); ++ItemIt) {
cInventoryItem *pItem = ItemIt->second;
cInventoryItem_GlobalSave saveItem;
saveItem.msName = pItem->msName;
saveItem.msGameName = pItem->msGameName;
saveItem.msDescription = pItem->msDescription;
saveItem.mItemType = pItem->mItemType;
saveItem.msSubType = pItem->msSubType;
saveItem.msEntityFile = pItem->msEntityFile;
saveItem.msGfxObjectFile = pItem->mpGfxObject->GetSourceFile();
saveItem.msHudModelFile = pItem->msHudModelFile;
saveItem.msHudModelName = pItem->msHudModelName;
saveItem.mbCanBeDropped = pItem->mbCanBeDropped;
saveItem.mbHasCount = pItem->mbHasCount;
saveItem.mlCount = pItem->mlCount;
apSave->mlstItems.Add(saveItem);
}
////////////////////////////
// Equip slots
apSave->mvEquipSlots.Resize(mvEquipSlots.size());
for (size_t i = 0; i < mvEquipSlots.size(); i++) {
if (mvEquipSlots[i]->mpItem)
apSave->mvEquipSlots[i].msItemName = mvEquipSlots[i]->mpItem->GetName();
else
apSave->mvEquipSlots[i].msItemName = "";
}
////////////////////////////
// Normal slots
tInventorySlotListIt SlotIt = mlstSlots.begin();
for (; SlotIt != mlstSlots.end(); ++SlotIt) {
cInventorySlot *pSlot = *SlotIt;
cInventorySlot_GlobalSave saveSlot;
if (pSlot->mpItem)
saveSlot.msItemName = pSlot->mpItem->GetName();
else
saveSlot.msItemName = "";
apSave->mlstSlots.Add(saveSlot);
}
}
//-----------------------------------------------------------------------
void cInventory::LoadFromGlobal(cInventory_GlobalSave *apSave) {
mbNoteBookIsActive = apSave->mbNoteBookActive;
////////////////////////////
// Items
cContainerListIterator<cInventoryItem_GlobalSave> ItemIt = apSave->mlstItems.GetIterator();
while (ItemIt.HasNext()) {
cInventoryItem *pItem = hplNew(cInventoryItem, (mpInit));
cInventoryItem_GlobalSave saveItem = ItemIt.Next();
pItem->msName = saveItem.msName;
pItem->msGameName = saveItem.msGameName;
pItem->msDescription = saveItem.msDescription;
pItem->mItemType = saveItem.mItemType;
pItem->msSubType = saveItem.msSubType;
pItem->msEntityFile = saveItem.msEntityFile;
pItem->mpGfxObject = mpDrawer->CreateGfxObject(saveItem.msGfxObjectFile, "diffalpha2d");
pItem->mpGfxObjectAdditive = mpDrawer->CreateGfxObject(saveItem.msGfxObjectFile, "diffadditive2d");
pItem->msHudModelFile = saveItem.msHudModelFile;
pItem->msHudModelName = saveItem.msHudModelName;
pItem->mbCanBeDropped = saveItem.mbCanBeDropped;
pItem->mbHasCount = saveItem.mbHasCount;
pItem->mlCount = saveItem.mlCount;
m_mapItems.insert(tInventoryItemMap::value_type(pItem->msName, pItem));
}
////////////////////////////
// Equip slots
for (size_t i = 0; i < mvEquipSlots.size(); i++) {
if (apSave->mvEquipSlots[i].msItemName != "")
mvEquipSlots[i]->mpItem = GetItem(apSave->mvEquipSlots[i].msItemName);
else
mvEquipSlots[i]->mpItem = NULL;
}
////////////////////////////
// Normal slots
cContainerListIterator<cInventorySlot_GlobalSave> SlotIt = apSave->mlstSlots.GetIterator();
tInventorySlotListIt SlotListIt = mlstSlots.begin();
while (SlotIt.HasNext()) {
cInventorySlot *pSlot = *SlotListIt;
cInventorySlot_GlobalSave saveSlot = SlotIt.Next();
if (saveSlot.msItemName != "")
pSlot->mpItem = GetItem(saveSlot.msItemName);
else
pSlot->mpItem = NULL;
++SlotListIt;
}
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// SAVE OBJECT STUFF
//////////////////////////////////////////////////////////////////////////
//-------------------------------------------------------------------
kBeginSerializeBase(cInventoryUseCallback)
kSerializeVar(msItem, eSerializeType_String)
kSerializeVar(msObject, eSerializeType_String)
kSerializeVar(msFunction, eSerializeType_String)
kEndSerialize()
//-------------------------------------------------------------------
kBeginSerializeBase(cInventoryPickupCallback)
kSerializeVar(msItem, eSerializeType_String)
kSerializeVar(msFunction, eSerializeType_String)
kEndSerialize()
//-----------------------------------------------------------------------
kBeginSerializeBase(cInventoryCombineCallback)
kSerializeVar(msItem1, eSerializeType_String)
kSerializeVar(msItem2, eSerializeType_String)
kSerializeVar(msFunction, eSerializeType_String)
kSerializeVar(bKillMe, eSerializeType_Bool)
kEndSerialize()
//-----------------------------------------------------------------------
kBeginSerializeBase(cSaveData_cInventory)
kSerializeClassContainer(mlstUseCallbacks, cInventoryUseCallback, eSerializeType_Class)
kSerializeClassContainer(mlstPickupCallbacks, cInventoryPickupCallback, eSerializeType_Class)
kSerializeClassContainer(mlstCombineCallbacks, cInventoryCombineCallback, eSerializeType_Class)
kEndSerialize()
//-----------------------------------------------------------------------
iSaveObject *cSaveData_cInventory::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
///////////////////////
// Use callbacks
{
cContainerListIterator<cInventoryUseCallback> it = mlstUseCallbacks.GetIterator();
while (it.HasNext()) {
cInventoryUseCallback &temp = it.Next();
gpInit->mpInventory->AddUseCallback(temp.msItem, temp.msObject, temp.msFunction);
}
}
///////////////////////
// Pickup callbacks
{
cContainerListIterator<cInventoryPickupCallback> it = mlstPickupCallbacks.GetIterator();
while (it.HasNext()) {
cInventoryPickupCallback &temp = it.Next();
gpInit->mpInventory->AddPickupCallback(temp.msItem, temp.msFunction);
}
}
///////////////////////
// Combine callbacks
{
cContainerListIterator<cInventoryCombineCallback> it = mlstCombineCallbacks.GetIterator();
while (it.HasNext()) {
cInventoryCombineCallback &temp = it.Next();
gpInit->mpInventory->AddCombineCallback(temp.msItem1, temp.msItem2, temp.msFunction);
}
}
return NULL;
}
//-----------------------------------------------------------------------
int cSaveData_cInventory::GetSaveCreatePrio() {
return 4;
}
//-----------------------------------------------------------------------
iSaveData *cInventory::CreateSaveData() {
cSaveData_cInventory *pData = hplNew(cSaveData_cInventory, ());
//////////////////////
// Use callbacks
{
tInventoryUseCallbackMapIt it = m_mapUseCallbacks.begin();
for (; it != m_mapUseCallbacks.end(); ++it) {
pData->mlstUseCallbacks.Add(*(it->second));
}
}
//////////////////////
// Pickup callbacks
{
tInventoryPickupCallbackMapIt it = m_mapPickupCallbacks.begin();
for (; it != m_mapPickupCallbacks.end(); ++it) {
pData->mlstPickupCallbacks.Add(*(it->second));
}
}
//////////////////////
// Combine callbacks
{
tInventoryCombineCallbackListIt it = mlstCombineCallbacks.begin();
for (; it != mlstCombineCallbacks.end(); ++it) {
pData->mlstCombineCallbacks.Add(*(*it));
}
}
return pData;
}
//-----------------------------------------------------------------------