/*
===========================================================================
ARX FATALIS GPL Source Code
Copyright (C) 1999-2010 Arkane Studios SA, a ZeniMax Media company.
This file is part of the Arx Fatalis GPL Source Code ('Arx Fatalis Source Code').
Arx Fatalis Source Code 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.
Arx Fatalis Source Code 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 Arx Fatalis Source Code. If not, see
.
In addition, the Arx Fatalis Source Code is also subject to certain additional terms. You should have received a copy of these
additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Arx
Fatalis Source Code. If not, please request a copy in writing from Arkane Studios at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing Arkane Studios, c/o
ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
//////////////////////////////////////////////////////////////////////////////////////
// @@ @@@ @@@ @@ @@@@@ //
// @@@ @@@@@@ @@@ @@ @@@@ @@@ @@@ //
// @@@ @@@@@@@ @@@ @@@@ @@@@ @@ @@@@ //
// @@@ @@ @@@@ @@@ @@@@@ @@@@@@ @@@ @@@ //
// @@@@@ @@ @@@@ @@@ @@@@@ @@@@@@@ @@@ @ @@@ //
// @@@@@ @@ @@@@ @@@@@@@@ @@@@ @@@ @@@@@ @@ @@@@@@@ //
// @@ @@@ @@ @@@@ @@@@@@@ @@@ @@@ @@@@@@ @@ @@@@ //
// @@@ @@@ @@@ @@@@ @@@@@ @@@@@@@@@ @@@@@@@ @@@ @@@@ //
// @@@ @@@@ @@@@@@@ @@@@@@ @@@ @@@@ @@@ @@@ @@@ @@@@ //
// @@@@@@@@ @@@@@ @@@@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@@@ //
// @@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@ @@@@ @@@ @@@@ @@@@@ //
//@@@ @@@@ @@@@@ @@@ @@@@@@ @@ @@@ @@@@ @@@@@@@ @@@@@ @@@@@ //
//@@@ @@@@@ @@@@@ @@@@ @@@ @@ @@ @@@@ @@@@@@@ @@@@@@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@@@@ //
//@@@ @@@@ @@@@@@@ @@@@ @@ @@ @@@@ @@@@@ @@ //
//@@@ @@@ @@@ @@@@@ @@ @@@ //
// @@@ @@@ @@ @@ STUDIOS //
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
// ARX_Inventory
//////////////////////////////////////////////////////////////////////////////////////
//
// Description:
// ARX Inventories Management
//
// Updates: (date) (person) (update)
//
// Code: Cyril Meynier
//
// Copyright (c) 1999-2001 ARKANE Studios SA. All rights reserved
//////////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------------
#include "HERMESPerf.h"
#include "EERIEApp.h"
#include "EERIELight.h"
#include "EERIELinkedObj.h"
#include "EERIEMath.h"
#include "EERIEPhysicsBox.h"
#include "EERIEPoly.H"
#include "EERIETexture.H"
#include "ARX_INPUT.h"
#include "ARX_Interactive.h"
#include "ARX_Interface.h"
#include "ARX_Equipment.h"
#include "ARX_Menu2.h"
#include "ARX_Paths.h"
#include "ARX_Player.h"
#include "ARX_Script.h"
#include "ARX_Sound.h"
#include
#include
using namespace std;
#include
#define _CRTDBG_MAP_ALLOC
#include
//------------------------------------------------------------------------------------
extern E_ARX_STATE_MOUSE eMouseState;
extern float InventoryX;
extern float InventoryDir;
extern long PLAYER_INTERFACE_HIDE_COUNT;
extern long DRAGGING;
extern CMenuConfig * pMenuConfig;
extern long TRUE_PLAYER_MOUSELOOK_ON;
void ARX_INTERFACE_Combat_Mode(long i);
void ARX_INVENTORY_ReOrder();
void ARX_INVENTORY_IdentifyIO(INTERACTIVE_OBJ * _pIO);
//------------------------------------------------------------------------------------
//CInventory Inventory;
INVENTORY_SLOT inventory[3][INVENTORY_X][INVENTORY_Y];
INVENTORY_DATA * SecondaryInventory = NULL;
INTERACTIVE_OBJ * DRAGINTER = NULL;
INTERACTIVE_OBJ * ioSteal = NULL;
long InventoryY = 100;
long HERO_OR_SECONDARY = 0;
short sActiveInventory = 0;
// 1 player 2 secondary
short sInventory = -1;
short sInventoryX = -1;
short sInventoryY = -1;
//*************************************************************************************
// void ARX_INVENTORY_Declare_InventoryIn(INTERACTIVE_OBJ * io)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Declares an IO as entering into player Inventory
// Sends appropriate INVENTORYIN Event to player AND concerned io.
//*************************************************************************************
void ARX_INVENTORY_Declare_InventoryIn(INTERACTIVE_OBJ * io)
{
if (io)
{
if (io->ignition > 0)
{
if (ValidDynLight(io->ignit_light))
DynLight[io->ignit_light].exist = 0;
io->ignit_light = -1;
if (io->ignit_sound != ARX_SOUND_INVALID_RESOURCE)
{
ARX_SOUND_Stop(io->ignit_sound);
io->ignit_sound = ARX_SOUND_INVALID_RESOURCE;
}
io->ignition = 0;
}
EVENT_SENDER = io;
SendIOScriptEvent(inter.iobj[0], SM_INVENTORYIN, "", NULL);
EVENT_SENDER = inter.iobj[0];
SendIOScriptEvent(io, SM_INVENTORYIN, "", NULL);
EVENT_SENDER = NULL;
}
}
//*************************************************************************************
// void ARX_INVENTORY_Declare_InventoryOut(INTERACTIVE_OBJ * io)
//-------------------------------------------------------------------------------------
// NOT USED Right Now
//*************************************************************************************
void ARX_INVENTORY_Declare_InventoryOut(INTERACTIVE_OBJ * io)
{
}
//*************************************************************************************
// void ARX_INVENTORY_Declare_Inventory_2_Out(INTERACTIVE_OBJ * io)
//-------------------------------------------------------------------------------------
// NOT USED Right Now
//*************************************************************************************
void ARX_INVENTORY_Declare_Inventory_2_Out(INTERACTIVE_OBJ * io)
{
}
//*************************************************************************************
// void CleanInventory()
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Cleans Player inventory
//*************************************************************************************
void CleanInventory()
{
for (long iNbBag = 0; iNbBag < 3; iNbBag++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
inventory[iNbBag][i][j].io = NULL;
inventory[iNbBag][i][j].show = 1;
}
sActiveInventory = 0;
}
extern EERIE_S2D DANAEMouse;
extern long DANAESIZX;
extern long DANAESIZY;
extern long DANAECENTERX;
extern long DANAECENTERY;
//*************************************************************************************
// INTERACTIVE_OBJ * GetInventoryObj()
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
//
//*************************************************************************************
INTERACTIVE_OBJ * GetInventoryObj(EERIE_S2D * pos)
{
long tx, ty;
float fCenterX = DANAECENTERX - INTERFACE_RATIO(320) + INTERFACE_RATIO(35);
float fSizY = DANAESIZY - INTERFACE_RATIO(101) + INTERFACE_RATIO_LONG(InventoryY);
ARX_CHECK_INT(fCenterX);
ARX_CHECK_INT(fSizY);
int iPosX = ARX_CLEAN_WARN_CAST_INT(fCenterX);
int iPosY = ARX_CLEAN_WARN_CAST_INT(fSizY);
if (player.Interface & INTER_INVENTORY)
{
tx = pos->x - iPosX; //-4
ty = pos->y - iPosY; //-2
if ((tx >= 0) && (ty >= 0))
{
ARX_CHECK_LONG(tx / INTERFACE_RATIO(32.f));
ARX_CHECK_LONG(ty / INTERFACE_RATIO(32.f));
tx = ARX_CLEAN_WARN_CAST_LONG(tx / INTERFACE_RATIO(32));
ty = ARX_CLEAN_WARN_CAST_LONG(ty / INTERFACE_RATIO(32));
if ((tx >= 0) && (tx < INVENTORY_X) && (ty >= 0) && (ty < INVENTORY_Y))
{
if ((inventory[sActiveInventory][tx][ty].io)
&& (inventory[sActiveInventory][tx][ty].io->GameFlags & GFLAG_INTERACTIVITY))
{
HERO_OR_SECONDARY = 1;
return (inventory[sActiveInventory][tx][ty].io);
}
}
return NULL;
}
}
else if (player.Interface & INTER_INVENTORYALL)
{
float fBag = (player.bag - 1) * INTERFACE_RATIO(-121);
ARX_CHECK_INT(fBag);
int iY = ARX_CLEAN_WARN_CAST_INT(fBag);
for (int i = 0; i < player.bag; i++)
{
tx = pos->x - iPosX;
ty = pos->y - iPosY - iY;
ARX_CHECK_LONG(tx / INTERFACE_RATIO(32));
ARX_CHECK_LONG(ty / INTERFACE_RATIO(32));
tx = ARX_CLEAN_WARN_CAST_LONG(tx / INTERFACE_RATIO(32));
ty = ARX_CLEAN_WARN_CAST_LONG(ty / INTERFACE_RATIO(32));
if ((tx >= 0) && (tx < INVENTORY_X) && (ty >= 0) && (ty < INVENTORY_Y))
{
if ((inventory[i][tx][ty].io)
&& (inventory[i][tx][ty].io->GameFlags & GFLAG_INTERACTIVITY))
{
HERO_OR_SECONDARY = 1;
return (inventory[i][tx][ty].io);
}
return NULL;
}
float fRatio = INTERFACE_RATIO(121);
ARX_CHECK_INT(iY + fRatio);
iY += ARX_CLEAN_WARN_CAST_INT(fRatio);
}
}
return NULL;
}
//*************************************************************************************
// INTERACTIVE_OBJ * GetInventoryObj_INVENTORYUSE(EERIE_S2D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
//
//*************************************************************************************
INTERACTIVE_OBJ * GetInventoryObj_INVENTORYUSE(EERIE_S2D * pos)
{
INTERACTIVE_OBJ * io = GetFromInventory(pos);
if (io != NULL)
{
if (HERO_OR_SECONDARY == 2)
{
if (SecondaryInventory != NULL)
{
INTERACTIVE_OBJ * temp = (INTERACTIVE_OBJ *)SecondaryInventory->io;
if (temp->ioflags & IO_SHOP) return NULL;
}
}
return io;
}
if (InInventoryPos(pos)) return NULL;
if ((io = InterClick(pos)) != NULL)
{
return io;
}
return NULL;
}
//*************************************************************************************
// void PutInFrontOfPlayer(INTERACTIVE_OBJ * io,long flag)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Puts an IO in front of the player
// flag=1 don't apply physics
//*************************************************************************************
void PutInFrontOfPlayer(INTERACTIVE_OBJ * io, long flag)
{
if (io == NULL) return;
float t = DEG2RAD(player.angle.b);
io->pos.x = player.pos.x - (float)EEsin(t) * 80.f;
io->pos.z = player.pos.z + (float)EEcos(t) * 80.f;
io->pos.y = player.pos.y + 20.f;
io->velocity.y = 0.3f;
io->velocity.x = 0;
io->velocity.z = 0;
io->angle.a = 0.f;
io->angle.b = 0;
io->angle.g = 0.f;
io->stopped = 0;
io->show = SHOW_FLAG_IN_SCENE;
EERIE_3D pos, vector;
vector.x = 0.f;
vector.y = 100.f;
vector.z = 0.f;
pos.x = io->pos.x;
pos.y = io->pos.y;
pos.z = io->pos.z;
if ((flag) && (io) && (io->obj) && (io->obj->pbox))
{
io->soundtime = 0;
io->soundcount = 0;
EERIE_PHYSICS_BOX_Launch(io->obj, &pos, &vector);
}
}
//*************************************************************************************
// void IO_Drop_Item(INTERACTIVE_OBJ * io_src,INTERACTIVE_OBJ * io)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// forces "io_scr" IO to drop "io" item with physics
//*************************************************************************************
void IO_Drop_Item(INTERACTIVE_OBJ * io_src, INTERACTIVE_OBJ * io)
{
// Validity Check
if ((!io) || (!io_src)) return;
float t = DEG2RAD(io_src->angle.b);
io->velocity.y = 0.3f;
io->velocity.x = -(float)EEsin(t) * 50.f;
io->velocity.z = (float)EEcos(t) * 50.f;
io->angle.a = 0.f;
io->angle.b = 0;
io->angle.g = 0.f;
io->stopped = 0;
io->show = SHOW_FLAG_IN_SCENE;
EERIE_3D pos, vector;
vector.x = 0.f;
vector.y = 100.f;
vector.z = 0.f;
pos.x = io->pos.x;
pos.y = io->pos.y;
pos.z = io->pos.z;
if ((io) && (io->obj) && (io->obj->pbox))
{
io->soundtime = 0;
io->soundcount = 0;
EERIE_PHYSICS_BOX_Launch_NOCOL(io, io->obj, &pos, &vector);
}
}
//*************************************************************************************
//
//*************************************************************************************
void ForcePlayerInventoryObjectLevel(long level)
{
for (long iNbBag = 0; iNbBag < 3; iNbBag++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io != NULL)
inventory[iNbBag][i][j].io->level = (short)level;
}
}
//-----------------------------------------------------------------------------
typedef struct _ATRIMAXSIZE: public greater
{
bool operator()(const INTERACTIVE_OBJ * x, const INTERACTIVE_OBJ * y) const;
} ATRIMAXSIZE;
bool ATRIMAXSIZE::operator()(const INTERACTIVE_OBJ * x, const INTERACTIVE_OBJ * y) const
{
int iSize0 = x->sizex * x->sizey * x->sizey;
int iSize1 = y->sizex * y->sizey * y->sizey;
if (iSize0 > iSize1)
{
return true;
}
else
{
if (iSize0 == iSize1)
{
int iRes = strcmp(x->locname, y->locname);
if (!iRes)
{
return false;
}
return iRes < 0 ? true : false;
}
}
return false;
}
bool FastInsert(INTERACTIVE_OBJ * _pIO, long _uiNumBag)
{
//on essaye de stacker
bool bFullStack = false;
for (long i = 0; i < INVENTORY_X; i++)
{
for (long j = 0; j < INVENTORY_Y; j++)
{
INTERACTIVE_OBJ * ioo = inventory[_uiNumBag][i][j].io;
if ((ioo) &&
(ioo->_itemdata->playerstacksize > 1) &&
IsSameObject(_pIO, ioo))
{
if (ioo->_itemdata->count < ioo->_itemdata->playerstacksize)
{
ioo->_itemdata->count += _pIO->_itemdata->count;
if (ioo->_itemdata->count > ioo->_itemdata->playerstacksize)
{
_pIO->_itemdata->count = ioo->_itemdata->count - ioo->_itemdata->playerstacksize;
ioo->_itemdata->count = ioo->_itemdata->playerstacksize;
bFullStack = true;
break;
}
else
{
_pIO->_itemdata->count = 0;
}
if (!_pIO->_itemdata->count)
{
if (_pIO->scriptload)
{
for (long ii = 0; ii < inter.nbmax; ii++)
{
if (inter.iobj[ii] == _pIO)
{
ReleaseInter(inter.iobj[ii]);
if (DRAGINTER == _pIO)
{
Set_DragInter(NULL);
}
_pIO = inter.iobj[ii] = NULL;
}
}
}
else
{
_pIO->show = SHOW_FLAG_KILLED;
}
}
return true;
}
}
}
if (bFullStack)
{
break;
}
}
for (int i = 0; i < INVENTORY_X; i++)
{
for (long j = 0; j < INVENTORY_Y; j++)
{
if (inventory[_uiNumBag][i][j].io == NULL)
{
int iSizeX = _pIO->sizex;
int iSizeY = _pIO->sizey;
bool bFound = true;
if (((i + iSizeX) > INVENTORY_X) ||
((j + iSizeY) > INVENTORY_Y))
{
bFound = false;
}
if (bFound)
{
for (long jj = j; jj < (j + iSizeY); jj++)
{
for (long ii = i; ii < (i + iSizeX); ii++)
{
if (inventory[_uiNumBag][ii][jj].io)
{
bFound = false;
}
if (!bFound)
{
break;
}
}
if (!bFound)
{
break;
}
}
}
if (bFound)
{
for (long jj = j; jj < (j + iSizeY); jj++)
{
for (long ii = i; ii < (i + iSizeX); ii++)
{
inventory[_uiNumBag][ii][jj].io = _pIO;
inventory[_uiNumBag][ii][jj].show = (ii == i) && (jj == j) ? 1 : 0;
}
}
return true;
}
}
}
}
return false;
}
void OptmizeInventory(unsigned int _uiNumBag)
{
ARX_CHECK_NOT_NEG(player.bag);
if (_uiNumBag < ARX_CAST_USHORT(player.bag))
{
vector vIO;
for (long j = 0 ; j < INVENTORY_Y ; j++)
{
for (long i = 0 ; i < INVENTORY_X ; i++)
{
if (inventory[_uiNumBag][i][j].io)
{
vIO.push_back(inventory[_uiNumBag][i][j].io);
int iSizeX = inventory[_uiNumBag][i][j].io->sizex;
int iSizeY = inventory[_uiNumBag][i][j].io->sizey;
for (long jj = j ; jj < (j + iSizeY) ; jj++)
{
for (long ii = i ; ii < (i + iSizeX) ; ii++)
{
inventory[_uiNumBag][ii][jj].io = NULL;
}
}
}
}
}
std::sort(vIO.begin(), vIO.end(), ATRIMAXSIZE());
vector::iterator it;
for (it = vIO.begin(); it != vIO.end(); it++)
{
FastInsert(*it, _uiNumBag);
}
vIO.clear();
}
}
//*************************************************************************************
// BOOL CanBePutInInventory(INTERACTIVE_OBJ * io)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// tries to put an object in player inventory
//*************************************************************************************
BOOL CanBePutInInventory(INTERACTIVE_OBJ * io)
{
if (io == NULL) return FALSE;
if (io->ioflags & IO_MOVABLE) return FALSE;
if (io->ioflags & IO_GOLD)
{
ARX_PLAYER_AddGold(io->_itemdata->price);
if (io->scriptload)
{
RemoveFromAllInventories(io);
long i = GetInterNum(io);
ReleaseInter(io);
inter.iobj[i] = NULL;
}
else
{
io->show = SHOW_FLAG_KILLED;
io->GameFlags &= ~GFLAG_ISINTREATZONE;
}
return TRUE;
}
long sx, sy;
long i, j, k, l;
sx = io->sizex;
sy = io->sizey;
// on essaie de le remettre à son ancienne place --------------------------
if (sInventory == 1 &&
(sInventoryX >= 0) &&
(sInventoryX <= INVENTORY_X - sx) &&
(sInventoryY >= 0) &&
(sInventoryY <= INVENTORY_Y - sy))
{
j = sInventoryY;
i = sInventoryX;
// first try to stack -------------------------------------------------
if (player.bag)
{
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
{
INTERACTIVE_OBJ * ioo = inventory[iNbBag][i][j].io;
if ((ioo)
&& (ioo->_itemdata->playerstacksize > 1)
&& (IsSameObject(io, ioo)))
{
if (ioo->_itemdata->count < ioo->_itemdata->playerstacksize)
{
ioo->_itemdata->count += io->_itemdata->count;
if (ioo->_itemdata->count > ioo->_itemdata->playerstacksize)
{
io->_itemdata->count = ioo->_itemdata->count - ioo->_itemdata->playerstacksize;
ioo->_itemdata->count = ioo->_itemdata->playerstacksize;
}
else io->_itemdata->count = 0;
if (!io->_itemdata->count)
{
if (io->scriptload)
{
for (long ii = 0; ii < inter.nbmax; ii++)
{
if (inter.iobj[ii] == io)
{
ReleaseInter(inter.iobj[ii]);
if (DRAGINTER == io)
Set_DragInter(NULL);
io = inter.iobj[ii] = NULL;
}
}
}
else
{
io->show = SHOW_FLAG_KILLED;
}
}
ARX_INVENTORY_Declare_InventoryIn(ioo);
sInventory = -1;
return TRUE;
}
}
}
}
if (player.bag)
{
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
{
if (inventory[iNbBag][i][j].io == NULL)
{
bool valid = true;
if ((sx == 0) || (sy == 0)) valid = false;
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
if (inventory[iNbBag][l][k].io != NULL) valid = false;
}
if (valid)
{
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
inventory[iNbBag][l][k].io = io;
inventory[iNbBag][l][k].show = 0;
}
inventory[iNbBag][i][j].show = 1;
ARX_INVENTORY_Declare_InventoryIn(io);
sInventory = -1;
return TRUE;
}
}
}
}
}
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (i = 0; i <= INVENTORY_X - sx; i++)
for (j = 0; j <= INVENTORY_Y - sy; j++)
{
INTERACTIVE_OBJ * ioo = inventory[iNbBag][i][j].io;
if ((ioo)
&& (ioo->_itemdata->playerstacksize > 1)
&& (IsSameObject(io, ioo)))
{
if (ioo->_itemdata->count < ioo->_itemdata->playerstacksize)
{
ioo->_itemdata->count += io->_itemdata->count;
if (ioo->_itemdata->count > ioo->_itemdata->playerstacksize)
{
io->_itemdata->count = ioo->_itemdata->count - ioo->_itemdata->playerstacksize;
ioo->_itemdata->count = ioo->_itemdata->playerstacksize;
}
else io->_itemdata->count = 0;
if (!io->_itemdata->count)
{
if (io->scriptload)
{
for (long ii = 0; ii < inter.nbmax; ii++)
{
if (inter.iobj[ii] == io)
{
ReleaseInter(inter.iobj[ii]);
if (DRAGINTER == io)
Set_DragInter(NULL);
io = inter.iobj[ii] = NULL;
}
}
}
else
{
io->show = SHOW_FLAG_KILLED;
}
ARX_INVENTORY_Declare_InventoryIn(ioo);
return TRUE;
}
}
}
}
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (i = 0; i <= INVENTORY_X - sx; i++)
for (j = 0; j <= INVENTORY_Y - sy; j++)
{
if (inventory[iNbBag][i][j].io == NULL)
{
bool valid = true;
if ((sx == 0) || (sy == 0)) valid = false;
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
if (inventory[iNbBag][l][k].io != NULL) valid = false;
}
if (valid)
{
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
inventory[iNbBag][l][k].io = io;
inventory[iNbBag][l][k].show = 0;
}
inventory[iNbBag][i][j].show = 1;
ARX_INVENTORY_Declare_InventoryIn(io);
return TRUE;
}
}
}
return FALSE;
}
//*************************************************************************************
// BOOL CanBePutInSecondaryInventory(INVENTORY_DATA * id,INTERACTIVE_OBJ * io,long * xx,long * yy)
//------------------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Tries to put an object in secondary inventory
//*************************************************************************************
BOOL CanBePutInSecondaryInventory(INVENTORY_DATA * id, INTERACTIVE_OBJ * io, long * xx, long * yy)
{
if (!id) return FALSE;
if (!io) return FALSE;
if (io->ioflags & IO_MOVABLE) return FALSE;
long sx, sy;
long i, j, k, l;
*xx = -1;
*yy = -1;
sx = io->sizex;
sy = io->sizey;
// on essaie de le remettre à son ancienne place
if (sInventory == 2 &&
(sInventoryX >= 0) &&
(sInventoryX <= id->sizex - sx) &&
(sInventoryY >= 0) &&
(sInventoryY <= id->sizey - sy))
{
j = sInventoryY;
i = sInventoryX;
// first try to stack
INTERACTIVE_OBJ * ioo = id->slot[i][j].io;
if (ioo)
if ((ioo->_itemdata->playerstacksize > 1) &&
(IsSameObject(io, ioo)))
{
if ((ioo->_itemdata->count < ioo->_itemdata->playerstacksize)
&& (ioo->durability == io->durability))
{
if (io->ioflags & IO_GOLD)
{
ioo->_itemdata->price += io->_itemdata->price;
}
else
{
ioo->_itemdata->count += io->_itemdata->count;
ioo->scale = 1.f;
}
if (io->scriptload)
{
for (long ii = 0; ii < inter.nbmax; ii++)
{
if (inter.iobj[ii] == io)
{
ReleaseInter(inter.iobj[ii]);
}
}
}
else
{
io->show = SHOW_FLAG_KILLED;
}
sInventory = -1;
return TRUE;
}
}
ioo = id->slot[i][j].io;
if (!ioo)
{
long valid = 1;
if ((sx == 0) || (sy == 0)) valid = 0;
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
if (id->slot[l][k].io != NULL)
{
valid = 0;
break;
}
}
if (valid)
{
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
id->slot[l][k].io = io;
id->slot[l][k].show = 0;
}
id->slot[i][j].show = 1;
*xx = i;
*yy = j;
sInventory = -1;
return TRUE;
}
}
}
for (j = 0; j <= id->sizey - sy; j++)
for (i = 0; i <= id->sizex - sx; i++)
{
INTERACTIVE_OBJ * ioo = id->slot[i][j].io;
if (ioo)
if ((ioo->_itemdata->playerstacksize > 1) &&
(IsSameObject(io, ioo)))
{
if ((ioo->_itemdata->count < ioo->_itemdata->playerstacksize)
&& (ioo->durability == io->durability))
{
if (io->ioflags & IO_GOLD)
{
ioo->_itemdata->price += io->_itemdata->price;
}
else
{
ioo->_itemdata->count += io->_itemdata->count;
ioo->scale = 1.f;
}
if (io->scriptload)
{
for (long ii = 0; ii < inter.nbmax; ii++)
{
if (inter.iobj[ii] == io)
{
ReleaseInter(inter.iobj[ii]);
}
}
}
else
{
io->show = SHOW_FLAG_KILLED;
}
return TRUE;
}
}
}
for (j = 0; j <= id->sizey - sy; j++)
for (i = 0; i <= id->sizex - sx; i++)
{
INTERACTIVE_OBJ * ioo = id->slot[i][j].io;
if (!ioo)
{
long valid = 1;
if ((sx == 0) || (sy == 0)) valid = 0;
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
if (id->slot[l][k].io != NULL)
{
valid = 0;
break;
}
}
if (valid)
{
for (k = j; k < j + sy; k++)
for (l = i; l < i + sx; l++)
{
id->slot[l][k].io = io;
id->slot[l][k].show = 0;
}
id->slot[i][j].show = 1;
*xx = i;
*yy = j;
return TRUE;
}
}
}
*xx = -1;
*yy = -1;
return FALSE;
}
//*************************************************************************************
// BOOL PutInInventory()
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Try to put DRAGINTER object in an inventory
//*************************************************************************************
BOOL PutInInventory()
{
// Check Validity
if ((!DRAGINTER)
|| (DRAGINTER->ioflags & IO_MOVABLE))
return FALSE;
short tx, ty;
long sx, sy;
long i, j;
tx = ty = 0;
sx = DRAGINTER->sizex;
sy = DRAGINTER->sizey;
// Check for backpack Icon
if (MouseInRect((float)DANAESIZX - 35, (float)DANAESIZY - 113, (float)DANAESIZX - 35 + 32, (float)DANAESIZY - 113 + 32))
{
if (CanBePutInInventory(DRAGINTER))
{
if (DRAGINTER)
DRAGINTER->show = SHOW_FLAG_IN_INVENTORY;
ARX_SOUND_PlayInterface(SND_INVSTD);
Set_DragInter(NULL);
}
return FALSE;
}
// First Look for Identical Item...
if ((SecondaryInventory != NULL) && (InSecondaryInventoryPos(&DANAEMouse)))
{
INTERACTIVE_OBJ * io = (INTERACTIVE_OBJ *)SecondaryInventory->io;
float fcos = ARX_INTERACTIVE_GetPrice(DRAGINTER, io) / 3.0f; //>>1;
ARX_CHECK_LONG(fcos);
long cos = ARX_CLEAN_WARN_CAST_LONG(fcos);
cos *= DRAGINTER->_itemdata->count;
fcos = cos + cos * ((float)player.Full_Skill_Intuition) * 0.005f;
ARX_CHECK_LONG(fcos);
cos = ARX_CLEAN_WARN_CAST_LONG(fcos);
if (io->ioflags & IO_SHOP)
{
if ((io->shop_category) && (!IsIOGroup(DRAGINTER, io->shop_category)))
return FALSE;
if (cos <= 0) return FALSE;
}
INTERACTIVE_OBJ * ioo;
if (io->ioflags & IO_SHOP) // SHOP
{
// Check shop group
for (j = 0; j < SecondaryInventory->sizey; j++)
for (i = 0; i < SecondaryInventory->sizex; i++)
{
ioo = (INTERACTIVE_OBJ *)SecondaryInventory->slot[i][j].io;
if (ioo)
{
if (IsSameObject(DRAGINTER, ioo))
{
ioo->_itemdata->count += DRAGINTER->_itemdata->count;
ioo->scale = 1.f;
if (DRAGINTER->scriptload)
{
for (long ii = 0; ii < inter.nbmax; ii++)
{
if (inter.iobj[ii] == DRAGINTER)
{
ReleaseInter(inter.iobj[ii]);
inter.iobj[ii] = NULL;
Set_DragInter(NULL);
}
}
}
else
{
DRAGINTER->show = SHOW_FLAG_KILLED;
Set_DragInter(NULL);
}
ARX_PLAYER_AddGold(cos);
ARX_SOUND_PlayInterface(SND_GOLD);
ARX_SOUND_PlayInterface(SND_INVSTD);
return TRUE;
}
}
}
}
tx = DANAEMouse.x + ARX_CLEAN_WARN_CAST_SHORT(InventoryX) - SHORT_INTERFACE_RATIO(2);
ty = DANAEMouse.y - SHORT_INTERFACE_RATIO(13);
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx <= SecondaryInventory->sizex - sx) && (ty <= SecondaryInventory->sizey - sy))
{
float fcos = ARX_INTERACTIVE_GetPrice(DRAGINTER, io) / 3.0f; //>>1;
ARX_CHECK_LONG(fcos);
long cos = ARX_CLEAN_WARN_CAST_LONG(fcos);
cos *= DRAGINTER->_itemdata->count;
fcos = cos + cos * ((float)player.Full_Skill_Intuition) * 0.005f;
ARX_CHECK_LONG(fcos);
cos = ARX_CLEAN_WARN_CAST_LONG(fcos);
for (j = 0; j < sy; j++)
for (i = 0; i < sx; i++)
{
if (SecondaryInventory->slot[tx+i][ty+j].io != NULL)
{
long xx, yy;
DRAGINTER->show = SHOW_FLAG_IN_INVENTORY;
//Superposition d'objets
INTERACTIVE_OBJ * ioo = SecondaryInventory->slot[tx+i][ty+j].io;
if ((ioo->_itemdata->playerstacksize > 1) &&
(IsSameObject(DRAGINTER, ioo)) &&
(ioo->_itemdata->count < ioo->_itemdata->playerstacksize))
{
ioo->_itemdata->count += DRAGINTER->_itemdata->count;
if (ioo->_itemdata->count > ioo->_itemdata->playerstacksize)
{
DRAGINTER->_itemdata->count = ioo->_itemdata->count - ioo->_itemdata->playerstacksize;
ioo->_itemdata->count = ioo->_itemdata->playerstacksize;
}
else DRAGINTER->_itemdata->count = 0;
}
if (DRAGINTER->_itemdata->count)
{
if (CanBePutInSecondaryInventory(SecondaryInventory, DRAGINTER, &xx, &yy))
{
if (io->ioflags & IO_SHOP) // SHOP
{
ARX_PLAYER_AddGold(cos);
ARX_SOUND_PlayInterface(SND_GOLD);
}
}
else return FALSE;
}
ARX_SOUND_PlayInterface(SND_INVSTD);
Set_DragInter(NULL);
return TRUE;
}
}
if (DRAGINTER->ioflags & IO_GOLD)
{
ARX_PLAYER_AddGold(DRAGINTER->_itemdata->price);
ARX_SOUND_PlayInterface(SND_GOLD);
if (DRAGINTER->scriptload)
{
RemoveFromAllInventories(DRAGINTER);
ReleaseInter(DRAGINTER);
}
else
{
DRAGINTER->show = SHOW_FLAG_KILLED;
DRAGINTER->GameFlags &= ~GFLAG_ISINTREATZONE;
}
Set_DragInter(NULL);
return TRUE;
}
for (j = 0; j < sy; j++)
for (i = 0; i < sx; i++)
{
SecondaryInventory->slot[tx+i][ty+j].io = DRAGINTER;
SecondaryInventory->slot[tx+i][ty+j].show = 0;
}
if (io->ioflags & IO_SHOP) // SHOP
{
player.gold += cos;
ARX_SOUND_PlayInterface(SND_GOLD);
}
SecondaryInventory->slot[tx][ty].show = 1;
DRAGINTER->show = SHOW_FLAG_IN_INVENTORY;
ARX_SOUND_PlayInterface(SND_INVSTD);
Set_DragInter(NULL);
return TRUE;
}
}
if (!(player.Interface & INTER_INVENTORY) && !(player.Interface & INTER_INVENTORYALL))
return FALSE;
if (InventoryY != 0) return FALSE;
if (!InPlayerInventoryPos(&DANAEMouse)) return FALSE;
int iBag = 0;
float fCenterX = DANAECENTERX - INTERFACE_RATIO(320) + INTERFACE_RATIO(35);
float fSizY = DANAESIZY - INTERFACE_RATIO(101) + INTERFACE_RATIO_LONG(InventoryY);
ARX_CHECK_SHORT(fCenterX);
ARX_CHECK_SHORT(fSizY);
short iPosX = ARX_CLEAN_WARN_CAST_SHORT(fCenterX);
short iPosY = ARX_CLEAN_WARN_CAST_SHORT(fSizY);
if (player.Interface & INTER_INVENTORY)
{
tx = DANAEMouse.x - iPosX;
ty = DANAEMouse.y - iPosY;
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx >= 0) && (tx <= 16 - sx) && (ty >= 0) && (ty <= 3 - sy))
iBag = sActiveInventory;
else return FALSE;
}
else
{
bool bOk = false;
float fBag = (player.bag - 1) * INTERFACE_RATIO(-121);
ARX_CHECK_SHORT(fBag);
short iY = ARX_CLEAN_WARN_CAST_SHORT(fBag);
//We must enter the for-loop to initialyze tx/ty
ARX_CHECK(0 < player.bag);
for (int i = 0; i < player.bag; i++)
{
tx = DANAEMouse.x - iPosX;
ty = DANAEMouse.y - iPosY - iY;
if ((tx >= 0) && (ty >= 0))
{
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx >= 0) && (tx <= 16 - sx) && (ty >= 0) && (ty <= 3 - sy))
{
bOk = true;
iBag = i;
break;
}
}
float fRatio = INTERFACE_RATIO(121);
ARX_CHECK_SHORT(iY + fRatio);
iY += ARX_CLEAN_WARN_CAST_SHORT(fRatio);
}
if (!bOk)
return false;
}
if (DRAGINTER->ioflags & IO_GOLD)
{
ARX_PLAYER_AddGold(DRAGINTER->_itemdata->price);
ARX_SOUND_PlayInterface(SND_GOLD);
if (DRAGINTER->scriptload)
{
RemoveFromAllInventories(DRAGINTER);
ReleaseInter(DRAGINTER);
}
else
{
DRAGINTER->show = SHOW_FLAG_KILLED;
DRAGINTER->GameFlags &= ~GFLAG_ISINTREATZONE;
}
Set_DragInter(NULL);
return TRUE;
}
for (j = 0; j < sy; j++)
for (i = 0; i < sx; i++)
{
INTERACTIVE_OBJ * ioo = inventory[iBag][tx+i][ty+j].io;
if (ioo != NULL)
{
ARX_INVENTORY_IdentifyIO(ioo);
if ((ioo->_itemdata->playerstacksize > 1) &&
(IsSameObject(DRAGINTER, ioo)) &&
(ioo->_itemdata->count < ioo->_itemdata->playerstacksize))
{
ioo->_itemdata->count += DRAGINTER->_itemdata->count;
if (ioo->_itemdata->count > ioo->_itemdata->playerstacksize)
{
DRAGINTER->_itemdata->count = ioo->_itemdata->count - ioo->_itemdata->playerstacksize;
ioo->_itemdata->count = ioo->_itemdata->playerstacksize;
}
else DRAGINTER->_itemdata->count = 0;
ioo->scale = 1.f;
ARX_INVENTORY_Declare_InventoryIn(DRAGINTER);
if (!DRAGINTER->_itemdata->count)
{
if (DRAGINTER->scriptload)
{
for (long ii = 0; ii < inter.nbmax; ii++)
{
if (inter.iobj[ii] == DRAGINTER)
{
ReleaseInter(inter.iobj[ii]);
inter.iobj[ii] = NULL;
Set_DragInter(NULL);
}
}
}
else
{
DRAGINTER->show = SHOW_FLAG_KILLED;
Set_DragInter(NULL);
}
}
ARX_SOUND_PlayInterface(SND_INVSTD);
return TRUE;
}
if (0)
if (CanBePutInInventory(DRAGINTER))
{
if (DRAGINTER)
DRAGINTER->show = SHOW_FLAG_IN_INVENTORY;
ARX_SOUND_PlayInterface(SND_INVSTD);
Set_DragInter(NULL);
return TRUE;
}
return FALSE;
}
}
for (j = 0; j < sy; j++)
for (i = 0; i < sx; i++)
{
inventory[iBag][tx+i][ty+j].io = DRAGINTER;
inventory[iBag][tx+i][ty+j].show = 0;
}
inventory[iBag][tx][ty].show = 1;
ARX_INVENTORY_Declare_InventoryIn(DRAGINTER);
ARX_SOUND_PlayInterface(SND_INVSTD);
DRAGINTER->show = SHOW_FLAG_IN_INVENTORY;
Set_DragInter(NULL);
return TRUE;
}
//*************************************************************************************
// BOOL InSecondaryInventoryPos(EERIE_S2D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Returns TRUE if xx,yy is a position in secondary inventory
//*************************************************************************************
BOOL InSecondaryInventoryPos(EERIE_S2D * pos)
{
if (SecondaryInventory != NULL)
{
short tx, ty;
ARX_CHECK_SHORT(InventoryX);
tx = pos->x + ARX_CLEAN_WARN_CAST_SHORT(InventoryX) - SHORT_INTERFACE_RATIO(2);
ty = pos->y - SHORT_INTERFACE_RATIO(13);
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx < 0) || (tx >= SecondaryInventory->sizex)) return FALSE;
if ((ty < 0) || (ty >= SecondaryInventory->sizey)) return FALSE;
return TRUE;
}
return FALSE;
}
//*************************************************************************************
// BOOL InPlayerInventoryPos(EERIE_S2D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Returns TRUE if xx,yy is a position in player inventory
//*************************************************************************************
BOOL InPlayerInventoryPos(EERIE_S2D * pos)
{
if (PLAYER_INTERFACE_HIDE_COUNT) return FALSE;
float fCenterX = DANAECENTERX - INTERFACE_RATIO(320) + INTERFACE_RATIO(35);
float fSizY = DANAESIZY - INTERFACE_RATIO(101) + INTERFACE_RATIO_LONG(InventoryY);
ARX_CHECK_SHORT(fCenterX);
ARX_CHECK_SHORT(fSizY);
short iPosX = ARX_CLEAN_WARN_CAST_SHORT(fCenterX);
short iPosY = ARX_CLEAN_WARN_CAST_SHORT(fSizY);
short tx, ty;
if (player.Interface & INTER_INVENTORY)
{
tx = pos->x - iPosX;
ty = pos->y - iPosY;//-2;
if ((tx >= 0) && (ty >= 0))
{
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx >= 0) && (tx <= INVENTORY_X) && (ty >= 0) && (ty < INVENTORY_Y))
return TRUE;
else
return FALSE;
}
}
else if (player.Interface & INTER_INVENTORYALL)
{
float fBag = (player.bag - 1) * INTERFACE_RATIO(-121);
ARX_CHECK_SHORT(fBag);
short iY = ARX_CLEAN_WARN_CAST_SHORT(fBag);
if ((
(pos->x >= iPosX) &&
(pos->x <= iPosX + INVENTORY_X * INTERFACE_RATIO(32)) &&
(pos->y >= iPosY + iY) &&
(pos->y <= DANAESIZY)))
return true;
for (int i = 0; i < player.bag; i++)
{
tx = pos->x - iPosX;
ty = pos->y - iPosY - iY;
if ((tx >= 0) && (ty >= 0))
{
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx >= 0) && (tx <= INVENTORY_X) && (ty >= 0) && (ty < INVENTORY_Y))
return TRUE;
}
float fRatio = INTERFACE_RATIO(121);
ARX_CHECK_SHORT(iY + fRatio);
iY += ARX_CLEAN_WARN_CAST_SHORT(fRatio);
}
}
return FALSE;
}
//*************************************************************************************
// BOOL InInventoryPos(EERIE_S2D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Returns TRUE if "pos" is a position in player inventory or in SECONDARY inventory
//*************************************************************************************
BOOL InInventoryPos(EERIE_S2D * pos)
{
if (InSecondaryInventoryPos(pos))
return TRUE;
return (InPlayerInventoryPos(pos));
}
//*************************************************************************************
// BOOL IsFlyingOverInventory(EERIE_S2D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// returns TRUE if cursor is flying over any inventory
//*************************************************************************************
BOOL IsFlyingOverInventory(EERIE_S2D * pos)
{
short tx, ty;
// if(eMouseState==MOUSE_IN_WORLD) return false;
if (SecondaryInventory != NULL)
{
ARX_CHECK_SHORT(InventoryX);
tx = pos->x + ARX_CLEAN_WARN_CAST_SHORT(InventoryX) - SHORT_INTERFACE_RATIO(2);
ty = pos->y - SHORT_INTERFACE_RATIO(13);
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx >= 0) && (tx <= SecondaryInventory->sizex) && (ty >= 0) && (ty <= SecondaryInventory->sizey))
return TRUE;
}
return InPlayerInventoryPos(pos);
}
//*************************************************************************************
// INTERACTIVE_OBJ * GetFromInventory(EERIE_S2D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION/RESULT:
// Returns IO under position xx,yy in any INVENTORY or NULL if no IO
// was found
//*************************************************************************************
INTERACTIVE_OBJ * GetFromInventory(EERIE_S2D * pos)
{
short tx, ty;
INTERACTIVE_OBJ * io;
HERO_OR_SECONDARY = 0;
if (!IsFlyingOverInventory(pos))
return NULL;
if (SecondaryInventory != NULL)
{
ARX_CHECK_SHORT(InventoryX);
tx = pos->x + ARX_CLEAN_WARN_CAST_SHORT(InventoryX) - SHORT_INTERFACE_RATIO(2);
ty = pos->y - SHORT_INTERFACE_RATIO(13);
if ((tx >= 0) && (ty >= 0))
{
tx = tx / SHORT_INTERFACE_RATIO(32);
ty = ty / SHORT_INTERFACE_RATIO(32);
if ((tx >= 0) && (tx <= SecondaryInventory->sizex)
&& (ty >= 0) && (ty <= SecondaryInventory->sizey))
{
if (SecondaryInventory->slot[tx][ty].io == NULL)
return NULL;
if (((player.Interface & INTER_STEAL) && (!ARX_PLAYER_CanStealItem(SecondaryInventory->slot[tx][ty].io))))
return NULL;
io = SecondaryInventory->slot[tx][ty].io;
if (!(io->GameFlags & GFLAG_INTERACTIVITY))
return NULL;
HERO_OR_SECONDARY = 2;
return io;
}
}
}
return GetInventoryObj(pos);
}
//*************************************************************************************
// BOOL GetItemWorldPosition( INTERACTIVE_OBJ * io,EERIE_3D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION:
// Gets real world position for an IO (can be used for non items)
// (even in an inventory or being dragged)
// RESULT:
// Put the position in "pos". returns TRUE if position was found
// or FALSE if object is invalid, or position not defined.
//*************************************************************************************
BOOL GetItemWorldPosition(INTERACTIVE_OBJ * io, EERIE_3D * pos)
{
// Valid IO ?
if (!io) return FALSE;
// Is this object being Dragged by player ?
if (DRAGINTER == io)
{
// Set position to approximate center of player.
pos->x = player.pos.x;
pos->y = player.pos.y + 80.f;
pos->z = player.pos.z;
return TRUE;
}
// Not in scene ?
if (io->show != SHOW_FLAG_IN_SCENE)
{
// Is it equiped ?
if (IsEquipedByPlayer(io))
{
// in player inventory
pos->x = player.pos.x;
pos->y = player.pos.y + 80.f;
pos->z = player.pos.z;
return TRUE;
}
// Is it in any player inventory ?
for (long iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io == io)
{
pos->x = player.pos.x;
pos->y = player.pos.y + 80.f;
pos->z = player.pos.z;
return TRUE;
}
}
// Is it in any other IO inventory ?
for (long i = 0; i < inter.nbmax; i++)
{
INTERACTIVE_OBJ * ioo = inter.iobj[i];
if (ioo && ioo->inventory)
{
INVENTORY_DATA * id = (INVENTORY_DATA *)ioo->inventory;
for (long j = 0; j < id->sizey; j++)
for (long k = 0; k < id->sizex; k++)
{
if (id->slot[k][j].io == io)
{
Vector_Copy(pos, &ioo->pos);
return TRUE;
}
}
}
}
}
// Default position.
Vector_Copy(pos, &io->pos);
return TRUE;
}
//*************************************************************************************
// BOOL GetItemWorldPositionSound( INTERACTIVE_OBJ * io,EERIE_3D * pos)
//-------------------------------------------------------------------------------------
// FUNCTION:
// Gets real world position for an IO to spawn a sound
//*************************************************************************************
BOOL GetItemWorldPositionSound(INTERACTIVE_OBJ * io, EERIE_3D * pos)
{
if (!io) return FALSE;
long i, j, k;
INVENTORY_DATA * id;
if (DRAGINTER == io)
{
ARX_PLAYER_FrontPos(pos);
return TRUE;
}
if (io->show != SHOW_FLAG_IN_SCENE)
{
if (IsEquipedByPlayer(io))
{
// in player inventory
ARX_PLAYER_FrontPos(pos);
return TRUE;
}
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (j = 0; j < INVENTORY_Y; j++)
for (i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io == io)
{
// in player inventory
ARX_PLAYER_FrontPos(pos);
return TRUE;
}
}
for (i = 0; i < inter.nbmax; i++)
{
INTERACTIVE_OBJ * ioo = inter.iobj[i];
if (ioo && ioo->inventory)
{
id = (INVENTORY_DATA *)ioo->inventory;
for (j = 0; j < id->sizey; j++)
for (k = 0; k < id->sizex; k++)
{
if (id->slot[k][j].io == io)
{
pos->x = ioo->pos.x;
pos->y = ioo->pos.y;
pos->z = ioo->pos.z;
return TRUE;
}
}
}
}
}
pos->x = io->pos.x;
pos->y = io->pos.y;
pos->z = io->pos.z;
return TRUE;
}
//*************************************************************************************
// void RemoveFromAllInventories(INTERACTIVE_OBJ * io)
//-------------------------------------------------------------------------------------
// FUNCTION:
// Seeks an IO in all Inventories to remove it
//*************************************************************************************
void RemoveFromAllInventories(INTERACTIVE_OBJ * io)
{
if (!io) return;
long iNbBag, i, j, k;
INVENTORY_DATA * id;
long removed_count = 0;
// Seek IO in Player Inventory/ies
for (iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (j = 0; j < INVENTORY_Y; j++)
for (i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io == io)
{
inventory[iNbBag][i][j].io = NULL;
inventory[iNbBag][i][j].show = 1;
removed_count++;
}
}
// Seek IO in Other IO's Inventories
for (i = 0; i < inter.nbmax; i++)
{
if (inter.iobj[i] != NULL)
{
if (inter.iobj[i]->inventory != NULL)
{
id = (INVENTORY_DATA *)inter.iobj[i]->inventory;
for (j = 0; j < id->sizey; j++)
for (k = 0; k < id->sizex; k++)
{
if (id->slot[k][j].io == io)
{
id->slot[k][j].io = NULL;
id->slot[k][j].show = 1;
removed_count++;
}
}
}
}
}
}
//*************************************************************************************
// Seeks an IO in all Inventories to replace it by another IO
//*************************************************************************************
void CheckForInventoryReplaceMe(INTERACTIVE_OBJ * io, INTERACTIVE_OBJ * old)
{
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io == old)
{
if (CanBePutInInventory(io)) return;
PutInFrontOfPlayer(io, 1);
return;
}
}
for (long i = 0; i < inter.nbmax; i++)
{
if (inter.iobj[i] != NULL)
{
if (inter.iobj[i]->inventory != NULL)
{
INVENTORY_DATA * id = (INVENTORY_DATA *)inter.iobj[i]->inventory;
for (long j = 0; j < id->sizey; j++)
for (long k = 0; k < id->sizex; k++)
{
if (id->slot[k][j].io == old)
{
long xx, yy;
if (CanBePutInSecondaryInventory(id, io, &xx, &yy)) return;
PutInFrontOfPlayer(io, 1);
return;
}
}
}
}
}
}
void ReplaceInAllInventories(INTERACTIVE_OBJ * io, INTERACTIVE_OBJ * ioo)
{
if ((io == NULL) || (ioo == NULL)) return;
long i, j, k;
INVENTORY_DATA * id;
long ion = GetInterNum(io);
long ioon = GetInterNum(ioo);
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (j = 0; j < INVENTORY_Y; j++)
for (i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io == inter.iobj[ion])
{
inventory[iNbBag][i][j].io = inter.iobj[ioon];
}
}
for (i = 0; i < inter.nbmax; i++)
{
if ((inter.iobj[i] != NULL)
&& (inter.iobj[i] != inter.iobj[ion]))
{
if (inter.iobj[i]->inventory != NULL)
{
id = (INVENTORY_DATA *)inter.iobj[i]->inventory;
for (j = 0; j < id->sizey; j++)
for (k = 0; k < id->sizex; k++)
{
if (id->slot[k][j].io == inter.iobj[ion])
{
id->slot[k][j].io = inter.iobj[ioon];
}
}
}
}
}
}
//*************************************************************************************
// Takes an object from an inventory (be it player's or secondary inventory)
// at screen position "xx,yy"
// Puts that object in player's "hand" (cursor)
// returns TRUE if an object was taken FALSE elseway
//*************************************************************************************
BOOL TakeFromInventory(EERIE_S2D * pos)
{
long i, j;
INTERACTIVE_OBJ * io = GetFromInventory(pos);
INTERACTIVE_OBJ * ioo;
if (io == NULL) return FALSE;
if (SecondaryInventory != NULL)
{
if (InSecondaryInventoryPos(pos))
{
ioo = (INTERACTIVE_OBJ *)SecondaryInventory->io;
if (ioo->ioflags & IO_SHOP) // SHOP !
{
{
if (io->ioflags & IO_ITEM) // Just in case...
{
long cos = ARX_INTERACTIVE_GetPrice(io, ioo);
float fcos = cos - cos * ((float)player.Full_Skill_Intuition) * 0.005f;
ARX_CHECK_LONG(fcos);
cos = ARX_CLEAN_WARN_CAST_LONG(fcos);
if (player.gold < cos)
{
return FALSE;
}
ARX_SOUND_PlayInterface(SND_GOLD);
player.gold -= cos;
if (io->_itemdata->count > 1) // Multi-obj
{
ioo = CloneIOItem(io);
MakeTemporaryIOIdent(ioo);
ioo->show = SHOW_FLAG_NOT_DRAWN;
ioo->scriptload = 1;
ioo->_itemdata->count = 1;
io->_itemdata->count--;
ARX_SOUND_PlayInterface(SND_INVSTD);
Set_DragInter(ioo);
ARX_INVENTORY_Declare_Inventory_2_Out(ioo);
return TRUE;
}
}
}
}
else if ((io->ioflags & IO_ITEM) &&
(io->_itemdata->count > 1))
{
if (!ARX_IMPULSE_Pressed(CONTROLS_CUST_STEALTHMODE))
{
ioo = CloneIOItem(io);
MakeTemporaryIOIdent(ioo);
ioo->show = SHOW_FLAG_NOT_DRAWN;
ioo->scriptload = 1;
ioo->_itemdata->count = 1;
io->_itemdata->count--;
ARX_SOUND_PlayInterface(SND_INVSTD);
Set_DragInter(ioo);
sInventory = 2;
float fCalcX = (pos->x + InventoryX - INTERFACE_RATIO(2)) / INTERFACE_RATIO(32);
float fCalcY = (pos->y - INTERFACE_RATIO(13)) / INTERFACE_RATIO(32);
ARX_CHECK_SHORT(fCalcX);
ARX_CHECK_SHORT(fCalcY);
sInventoryX = ARX_CLEAN_WARN_CAST_SHORT(fCalcX);
sInventoryY = ARX_CLEAN_WARN_CAST_SHORT(fCalcY);
//ARX_INVENTORY_Object_Out(SecondaryInventory->io, ioo);
ARX_INVENTORY_Declare_Inventory_2_Out(ioo);
ARX_INVENTORY_IdentifyIO(ioo);
return TRUE;
}
}
}
for (j = 0; j < SecondaryInventory->sizey; j++)
for (i = 0; i < SecondaryInventory->sizex; i++)
{
if (SecondaryInventory->slot[i][j].io == io)
{
SecondaryInventory->slot[i][j].io = NULL;
SecondaryInventory->slot[i][j].show = 1;
sInventory = 2;
float fCalcX = (pos->x + InventoryX - INTERFACE_RATIO(2)) / INTERFACE_RATIO(32);
float fCalcY = (pos->y - INTERFACE_RATIO(13)) / INTERFACE_RATIO(32);
ARX_CHECK_SHORT(fCalcX);
ARX_CHECK_SHORT(fCalcY);
sInventoryX = ARX_CLEAN_WARN_CAST_SHORT(fCalcX);
sInventoryY = ARX_CLEAN_WARN_CAST_SHORT(fCalcY);
}
}
}
float fCenterX = DANAECENTERX - INTERFACE_RATIO(320) + INTERFACE_RATIO(35);
float fSizY = DANAESIZY - INTERFACE_RATIO(101) + INTERFACE_RATIO_LONG(InventoryY);
ARX_CHECK_INT(fCenterX);
ARX_CHECK_INT(fSizY);
int iPosX = ARX_CLEAN_WARN_CAST_INT(fCenterX);
int iPosY = ARX_CLEAN_WARN_CAST_INT(fSizY);
long inplayer = 0;
if (InPlayerInventoryPos(pos))
{
inplayer = 1;
{
if (!ARX_IMPULSE_Pressed(CONTROLS_CUST_STEALTHMODE))
if ((io->ioflags & IO_ITEM) && (io->_itemdata->count > 1)) // Multi-obj
{
if (io->_itemdata->count - 1 > 0)
{
ioo = AddItem(GDevice, io->filename);
MakeTemporaryIOIdent(ioo);
ioo->show = SHOW_FLAG_NOT_DRAWN;
ioo->_itemdata->count = 1;
io->_itemdata->count--;
ioo->scriptload = 1;
long ioon = GetInterNum(ioo);
ARX_SOUND_PlayInterface(SND_INVSTD);
Set_DragInter(inter.iobj[ioon]);
RemoveFromAllInventories(ioo);
sInventory = 1;
float fX = (pos->x - iPosX) / INTERFACE_RATIO(32);
float fY = (pos->y - iPosY) / INTERFACE_RATIO(32);
ARX_CHECK_SHORT(fX);
ARX_CHECK_SHORT(fY);
sInventoryX = ARX_CLEAN_WARN_CAST_SHORT(fX);
sInventoryY = ARX_CLEAN_WARN_CAST_SHORT(fY);
SendInitScriptEvent(ioo);
ARX_INVENTORY_Declare_InventoryOut(ioo);
ARX_INVENTORY_IdentifyIO(ioo);
return TRUE;
}
}
}
}
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (j = 0; j < INVENTORY_Y; j++)
for (i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io == io)
{
inventory[iNbBag][i][j].io = NULL;
inventory[iNbBag][i][j].show = 1;
sInventory = 1;
float fX = (pos->x - iPosX) / INTERFACE_RATIO(32);
float fY = (pos->y - iPosY) / INTERFACE_RATIO(32);
ARX_CHECK_SHORT(fX);
ARX_CHECK_SHORT(fY);
sInventoryX = ARX_CLEAN_WARN_CAST_SHORT(fX);
sInventoryY = ARX_CLEAN_WARN_CAST_SHORT(fY);
}
}
Set_DragInter(io);
ARX_INVENTORY_Declare_InventoryOut(io);
RemoveFromAllInventories(io);
ARX_INVENTORY_IdentifyIO(io);
return TRUE;
}
//-----------------------------------------------------------------------------
BOOL IsInPlayerInventory(INTERACTIVE_OBJ * io)
{
for (long iNbBag = 0; iNbBag < player.bag; iNbBag ++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io == io)
{
return TRUE;
}
}
return FALSE;
}
//-----------------------------------------------------------------------------
BOOL IsInSecondaryInventory(INTERACTIVE_OBJ * io)
{
if (SecondaryInventory)
{
for (long j = 0; j < SecondaryInventory->sizey; j++)
for (long i = 0; i < SecondaryInventory->sizex; i++)
{
if (SecondaryInventory->slot[i][j].io == io)
{
return TRUE;
}
}
}
return FALSE;
}
//-----------------------------------------------------------------------------
void SendInventoryObjectCommand(char * _lpszText, long _lCommand)
{
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
if ((inventory[iNbBag][i][j].io)
&& (inventory[iNbBag][i][j].io->obj))
for (long lTex = 0; lTex < inventory[iNbBag][i][j].io->obj->nbmaps; lTex++)
{
if (inventory[iNbBag][i][j].io->obj->texturecontainer)
{
if (inventory[iNbBag][i][j].io->obj->texturecontainer[lTex])
{
if (strcmp(inventory[iNbBag][i][j].io->obj->texturecontainer[lTex]->m_texName, _lpszText) == 0)
{
if (inventory[iNbBag][i][j].io->GameFlags & GFLAG_INTERACTIVITY)
SendIOScriptEvent(inventory[iNbBag][i][j].io, _lCommand, "");
return;
}
}
}
}
}
}
//-----------------------------------------------------------------------------
INTERACTIVE_OBJ * ARX_INVENTORY_GetTorchLowestDurability()
{
INTERACTIVE_OBJ * io = NULL;
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
if (inventory[iNbBag][i][j].io)
{
if (strcmp(inventory[iNbBag][i][j].io->locname, "[description_torch]") == 0)
{
if (!io)
{
io = inventory[iNbBag][i][j].io;
}
else
{
if (inventory[iNbBag][i][j].io->durability < io->durability)
{
io = inventory[iNbBag][i][j].io;
}
}
}
}
}
return io;
}
//-----------------------------------------------------------------------------
void ARX_INVENTORY_IdentifyIO(INTERACTIVE_OBJ * _pIO)
{
if (_pIO)
{
if ((_pIO) && (_pIO->ioflags & IO_ITEM) && _pIO->_itemdata->equipitem)
{
if (player.Full_Skill_Object_Knowledge + player.Full_Attribute_Mind
>= _pIO->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_Identify_Value].value)
{
SendIOScriptEvent(_pIO, SM_IDENTIFY, "");
}
}
}
}
//-----------------------------------------------------------------------------
void ARX_INVENTORY_IdentifyAll()
{
INTERACTIVE_OBJ * io = NULL;
if (player.bag)
for (int iNbBag = 0; iNbBag < player.bag; iNbBag++)
for (long j = 0; j < INVENTORY_Y; j++)
for (long i = 0; i < INVENTORY_X; i++)
{
io = inventory[iNbBag][i][j].io;
if ((io) && (io->ioflags & IO_ITEM) && io->_itemdata->equipitem)
{
if (player.Full_Skill_Object_Knowledge + player.Full_Attribute_Mind
>= io->_itemdata->equipitem->elements[IO_EQUIPITEM_ELEMENT_Identify_Value].value)
{
SendIOScriptEvent(io, SM_IDENTIFY, "");
}
}
}
}
extern bool bInventoryClosing;
//-----------------------------------------------------------------------------
void ARX_INVENTORY_OpenClose(INTERACTIVE_OBJ * _io)
{
if ((_io && (SecondaryInventory == _io->inventory)) || (_io == NULL)) // CLOSING
{
if (SecondaryInventory && (SecondaryInventory->io != NULL))
SendIOScriptEvent((INTERACTIVE_OBJ *)SecondaryInventory->io, SM_INVENTORY2_CLOSE, "");
InventoryDir = -1;
TSecondaryInventory = SecondaryInventory;
SecondaryInventory = NULL;
EERIEMouseButton &= ~4;
if (DRAGGING) DRAGGING = 0;
}
else
{
if (TSecondaryInventory
&& TSecondaryInventory->io) SendIOScriptEvent((INTERACTIVE_OBJ *)TSecondaryInventory->io, SM_INVENTORY2_CLOSE, "");
InventoryDir = 1;
TSecondaryInventory = SecondaryInventory = (INVENTORY_DATA *)_io->inventory;
if (SecondaryInventory && SecondaryInventory->io != NULL)
{
if (SendIOScriptEvent((INTERACTIVE_OBJ *)SecondaryInventory->io, SM_INVENTORY2_OPEN, "") == REFUSE)
{
InventoryDir = -1;
TSecondaryInventory = SecondaryInventory = NULL;
return;
}
}
if (player.Interface & INTER_COMBATMODE)
{
ARX_INTERFACE_Combat_Mode(0);
}
if (pMenuConfig->bAutoReadyWeapon == false)
{
TRUE_PLAYER_MOUSELOOK_ON &= ~1;
}
if (SecondaryInventory && SecondaryInventory->io
&& (SecondaryInventory->io->ioflags & IO_SHOP))
ARX_INVENTORY_ReOrder();
EERIEMouseButton &= ~4;
if (DRAGGING) DRAGGING = 0;
}
if (player.Interface & INTER_INVENTORYALL)
{
ARX_SOUND_PlayInterface(SND_BACKPACK, 0.9F + 0.2F * rnd());
bInventoryClosing = true;
}
}
//-----------------------------------------------------------------------------
void ARX_INVENTORY_TakeAllFromSecondaryInventory()
{
bool bSound = false;
if (TSecondaryInventory)
{
ARX_CHECK_SHORT(TSecondaryInventory->sizey);
ARX_CHECK_SHORT(TSecondaryInventory->sizex);
for (long j = 0; j < TSecondaryInventory->sizey; j++)
for (long i = 0; i < TSecondaryInventory->sizex; i++)
{
if (TSecondaryInventory->slot[i][j].io && TSecondaryInventory->slot[i][j].show)
{
long sx = TSecondaryInventory->slot[i][j].io->sizex;
long sy = TSecondaryInventory->slot[i][j].io->sizey;
INTERACTIVE_OBJ * io = TSecondaryInventory->slot[i][j].io;
if (!(io->ioflags & IO_GOLD))
RemoveFromAllInventories(io);
if (CanBePutInInventory(io))
{
bSound = true;
}
else
{
sInventory = 2;
sInventoryX = ARX_CLEAN_WARN_CAST_SHORT(i);
sInventoryY = ARX_CLEAN_WARN_CAST_SHORT(j);
sx = i;
sy = j;
CanBePutInSecondaryInventory(TSecondaryInventory, io, &sx, &sy);
}
}
}
}
if (bSound)
ARX_SOUND_PlayInterface(SND_INVSTD);
else
ARX_SOUND_PlayInterface(SND_INVSTD, 0.1f);
}
//-----------------------------------------------------------------------------
void ARX_INVENTORY_ReOrder()
{
if (TSecondaryInventory)
{
ARX_CHECK_SHORT(TSecondaryInventory->sizey);
ARX_CHECK_SHORT(TSecondaryInventory->sizex);
for (long j = 0; j < TSecondaryInventory->sizey; j++)
for (long i = 0; i < TSecondaryInventory->sizex; i++)
{
if (TSecondaryInventory->slot[i][j].io && TSecondaryInventory->slot[i][j].show)
{
long sx = TSecondaryInventory->slot[i][j].io->sizex;
long sy = TSecondaryInventory->slot[i][j].io->sizey;
INTERACTIVE_OBJ * io = TSecondaryInventory->slot[i][j].io;
RemoveFromAllInventories(io);
long x, y;
sInventory = 2;
sInventoryX = 0;
sInventoryY = 0;
if (CanBePutInSecondaryInventory(TSecondaryInventory, io, &x, &y))
{
}
else
{
sInventory = 2;
sInventoryX = ARX_CLEAN_WARN_CAST_SHORT(i);
sInventoryY = ARX_CLEAN_WARN_CAST_SHORT(j);
sx = i;
sy = j;
CanBePutInSecondaryInventory(TSecondaryInventory, io, &sx, &sy);
}
}
}
}
}