/* 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 . * */ /* * 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(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 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 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 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 it = mlstUseCallbacks.GetIterator(); while (it.HasNext()) { cInventoryUseCallback &temp = it.Next(); gpInit->mpInventory->AddUseCallback(temp.msItem, temp.msObject, temp.msFunction); } } /////////////////////// // Pickup callbacks { cContainerListIterator it = mlstPickupCallbacks.GetIterator(); while (it.HasNext()) { cInventoryPickupCallback &temp = it.Next(); gpInit->mpInventory->AddPickupCallback(temp.msItem, temp.msFunction); } } /////////////////////// // Combine callbacks { cContainerListIterator 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; } //-----------------------------------------------------------------------