mirror of
https://github.com/1dot13/source.git
synced 2026-07-22 13:40:22 +02:00
- items now have an internal repair value that can be lowered through damage taken. They can only be repaired up to that value by your mercs, onyl smiths can fully restore it to 100% - guns get dirty over time, especially when shooting. Thsi can cause them to jam. Use cleaning kits (item #1576) to clean them by pressing 'Alt' + '.' - more on this feature in http://www.bears-pit.com/board/ubbthreads.php/topics/308926/New_feature_advanced_repair_di.html#Post308926 - this requires GameDir revision 1496 or higher WARING! THIS BREAKS SAVEGAME COMPATIBIITY! git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5480 3b4a5df2-a311-0410-b5c6-a8a6f20db521
1695 lines
48 KiB
C++
1695 lines
48 KiB
C++
#ifdef PRECOMPILEDHEADERS
|
|
#include "Editor All.h"
|
|
#else
|
|
#include "builddefines.h"
|
|
#endif
|
|
|
|
#ifdef JA2EDITOR
|
|
|
|
#ifndef PRECOMPILEDHEADERS
|
|
#include <windows.h>
|
|
#include "tiledef.h"
|
|
#include "edit_sys.h"
|
|
#include "vsurface.h"
|
|
#include "vobject.h"
|
|
#include "mousesystem.h"
|
|
#include "Button System.h"
|
|
#include "wcheck.h"
|
|
#include "vsurface.h"
|
|
#include "input.h"
|
|
#include "sysutil.h"
|
|
#include "font.h"
|
|
#include "Font Control.h"
|
|
#include "editscreen.h"
|
|
#include "selectwin.h"
|
|
#include "video.h"
|
|
#include "vobject_blitters.h"
|
|
#include "interface panels.h"
|
|
#include "interface items.h"
|
|
#include "text.h"
|
|
#include "utilities.h"
|
|
#include "Action Items.h"
|
|
#include "World Items.h"
|
|
#include "EditorDefines.h"
|
|
#include "EditorItems.h"
|
|
#include "EditorMercs.h"
|
|
#include "weapons.h"
|
|
#include "Editor Taskbar Utils.h"
|
|
#include "wordwrap.h"
|
|
#include "Item Statistics.h"
|
|
#include "Simple Render Utils.h"
|
|
#include "worldman.h"
|
|
#include "random.h"
|
|
#include "Pits.h"
|
|
#include "keys.h"
|
|
#include "InterfaceItemImages.h"
|
|
#endif
|
|
|
|
#include <vfs/Tools/vfs_log.h>
|
|
|
|
#define NUMBER_TRIGGERS 27
|
|
#define PRESSURE_ACTION_ID (NUMBER_TRIGGERS - 1)
|
|
|
|
extern ITEM_POOL *gpEditingItemPool;
|
|
|
|
//Simply counts the number of items in the world. This is used for display purposes.
|
|
UINT16 CountNumberOfEditorPlacementsInWorld( UINT16 usEInfoIndex, UINT16 *pusQuantity ); //wrapper for the next three
|
|
UINT16 CountNumberOfItemPlacementsInWorld( UINT16 usItem, UINT16 *pusQuantity );
|
|
UINT16 CountNumberOfItemsWithFrequency( UINT16 usItem, INT8 bFrequency );
|
|
UINT16 CountNumberOfPressureActionsInWorld();
|
|
UINT16 CountNumberOfKeysOfTypeInWorld( UINT8 ubKeyID );
|
|
|
|
//Finds and selects the next item when right clicking on an item type. Only works if the
|
|
//item actually exists in the world.
|
|
void FindNextItemOfSelectedType(); //wrapper for the next four
|
|
void SelectNextTriggerWithFrequency( UINT16 usItem, INT8 bFrequency );
|
|
void SelectNextItemOfType( UINT16 usItem );
|
|
void SelectNextPressureAction();
|
|
void SelectNextKeyOfType( UINT8 ubKeyID );
|
|
|
|
INT32 giDefaultExistChance = 100;
|
|
|
|
typedef struct IPListNode
|
|
{
|
|
INT32 sGridNo;
|
|
struct IPListNode *next;
|
|
}IPListNode;
|
|
|
|
IPListNode *pIPHead = NULL;
|
|
|
|
IPListNode *gpCurrItemPoolNode = NULL;
|
|
ITEM_POOL *gpItemPool = NULL;
|
|
|
|
void BuildItemPoolList()
|
|
{
|
|
ITEM_POOL *temp;
|
|
IPListNode *tail = NULL;
|
|
INT32 i;
|
|
KillItemPoolList();
|
|
for( i = 0; i < WORLD_MAX; i++ )
|
|
{
|
|
if( GetItemPoolFromGround( i, &temp ) )
|
|
{
|
|
if( !pIPHead )
|
|
{
|
|
pIPHead = (IPListNode*)MemAlloc( sizeof( IPListNode ) );
|
|
Assert( pIPHead );
|
|
tail = pIPHead;
|
|
}
|
|
else
|
|
{
|
|
tail->next = (IPListNode*)MemAlloc( sizeof( IPListNode ) );
|
|
Assert( tail->next );
|
|
tail = tail->next;
|
|
}
|
|
ShowItemCursor( i );
|
|
tail->sGridNo = i;
|
|
tail->next = NULL;
|
|
}
|
|
}
|
|
gpCurrItemPoolNode = pIPHead;
|
|
SpecifyItemToEdit( NULL, -1 );
|
|
}
|
|
|
|
void KillItemPoolList()
|
|
{
|
|
IPListNode *pIPCurr;
|
|
pIPCurr = pIPHead;
|
|
while( pIPCurr )
|
|
{
|
|
if(pIPCurr->sGridNo < WORLD_MAX)//dnl ch43 280909 Prevent CTD when world size is changed
|
|
HideItemCursor(pIPCurr->sGridNo);
|
|
pIPHead = pIPHead->next;
|
|
MemFree( pIPCurr );
|
|
pIPCurr = pIPHead;
|
|
}
|
|
pIPHead = NULL;
|
|
}
|
|
|
|
//Contains global information about the editor items
|
|
//May be expanded to encapsulate the entire editor later.
|
|
EditorItemsInfo eInfo;
|
|
|
|
//Does some precalculations regarding the number of each item type, so that it
|
|
//isn't calculated every time a player changes categories.
|
|
void EntryInitEditorItemsInfo()
|
|
{
|
|
INT32 i;
|
|
INVTYPE *item;
|
|
eInfo.uiBuffer = 0;
|
|
eInfo.fKill = 0;
|
|
eInfo.fActive = 0;
|
|
eInfo.sWidth = 0;
|
|
eInfo.sHeight = 0;
|
|
eInfo.sScrollIndex = 0;
|
|
eInfo.sSelItemIndex = 0;
|
|
eInfo.sHilitedItemIndex = -1;
|
|
eInfo.sNumItems = 0;
|
|
eInfo.pusItemIndex = NULL;
|
|
if( eInfo.fGameInit )
|
|
{ //This only gets called one time in game execution.
|
|
memset( &eInfo, 0, sizeof( EditorItemsInfo ) );
|
|
eInfo.sHilitedItemIndex = -1;
|
|
eInfo.uiItemType = TBAR_MODE_ITEM_WEAPONS;
|
|
//Pre-calculate the number of each item type.
|
|
eInfo.sNumTriggers = NUMBER_TRIGGERS;
|
|
for( i=0; i < MAXITEMS; i++ )
|
|
{
|
|
if ( Item[i].usItemClass == 0 )
|
|
break;
|
|
item = &Item[i];
|
|
//if( Item[i].fFlags & ITEM_NOT_EDITOR )
|
|
// continue;
|
|
if(item->notineditor)
|
|
continue;
|
|
if( i == SWITCH || i == ACTION_ITEM )
|
|
{
|
|
|
|
}
|
|
else switch( item->usItemClass )
|
|
{
|
|
case IC_GUN:
|
|
case IC_BLADE:
|
|
case IC_THROWN:
|
|
case IC_LAUNCHER:
|
|
case IC_THROWING_KNIFE:
|
|
eInfo.sNumWeapons++;
|
|
break;
|
|
case IC_PUNCH:
|
|
if ( i != NOTHING )
|
|
{
|
|
eInfo.sNumWeapons++;
|
|
}
|
|
break;
|
|
case IC_AMMO:
|
|
eInfo.sNumAmmo++;
|
|
break;
|
|
case IC_ARMOUR:
|
|
eInfo.sNumArmour++;
|
|
break;
|
|
case IC_LBEGEAR:
|
|
eInfo.sLBEGear++;
|
|
break;
|
|
case IC_GRENADE:
|
|
case IC_BOMB:
|
|
eInfo.sNumExplosives++;
|
|
break;
|
|
case IC_MEDKIT:
|
|
case IC_KIT:
|
|
case IC_FACE:
|
|
case IC_MONEY:
|
|
case IC_BELTCLIP:
|
|
eInfo.sNumEquipment1++;
|
|
break;
|
|
case IC_MISC:
|
|
if( eInfo.sNumEquipment2 < eInfo.sNumEquipment3 )
|
|
eInfo.sNumEquipment2++;
|
|
else
|
|
eInfo.sNumEquipment3++;
|
|
break;
|
|
//case IC_KEY:
|
|
// eInfo.sNumKeys++;
|
|
// break;
|
|
}
|
|
}
|
|
eInfo.sNumKeys = NUM_KEYS;
|
|
}
|
|
}
|
|
|
|
void InitEditorItemsInfo(UINT32 uiItemType)
|
|
{
|
|
VSURFACE_DESC vs_desc;
|
|
UINT8 *pDestBuf, *pSrcBuf;
|
|
UINT32 uiSrcPitchBYTES, uiDestPitchBYTES;
|
|
INVTYPE *item;
|
|
SGPRect SaveRect, NewRect;
|
|
HVOBJECT hVObject;
|
|
UINT32 uiVideoObjectIndex;
|
|
UINT16 usUselessWidth, usUselessHeight;
|
|
INT16 sWidth, sOffset, sStart;
|
|
INT16 i, x, y;
|
|
UINT16 usCounter;
|
|
CHAR16 pStr[ 100 ];//, pStr2[ 100 ];
|
|
CHAR16 pItemName[SIZE_ITEM_NAME];
|
|
UINT8 ubBitDepth;
|
|
BOOLEAN fTypeMatch;
|
|
INT32 iEquipCount = 0;
|
|
|
|
// Check to make sure that there isn't already a valid eInfo
|
|
if( eInfo.fActive )
|
|
{
|
|
if( eInfo.uiItemType == uiItemType )
|
|
{ //User clicked on the same item classification -- ignore
|
|
return;
|
|
}
|
|
else
|
|
{ //User selected a different item classification -- delete it first.
|
|
ClearEditorItemsInfo();
|
|
ClearTaskbarRegion( iScreenWidthOffset + 100, 2 * iScreenHeightOffset + 360, iScreenWidthOffset + 480, 2 * iScreenHeightOffset + 440 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Clear the menu area, so that the buffer doesn't get corrupted.
|
|
ClearTaskbarRegion( iScreenWidthOffset + 100, 2 * iScreenHeightOffset + 360, iScreenWidthOffset + 480, 2 * iScreenHeightOffset + 440 );
|
|
}
|
|
EnableEditorRegion( ITEM_REGION_ID );
|
|
|
|
eInfo.uiItemType = uiItemType;
|
|
eInfo.fActive = TRUE;
|
|
//Begin initialization of data.
|
|
switch(uiItemType)
|
|
{
|
|
case TBAR_MODE_ITEM_WEAPONS:
|
|
eInfo.sNumItems = eInfo.sNumWeapons;
|
|
eInfo.sScrollIndex = eInfo.sSaveWeaponsScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelWeaponsIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_AMMO:
|
|
eInfo.sNumItems = eInfo.sNumAmmo;
|
|
eInfo.sScrollIndex = eInfo.sSaveAmmoScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelAmmoIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_ARMOUR:
|
|
eInfo.sNumItems = eInfo.sNumArmour;
|
|
eInfo.sScrollIndex = eInfo.sSaveArmourScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelArmourIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_LBEGEAR:
|
|
eInfo.sNumItems = eInfo.sLBEGear;
|
|
eInfo.sScrollIndex = eInfo.sSaveLBEScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelLBEIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_EXPLOSIVES:
|
|
eInfo.sNumItems = eInfo.sNumExplosives;
|
|
eInfo.sScrollIndex = eInfo.sSaveExplosivesScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelExplosivesIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_EQUIPMENT1:
|
|
eInfo.sNumItems = eInfo.sNumEquipment1;
|
|
eInfo.sScrollIndex = eInfo.sSaveEquipment1ScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelEquipment1Index;
|
|
break;
|
|
case TBAR_MODE_ITEM_EQUIPMENT2:
|
|
eInfo.sNumItems = eInfo.sNumEquipment2;
|
|
eInfo.sScrollIndex = eInfo.sSaveEquipment2ScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelEquipment2Index;
|
|
break;
|
|
case TBAR_MODE_ITEM_EQUIPMENT3:
|
|
eInfo.sNumItems = eInfo.sNumEquipment3;
|
|
eInfo.sScrollIndex = eInfo.sSaveEquipment3ScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelEquipment3Index;
|
|
break;
|
|
case TBAR_MODE_ITEM_TRIGGERS:
|
|
eInfo.sNumItems = eInfo.sNumTriggers;
|
|
eInfo.sScrollIndex = eInfo.sSaveTriggersScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelTriggersIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_KEYS:
|
|
eInfo.sNumItems = eInfo.sNumKeys;
|
|
eInfo.sScrollIndex = eInfo.sSaveKeysScrollIndex;
|
|
eInfo.sSelItemIndex = eInfo.sSaveSelKeysIndex;
|
|
break;
|
|
default:
|
|
//error
|
|
return;
|
|
}
|
|
//Allocate memory to store all the item pointers.
|
|
eInfo.pusItemIndex = (UINT16*)MemAlloc( sizeof(UINT16) * eInfo.sNumItems );
|
|
|
|
//Disable the appropriate scroll buttons based on the saved scroll index if applicable
|
|
//Left most scroll position
|
|
DetermineItemsScrolling();
|
|
//calculate the width of the buffer based on the number of items.
|
|
//every pair of items (odd rounded up) requires 60 pixels for width.
|
|
//the minimum buffer size is 420. Height is always 80 pixels.
|
|
|
|
eInfo.sWidth = (eInfo.sNumItems > 12) ? ((eInfo.sNumItems+1)/2)*60 : SCREEN_HEIGHT - 120;
|
|
eInfo.sHeight = 80;
|
|
// Create item buffer
|
|
GetCurrentVideoSettings( &usUselessWidth, &usUselessHeight, &ubBitDepth );
|
|
vs_desc.fCreateFlags = VSURFACE_CREATE_DEFAULT | VSURFACE_SYSTEM_MEM_USAGE;
|
|
vs_desc.usWidth = eInfo.sWidth;
|
|
vs_desc.usHeight = eInfo.sHeight;
|
|
vs_desc.ubBitDepth = ubBitDepth;
|
|
|
|
//!!!Memory check. Create the item buffer
|
|
if(!AddVideoSurface( &vs_desc, &eInfo.uiBuffer ))
|
|
{
|
|
eInfo.fKill = TRUE;
|
|
eInfo.fActive = FALSE;
|
|
return;
|
|
}
|
|
|
|
pDestBuf = LockVideoSurface(eInfo.uiBuffer, &uiDestPitchBYTES);
|
|
pSrcBuf = LockVideoSurface(FRAME_BUFFER, &uiSrcPitchBYTES);
|
|
|
|
//copy a blank chunk of the editor interface to the new buffer.
|
|
for( i=0; i<eInfo.sWidth; i+=60 )
|
|
{
|
|
Blt16BPPTo16BPP((UINT16 *)pDestBuf, uiDestPitchBYTES,
|
|
(UINT16 *)pSrcBuf, uiSrcPitchBYTES, 0+i, 0, iScreenWidthOffset + 100, 2 * iScreenHeightOffset + 360, 60, 80 );
|
|
}
|
|
|
|
UnLockVideoSurface(eInfo.uiBuffer);
|
|
UnLockVideoSurface(FRAME_BUFFER);
|
|
|
|
x = 0;
|
|
y = 0;
|
|
usCounter = 0;
|
|
NewRect.iTop = 0;
|
|
NewRect.iBottom = eInfo.sHeight;
|
|
NewRect.iLeft = 0;
|
|
NewRect.iRight = eInfo.sWidth;
|
|
GetClippingRect(&SaveRect);
|
|
SetClippingRect(&NewRect);
|
|
if( eInfo.uiItemType == TBAR_MODE_ITEM_KEYS )
|
|
{ //Keys use a totally different method for determining
|
|
for( i = 0; i < eInfo.sNumItems; i++ )
|
|
{
|
|
item = &Item[ KeyTable[ 0 ].usItem + LockTable[ i ].usKeyItem ];
|
|
uiVideoObjectIndex = GetInterfaceGraphicForItem( item );
|
|
GetVideoObject( &hVObject, uiVideoObjectIndex );
|
|
|
|
//Store these item pointers for later when rendering selected items.
|
|
eInfo.pusItemIndex[i] = KeyTable[ 0 ].usItem + LockTable[ i ].usKeyItem;
|
|
|
|
SetFont(SMALLCOMPFONT);
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
SetFontDestBuffer( eInfo.uiBuffer, 0, 0, eInfo.sWidth, eInfo.sHeight, FALSE );
|
|
|
|
swprintf( pStr, L"%S", LockTable[ i ].ubEditorName );
|
|
DisplayWrappedString(x, (UINT16)(y+25), 60, 2, SMALLCOMPFONT, FONT_WHITE, pStr, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
|
|
|
|
UINT16 usGraphicNum = g_bUsePngItemImages ? 0 : item->ubGraphicNum;
|
|
//Calculate the center position of the graphic in a 60 pixel wide area.
|
|
sWidth = hVObject->pETRLEObject[usGraphicNum].usWidth;
|
|
sOffset = hVObject->pETRLEObject[usGraphicNum].sOffsetX;
|
|
sStart = x + (60 - sWidth - sOffset*2) / 2;
|
|
|
|
BltVideoObjectOutlineFromIndex( eInfo.uiBuffer, uiVideoObjectIndex, usGraphicNum, sStart, y+2, 0, FALSE );
|
|
|
|
//cycle through the various slot positions (0,0), (0,40), (60,0), (60,40), (120,0)...
|
|
if( y == 0 )
|
|
{
|
|
y = 40;
|
|
}
|
|
else
|
|
{
|
|
y = 0;
|
|
x += 60;
|
|
}
|
|
}
|
|
}
|
|
else for( i = 0; i < eInfo.sNumItems; i++ )
|
|
{
|
|
|
|
fTypeMatch = FALSE;
|
|
while( usCounter<MAXITEMS && !fTypeMatch )
|
|
{
|
|
if ( Item[usCounter].usItemClass == 0 )
|
|
break;
|
|
item = &Item[usCounter];
|
|
//if( Item[usCounter].fFlags & ITEM_NOT_EDITOR )
|
|
if(item->notineditor)
|
|
{
|
|
usCounter++;
|
|
continue;
|
|
}
|
|
if( eInfo.uiItemType == TBAR_MODE_ITEM_TRIGGERS )
|
|
{
|
|
if( i < PRESSURE_ACTION_ID )
|
|
usCounter = ( i % 2 ) ? ACTION_ITEM : SWITCH;
|
|
else
|
|
usCounter = ACTION_ITEM;
|
|
fTypeMatch = TRUE;
|
|
item = &Item[usCounter];
|
|
}
|
|
else switch( item->usItemClass )
|
|
{
|
|
case IC_GUN:
|
|
case IC_BLADE:
|
|
case IC_LAUNCHER:
|
|
case IC_THROWN:
|
|
case IC_THROWING_KNIFE:
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_WEAPONS;
|
|
break;
|
|
case IC_PUNCH:
|
|
if ( i != NOTHING )
|
|
{
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_WEAPONS;
|
|
}
|
|
else
|
|
{
|
|
fTypeMatch = FALSE;
|
|
}
|
|
break;
|
|
case IC_AMMO:
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_AMMO;
|
|
break;
|
|
case IC_ARMOUR:
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_ARMOUR;
|
|
break;
|
|
case IC_LBEGEAR:
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_LBEGEAR;
|
|
break;
|
|
case IC_GRENADE:
|
|
case IC_BOMB:
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_EXPLOSIVES;
|
|
break;
|
|
case IC_MEDKIT:
|
|
case IC_KIT:
|
|
case IC_FACE:
|
|
case IC_MONEY:
|
|
case IC_BELTCLIP:
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_EQUIPMENT1;
|
|
break;
|
|
case IC_MISC:
|
|
if( usCounter == ACTION_ITEM || usCounter == SWITCH )
|
|
break;
|
|
if( iEquipCount < eInfo.sNumEquipment2 )
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_EQUIPMENT2;
|
|
else
|
|
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_EQUIPMENT3;
|
|
iEquipCount++;
|
|
break;
|
|
}
|
|
if( fTypeMatch )
|
|
{
|
|
|
|
uiVideoObjectIndex = GetInterfaceGraphicForItem( item );
|
|
GetVideoObject( &hVObject, uiVideoObjectIndex );
|
|
|
|
//Store these item pointers for later when rendering selected items.
|
|
eInfo.pusItemIndex[i] = usCounter;
|
|
|
|
SetFont(SMALLCOMPFONT);
|
|
SetFontForeground( FONT_MCOLOR_WHITE );
|
|
SetFontDestBuffer( eInfo.uiBuffer, 0, 0, eInfo.sWidth, eInfo.sHeight, FALSE );
|
|
|
|
|
|
if( eInfo.uiItemType != TBAR_MODE_ITEM_TRIGGERS )
|
|
{
|
|
LoadItemInfo( usCounter, pItemName, NULL );
|
|
swprintf( pStr, L"%s", pItemName );
|
|
}
|
|
else
|
|
{
|
|
if( i == PRESSURE_ACTION_ID )
|
|
{
|
|
swprintf( pStr, pInitEditorItemsInfoText[0] );
|
|
}
|
|
else if( i < 2 )
|
|
{
|
|
if( usCounter == SWITCH )
|
|
swprintf( pStr, pInitEditorItemsInfoText[5] );
|
|
else
|
|
swprintf( pStr, pInitEditorItemsInfoText[1] );
|
|
}
|
|
else if( i < 4 )
|
|
{
|
|
if( usCounter == SWITCH )
|
|
swprintf( pStr, pInitEditorItemsInfoText[6] );
|
|
else
|
|
swprintf( pStr, pInitEditorItemsInfoText[2] );
|
|
}
|
|
else if( i < 6 )
|
|
{
|
|
if( usCounter == SWITCH )
|
|
swprintf( pStr, pInitEditorItemsInfoText[7] );
|
|
else
|
|
swprintf( pStr, pInitEditorItemsInfoText[3] );
|
|
}
|
|
else
|
|
{
|
|
if( usCounter == SWITCH )
|
|
swprintf( pStr, pInitEditorItemsInfoText[8], (i-4)/2 );
|
|
else
|
|
swprintf( pStr, pInitEditorItemsInfoText[4], (i-4)/2 );
|
|
}
|
|
}
|
|
|
|
DisplayWrappedString(x, (UINT16)(y+25), 60, 2, SMALLCOMPFONT, FONT_WHITE, pStr, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
|
|
|
|
UINT16 usGraphicNum = g_bUsePngItemImages ? 0 : item->ubGraphicNum;
|
|
if(usGraphicNum < hVObject->usNumberOfObjects)
|
|
{
|
|
//Calculate the center position of the graphic in a 60 pixel wide area.
|
|
sWidth = hVObject->pETRLEObject[usGraphicNum].usWidth;
|
|
sOffset = hVObject->pETRLEObject[usGraphicNum].sOffsetX;
|
|
sStart = x + (60 - sWidth - sOffset*2) / 2;
|
|
|
|
if( sWidth && sWidth > 0 )
|
|
{
|
|
BltVideoObjectOutlineFromIndex( eInfo.uiBuffer, uiVideoObjectIndex, usGraphicNum, sStart, y+2, 0, FALSE );
|
|
}
|
|
|
|
//cycle through the various slot positions (0,0), (0,40), (60,0), (60,40), (120,0)...
|
|
if( y == 0 )
|
|
{
|
|
y = 40;
|
|
}
|
|
else
|
|
{
|
|
y = 0;
|
|
x += 60;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
static vfs::Log& editorLog = *vfs::Log::create(L"EditorItems.log");
|
|
editorLog << L"Tried to access item ["
|
|
<< item->ubGraphicNum << L"/" << hVObject->usNumberOfObjects
|
|
<< L"]" << vfs::Log::endl;
|
|
}
|
|
}
|
|
usCounter++;
|
|
}
|
|
}
|
|
SetFontDestBuffer( FRAME_BUFFER, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, FALSE );
|
|
SetClippingRect(&SaveRect);
|
|
gfRenderTaskbar = TRUE;
|
|
}
|
|
|
|
void DetermineItemsScrolling()
|
|
{
|
|
if( !eInfo.sScrollIndex )
|
|
DisableEditorButton( ITEMS_LEFTSCROLL );
|
|
else
|
|
EnableEditorButton( ITEMS_LEFTSCROLL );
|
|
//Right most scroll position. Calculated by taking every pair of numItems rounded up,
|
|
//and subtracting 7 (because a scroll index 0 is disabled if there are <=12 items,
|
|
//index 1 for <=14 items, index 2 for <=16 items...
|
|
if( eInfo.sScrollIndex == max( ((eInfo.sNumItems+1)/2)-6, 0 ) )
|
|
DisableEditorButton( ITEMS_RIGHTSCROLL );
|
|
else
|
|
EnableEditorButton( ITEMS_RIGHTSCROLL );
|
|
}
|
|
|
|
void RenderEditorItemsInfo()
|
|
{
|
|
UINT8 *pDestBuf, *pSrcBuf;
|
|
UINT32 uiSrcPitchBYTES, uiDestPitchBYTES;
|
|
INVTYPE *item;
|
|
HVOBJECT hVObject;
|
|
UINT32 uiVideoObjectIndex;
|
|
INT16 i;
|
|
INT16 minIndex, maxIndex;
|
|
INT16 sWidth, sOffset, sStart, x, y;
|
|
UINT16 usNumItems;
|
|
UINT16 usQuantity;
|
|
|
|
if(!eInfo.fActive)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( gusMouseXPos < (iScreenWidthOffset + 110) || gusMouseXPos > (iScreenWidthOffset + 480) || gusMouseYPos < (2 * iScreenHeightOffset + 360) || gusMouseYPos > (2 * iScreenHeightOffset + 440) )
|
|
{ //Mouse has moved out of the items display region -- so nothing can be highlighted.
|
|
eInfo.sHilitedItemIndex = -1;
|
|
}
|
|
pDestBuf = LockVideoSurface(FRAME_BUFFER, &uiDestPitchBYTES);
|
|
pSrcBuf = LockVideoSurface(eInfo.uiBuffer, &uiSrcPitchBYTES);
|
|
|
|
Blt16BPPTo16BPP((UINT16 *)pDestBuf, uiDestPitchBYTES,
|
|
(UINT16 *)pSrcBuf, uiSrcPitchBYTES, iScreenWidthOffset + 110, 2 * iScreenHeightOffset + 360, 60*eInfo.sScrollIndex, 0, 360, 80 );
|
|
|
|
UnLockVideoSurface(eInfo.uiBuffer);
|
|
UnLockVideoSurface(FRAME_BUFFER);
|
|
|
|
//calculate the min and max index that is currently shown. This determines
|
|
//if the highlighted and/or selected items are drawn with the outlines.
|
|
minIndex = eInfo.sScrollIndex * 2;
|
|
maxIndex = minIndex + 11;
|
|
|
|
//draw the hilighted item if applicable.
|
|
if( eInfo.sHilitedItemIndex >= minIndex && eInfo.sHilitedItemIndex <= maxIndex )
|
|
{
|
|
if( eInfo.pusItemIndex )
|
|
{
|
|
item = &Item[eInfo.pusItemIndex[eInfo.sHilitedItemIndex]];
|
|
uiVideoObjectIndex = GetInterfaceGraphicForItem( item );
|
|
GetVideoObject( &hVObject, uiVideoObjectIndex );
|
|
|
|
x = iScreenWidthOffset + (eInfo.sHilitedItemIndex/2 - eInfo.sScrollIndex)*60 + 110;
|
|
y = 2 * iScreenHeightOffset + 360 + (eInfo.sHilitedItemIndex % 2) * 40;
|
|
|
|
UINT16 usGraphicNum = g_bUsePngItemImages ? 0 : item->ubGraphicNum;
|
|
sWidth = hVObject->pETRLEObject[usGraphicNum].usWidth;
|
|
sOffset = hVObject->pETRLEObject[usGraphicNum].sOffsetX;
|
|
sStart = x + (60 - sWidth - sOffset*2) / 2;
|
|
if( sWidth )
|
|
{
|
|
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, usGraphicNum, sStart, y+2, Get16BPPColor(FROMRGB(250, 250, 0)), TRUE );
|
|
}
|
|
}
|
|
}
|
|
//draw the selected item
|
|
if( eInfo.sSelItemIndex >= minIndex && eInfo.sSelItemIndex <= maxIndex )
|
|
{
|
|
if( eInfo.pusItemIndex )
|
|
{
|
|
item = &Item[eInfo.pusItemIndex[eInfo.sSelItemIndex]];
|
|
uiVideoObjectIndex = GetInterfaceGraphicForItem( item );
|
|
GetVideoObject( &hVObject, uiVideoObjectIndex );
|
|
|
|
x = iScreenWidthOffset + (eInfo.sSelItemIndex/2 - eInfo.sScrollIndex)*60 + 110;
|
|
y = 2 * iScreenHeightOffset + 360 + (eInfo.sSelItemIndex % 2) * 40;
|
|
|
|
UINT16 usGraphicNum = g_bUsePngItemImages ? 0 : item->ubGraphicNum;
|
|
sWidth = hVObject->pETRLEObject[usGraphicNum].usWidth;
|
|
sOffset = hVObject->pETRLEObject[usGraphicNum].sOffsetX;
|
|
sStart = x + (60 - sWidth - sOffset*2) / 2;
|
|
if( sWidth )
|
|
{
|
|
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, usGraphicNum, sStart, y+2, Get16BPPColor(FROMRGB(250, 0, 0)), TRUE );
|
|
}
|
|
}
|
|
}
|
|
//draw the numbers of each visible item that currently resides in the world.
|
|
maxIndex = min( maxIndex, eInfo.sNumItems-1 );
|
|
for( i = minIndex; i <= maxIndex; i++ )
|
|
{
|
|
usNumItems = CountNumberOfEditorPlacementsInWorld( i, &usQuantity );
|
|
if( usNumItems )
|
|
{
|
|
x = iScreenWidthOffset + (i/2 - eInfo.sScrollIndex)*60 + 110;
|
|
y = 2 * iScreenHeightOffset + 360 + (i % 2) * 40;
|
|
SetFont( FONT10ARIAL );
|
|
SetFontForeground( FONT_YELLOW );
|
|
SetFontShadow( FONT_NEARBLACK );
|
|
if( usNumItems == usQuantity )
|
|
mprintf( x + 12, y + 4, L"%d", usNumItems );
|
|
else
|
|
mprintf( x + 12, y + 4, L"%d(%d)", usNumItems, usQuantity );
|
|
}
|
|
}
|
|
}
|
|
|
|
void ClearEditorItemsInfo()
|
|
{
|
|
if( eInfo.uiBuffer )
|
|
{
|
|
DeleteVideoSurfaceFromIndex( eInfo.uiBuffer );
|
|
eInfo.uiBuffer = 0;
|
|
}
|
|
if( eInfo.pusItemIndex )
|
|
{
|
|
MemFree( eInfo.pusItemIndex );
|
|
eInfo.pusItemIndex = NULL;
|
|
}
|
|
DisableEditorRegion( ITEM_REGION_ID );
|
|
eInfo.fKill = 0;
|
|
eInfo.fActive = 0;
|
|
eInfo.sWidth = 0;
|
|
eInfo.sHeight = 0;
|
|
eInfo.sNumItems = 0;
|
|
//save the highlighted selections
|
|
switch( eInfo.uiItemType )
|
|
{
|
|
case TBAR_MODE_ITEM_WEAPONS:
|
|
eInfo.sSaveSelWeaponsIndex = eInfo.sSelItemIndex;
|
|
eInfo.sSaveWeaponsScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_AMMO:
|
|
eInfo.sSaveSelAmmoIndex = eInfo.sSelItemIndex;
|
|
eInfo.sSaveAmmoScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_ARMOUR:
|
|
eInfo.sSaveSelArmourIndex = eInfo.sSelItemIndex;
|
|
eInfo.sSaveArmourScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_LBEGEAR:
|
|
eInfo.sSaveSelLBEIndex = eInfo.sSelItemIndex;
|
|
eInfo.sSaveLBEScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_EXPLOSIVES:
|
|
eInfo.sSaveSelExplosivesIndex = eInfo.sSelItemIndex;
|
|
eInfo.sSaveExplosivesScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_EQUIPMENT1:
|
|
eInfo.sSaveSelEquipment1Index = eInfo.sSelItemIndex;
|
|
eInfo.sSaveEquipment1ScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_EQUIPMENT2:
|
|
eInfo.sSaveSelEquipment2Index = eInfo.sSelItemIndex;
|
|
eInfo.sSaveEquipment2ScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_EQUIPMENT3:
|
|
eInfo.sSaveSelEquipment3Index = eInfo.sSelItemIndex;
|
|
eInfo.sSaveEquipment3ScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_TRIGGERS:
|
|
eInfo.sSaveSelTriggersIndex = eInfo.sSelItemIndex;
|
|
eInfo.sSaveTriggersScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
case TBAR_MODE_ITEM_KEYS:
|
|
eInfo.sSaveSelKeysIndex = eInfo.sSelItemIndex;
|
|
eInfo.sSaveKeysScrollIndex = eInfo.sScrollIndex;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void HandleItemsPanel( UINT16 usScreenX, UINT16 usScreenY, INT8 bEvent )
|
|
{
|
|
INT16 sIndex;
|
|
UINT16 usQuantity;
|
|
//Calc base index from scrolling index
|
|
sIndex = eInfo.sScrollIndex * 2;
|
|
//Determine if the index is in the first row or second row from mouse YPos.
|
|
if( usScreenY >= (2 * iScreenHeightOffset + 400) )
|
|
sIndex++;
|
|
//Add the converted mouse's XPos into a relative index;
|
|
//Calc: starting from 110, for every 60 pixels, add 2 to the index
|
|
|
|
sIndex += ((usScreenX-110-iScreenWidthOffset)/60) * 2;
|
|
switch( bEvent )
|
|
{
|
|
case GUI_MOVE_EVENT:
|
|
if( sIndex < eInfo.sNumItems )
|
|
{
|
|
if( eInfo.sHilitedItemIndex != sIndex )
|
|
gfRenderTaskbar = TRUE;
|
|
//this index will now highlight in yellow.
|
|
eInfo.sHilitedItemIndex = sIndex;
|
|
}
|
|
break;
|
|
case GUI_LCLICK_EVENT:
|
|
if( sIndex < eInfo.sNumItems )
|
|
{
|
|
//this index will now highlight in red.
|
|
if( eInfo.sSelItemIndex != sIndex )
|
|
gfRenderTaskbar = TRUE;
|
|
eInfo.sSelItemIndex = sIndex;
|
|
if( gfMercGetItem )
|
|
{
|
|
gfMercGetItem = FALSE;
|
|
gusMercsNewItemIndex = eInfo.pusItemIndex[ eInfo.sSelItemIndex ];
|
|
SetMercEditingMode( MERC_INVENTORYMODE );
|
|
ClearEditorItemsInfo();
|
|
}
|
|
}
|
|
break;
|
|
case GUI_RCLICK_EVENT:
|
|
if( gfMercGetItem )
|
|
{
|
|
gfMercGetItem = FALSE;
|
|
gusMercsNewItemIndex = 0xffff;
|
|
SetMercEditingMode( MERC_INVENTORYMODE );
|
|
ClearEditorItemsInfo();
|
|
}
|
|
else if( sIndex < eInfo.sNumItems )
|
|
{
|
|
eInfo.sSelItemIndex = sIndex;
|
|
gfRenderTaskbar = TRUE;
|
|
if( CountNumberOfEditorPlacementsInWorld( eInfo.sSelItemIndex, &usQuantity ) )
|
|
{
|
|
FindNextItemOfSelectedType();
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ShowItemCursor( INT32 iMapIndex )
|
|
{
|
|
LEVELNODE *pNode;
|
|
pNode = gpWorldLevelData[ iMapIndex ].pTopmostHead;
|
|
while( pNode )
|
|
{
|
|
if( pNode->usIndex == SELRING )
|
|
return;
|
|
pNode = pNode->pNext;
|
|
}
|
|
AddTopmostToTail( iMapIndex, SELRING1 );
|
|
}
|
|
|
|
void HideItemCursor( INT32 iMapIndex )
|
|
{
|
|
RemoveTopmost( iMapIndex, SELRING1 );
|
|
}
|
|
|
|
BOOLEAN TriggerAtGridNo( INT32 sGridNo )
|
|
{
|
|
ITEM_POOL *pItemPool;
|
|
if( !GetItemPoolFromGround( sGridNo, &pItemPool ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
while( pItemPool )
|
|
{
|
|
if( gWorldItems[ pItemPool->iItemIndex ].object.usItem == SWITCH )
|
|
{
|
|
return TRUE;
|
|
}
|
|
pItemPool = pItemPool->pNext;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void AddSelectedItemToWorld( INT32 sGridNo )
|
|
{
|
|
OBJECTTYPE *pObject;
|
|
INVTYPE *pItem;
|
|
ITEM_POOL *pItemPool;
|
|
INT32 iItemIndex;
|
|
INT8 bVisibility = INVISIBLE;
|
|
BOOLEAN fFound = FALSE;
|
|
IPListNode *pIPCurr, *pIPPrev;
|
|
UINT16 usFlags;
|
|
|
|
//Extract the currently selected item.
|
|
SpecifyItemToEdit( NULL, -1 );
|
|
|
|
if( eInfo.uiItemType == TBAR_MODE_ITEM_KEYS )
|
|
{
|
|
CreateKeyObject( &gTempObject, 1, (UINT8)eInfo.sSelItemIndex );
|
|
}
|
|
else
|
|
{
|
|
CreateItem( eInfo.pusItemIndex[eInfo.sSelItemIndex], 100, &gTempObject );
|
|
}
|
|
usFlags = 0;
|
|
switch( gTempObject.usItem )
|
|
{
|
|
case MINE:
|
|
if ( bVisibility == BURIED )
|
|
{
|
|
usFlags |= WORLD_ITEM_ARMED_BOMB;
|
|
}
|
|
break;
|
|
case MONEY:
|
|
case SILVER:
|
|
case GOLD:
|
|
gTempObject[0]->data.objectStatus = 100;
|
|
gTempObject[0]->data.money.uiMoneyAmount = 100 + Random( 19901 );
|
|
break;
|
|
case OWNERSHIP:
|
|
gTempObject[0]->data.owner.ubOwnerProfile = NO_PROFILE;
|
|
bVisibility = BURIED;
|
|
break;
|
|
case SWITCH:
|
|
if( TriggerAtGridNo( sGridNo ) )
|
|
{ //Restricted to one action per gridno.
|
|
return;
|
|
}
|
|
bVisibility = BURIED;
|
|
gTempObject[0]->data.objectStatus = 100;
|
|
gTempObject[0]->data.misc.ubBombOwner = 1;
|
|
if( eInfo.sSelItemIndex < 2 )
|
|
gTempObject[0]->data.misc.bFrequency = PANIC_FREQUENCY;
|
|
else if( eInfo.sSelItemIndex < 4 )
|
|
gTempObject[0]->data.misc.bFrequency = PANIC_FREQUENCY_2;
|
|
else if( eInfo.sSelItemIndex < 6 )
|
|
gTempObject[0]->data.misc.bFrequency = PANIC_FREQUENCY_3;
|
|
else
|
|
gTempObject[0]->data.misc.bFrequency = (INT8)(FIRST_MAP_PLACED_FREQUENCY + (eInfo.sSelItemIndex-4) / 2);
|
|
usFlags |= WORLD_ITEM_ARMED_BOMB;
|
|
break;
|
|
case ACTION_ITEM:
|
|
bVisibility = BURIED;
|
|
gTempObject[0]->data.objectStatus = 100;
|
|
gTempObject[0]->data.misc.ubBombOwner = 1;
|
|
gTempObject[0]->data.bTrap = gbDefaultBombTrapLevel;
|
|
if( eInfo.sSelItemIndex < PRESSURE_ACTION_ID )
|
|
{
|
|
gTempObject[0]->data.misc.bDetonatorType = BOMB_REMOTE;
|
|
if( eInfo.sSelItemIndex < 2 )
|
|
gTempObject[0]->data.misc.bFrequency = PANIC_FREQUENCY;
|
|
else if( eInfo.sSelItemIndex < 4 )
|
|
gTempObject[0]->data.misc.bFrequency = PANIC_FREQUENCY_2;
|
|
else if( eInfo.sSelItemIndex < 6 )
|
|
gTempObject[0]->data.misc.bFrequency = PANIC_FREQUENCY_3;
|
|
else
|
|
gTempObject[0]->data.misc.bFrequency = (INT8)(FIRST_MAP_PLACED_FREQUENCY + (eInfo.sSelItemIndex-4) / 2);
|
|
}
|
|
else
|
|
{
|
|
gTempObject[0]->data.misc.bDetonatorType = BOMB_PRESSURE;
|
|
gTempObject[0]->data.misc.bDelay = 0;
|
|
}
|
|
ChangeActionItem( &gTempObject, gbActionItemIndex );
|
|
gTempObject.fFlags |= OBJECT_ARMED_BOMB;
|
|
if( gbActionItemIndex == ACTIONITEM_SMPIT )
|
|
Add3X3Pit( sGridNo );
|
|
else if( gbActionItemIndex == ACTIONITEM_LGPIT )
|
|
Add5X5Pit( sGridNo );
|
|
usFlags |= WORLD_ITEM_ARMED_BOMB;
|
|
break;
|
|
}
|
|
|
|
pObject = InternalAddItemToPool( &sGridNo, &gTempObject, bVisibility, 0, usFlags, 0, -1, &iItemIndex );
|
|
if( gTempObject.usItem != OWNERSHIP )
|
|
{
|
|
gWorldItems[ iItemIndex ].ubNonExistChance = (UINT8)(100 - giDefaultExistChance);
|
|
}
|
|
else
|
|
{
|
|
gWorldItems[ iItemIndex ].ubNonExistChance = 0;
|
|
}
|
|
|
|
pItem = &( Item[ pObject->usItem ] );
|
|
if( pItem->usItemClass == IC_AMMO )
|
|
{
|
|
if (Random( 2 ))
|
|
{
|
|
(*pObject)[0]->data.ubShotsLeft = Magazine[ pItem->ubClassIndex ].ubMagSize;
|
|
}
|
|
else
|
|
{
|
|
(*pObject)[0]->data.ubShotsLeft = (UINT8) Random( Magazine[ pItem->ubClassIndex ].ubMagSize );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(gTempObject.usItem != OWNERSHIP)//dnl ch35 110909
|
|
{
|
|
(*pObject)[0]->data.objectStatus = (INT8)(70 + Random( 26 ));
|
|
(*pObject)[0]->data.sRepairThreshold = max(1, min(100, (100 + (*pObject)[0]->data.objectStatus)/2 ));
|
|
}
|
|
}
|
|
if( pItem->usItemClass & IC_GUN )
|
|
{
|
|
if ( pObject->usItem == ROCKET_LAUNCHER )
|
|
{
|
|
(*pObject)[0]->data.gun.ubGunShotsLeft = 1;
|
|
}
|
|
else
|
|
{
|
|
(*pObject)[0]->data.gun.ubGunShotsLeft = (UINT8)(Random( Weapon[ pObject->usItem ].ubMagSize ));
|
|
}
|
|
}
|
|
|
|
if( !GetItemPoolFromGround( sGridNo, &pItemPool ) )
|
|
Assert( 0 );
|
|
while( pItemPool )
|
|
{
|
|
if( &(gWorldItems[ pItemPool->iItemIndex ].object) == pObject )
|
|
{
|
|
fFound = TRUE;
|
|
//ShowSelectedItem();
|
|
break;
|
|
}
|
|
pItemPool = pItemPool->pNext;
|
|
}
|
|
Assert( fFound );
|
|
|
|
gpItemPool = pItemPool;
|
|
|
|
SpecifyItemToEdit( pObject, sGridNo );
|
|
|
|
//Get access to the itempool.
|
|
//search for a current node in list containing same mapindex
|
|
pIPCurr = pIPHead;
|
|
pIPPrev = NULL;
|
|
while( pIPCurr )
|
|
{
|
|
pIPPrev = pIPCurr;
|
|
if( pIPCurr->sGridNo == sGridNo )
|
|
{
|
|
//found one, so we don't need to add it
|
|
gpCurrItemPoolNode = pIPCurr;
|
|
return;
|
|
}
|
|
pIPCurr = pIPCurr->next;
|
|
}
|
|
//there isn't one, so we will add it now.
|
|
ShowItemCursor( sGridNo );
|
|
if( pIPPrev )
|
|
{
|
|
pIPPrev->next = (IPListNode*)MemAlloc( sizeof( IPListNode ) );
|
|
Assert( pIPPrev->next );
|
|
pIPPrev = pIPPrev->next;
|
|
pIPPrev->next = NULL;
|
|
pIPPrev->sGridNo = sGridNo;
|
|
gpCurrItemPoolNode = pIPPrev;
|
|
}
|
|
else
|
|
{
|
|
pIPHead = (IPListNode*)MemAlloc( sizeof( IPListNode ) );
|
|
Assert( pIPHead );
|
|
pIPHead->next = NULL;
|
|
pIPHead->sGridNo = sGridNo;
|
|
gpCurrItemPoolNode = pIPHead;
|
|
}
|
|
}
|
|
|
|
void HandleRightClickOnItem( INT32 sGridNo )
|
|
{
|
|
ITEM_POOL *pItemPool;
|
|
IPListNode *pIPCurr;
|
|
|
|
if( gsItemGridNo == sGridNo )
|
|
{ //Clicked on the same gridno as the selected item. Automatically select the next
|
|
//item in the same pool.
|
|
pItemPool = gpItemPool->pNext;
|
|
if( !pItemPool )
|
|
{ //currently selected item was last node, so select the head node even if it is the same.
|
|
GetItemPoolFromGround( sGridNo, &pItemPool );
|
|
}
|
|
}
|
|
else if( !GetItemPoolFromGround( sGridNo, &pItemPool ) )
|
|
{
|
|
//possibly relocate selected item to this gridno?
|
|
return;
|
|
}
|
|
|
|
gpItemPool = pItemPool;
|
|
|
|
//set up the item pool pointer to point to the same mapindex node
|
|
pIPCurr = pIPHead;
|
|
gpCurrItemPoolNode = NULL;
|
|
while( pIPCurr )
|
|
{
|
|
if( pIPCurr->sGridNo == sGridNo )
|
|
{
|
|
gpCurrItemPoolNode = pIPCurr;
|
|
break;
|
|
}
|
|
pIPCurr = pIPCurr->next;
|
|
}
|
|
Assert( gpCurrItemPoolNode );
|
|
SpecifyItemToEdit( &gWorldItems[ gpItemPool->iItemIndex ].object, gpItemPool->sGridNo );
|
|
}
|
|
|
|
extern void DeleteSelectedMercsItem();
|
|
|
|
void DeleteSelectedItem()
|
|
{
|
|
SpecifyItemToEdit( NULL, -1 );
|
|
//First, check to see if there even is a currently selected item.
|
|
if( iCurrentTaskbar == TASK_MERCS )
|
|
{
|
|
DeleteSelectedMercsItem();
|
|
return;
|
|
}
|
|
if( gpItemPool )
|
|
{ //Okay, we have a selected item...
|
|
INT32 sGridNo;
|
|
//save the mapindex
|
|
if( gpItemPool->pNext )
|
|
{
|
|
SpecifyItemToEdit( &gWorldItems[ gpItemPool->pNext->iItemIndex ].object, gpItemPool->sGridNo );
|
|
}
|
|
sGridNo = gpItemPool->sGridNo;
|
|
//remove the item
|
|
if( gWorldItems[ gpItemPool->iItemIndex ].object.usItem == ACTION_ITEM )
|
|
{
|
|
if( gWorldItems[ gpItemPool->iItemIndex ].object[0]->data.misc.bActionValue == ACTION_ITEM_SMALL_PIT )
|
|
Remove3X3Pit( gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
else if( gWorldItems[ gpItemPool->iItemIndex ].object[0]->data.misc.bActionValue == ACTION_ITEM_LARGE_PIT )
|
|
Remove5X5Pit( gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
}
|
|
if( gpEditingItemPool == gpItemPool )
|
|
gpEditingItemPool = NULL;
|
|
RemoveItemFromPool( sGridNo, gpItemPool->iItemIndex, 0 );
|
|
gpItemPool = NULL;
|
|
//determine if there are still any items at this location
|
|
if( !GetItemPoolFromGround( sGridNo, &gpItemPool ) )
|
|
{ //no items left, so remove the node from the list.
|
|
IPListNode *pIPPrev, *pIPCurr;
|
|
pIPCurr = pIPHead;
|
|
pIPPrev = NULL;
|
|
while( pIPCurr )
|
|
{
|
|
if( pIPCurr->sGridNo == sGridNo )
|
|
{
|
|
if( pIPPrev ) //middle of list
|
|
pIPPrev->next = pIPCurr->next;
|
|
else //head of list
|
|
pIPHead = pIPHead->next;
|
|
//move the curr item pool to the next one.
|
|
if( pIPCurr->next )
|
|
gpCurrItemPoolNode = pIPCurr->next;
|
|
else
|
|
gpCurrItemPoolNode = pIPHead;
|
|
if( gpCurrItemPoolNode )
|
|
{
|
|
GetItemPoolFromGround( gpCurrItemPoolNode->sGridNo, &gpItemPool );
|
|
Assert( gpItemPool );
|
|
}
|
|
//remove node
|
|
HideItemCursor( sGridNo );
|
|
MemFree( pIPCurr );
|
|
pIPCurr = NULL;
|
|
return;
|
|
}
|
|
pIPPrev = pIPCurr;
|
|
pIPCurr = pIPCurr->next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ShowSelectedItem()
|
|
{
|
|
if( gpItemPool )
|
|
{
|
|
gpItemPool->bVisible = INVISIBLE;
|
|
gWorldItems[ gpItemPool->iItemIndex ].bVisible = INVISIBLE;
|
|
}
|
|
}
|
|
|
|
void HideSelectedItem()
|
|
{
|
|
if( gpItemPool )
|
|
{
|
|
gpItemPool->bVisible = HIDDEN_ITEM;
|
|
gWorldItems[ gpItemPool->iItemIndex ].bVisible = HIDDEN_ITEM;
|
|
}
|
|
}
|
|
|
|
void SelectNextItemPool()
|
|
{
|
|
if( !gpCurrItemPoolNode )
|
|
return;
|
|
//remove the current hilight.
|
|
if( gpItemPool )
|
|
{
|
|
MarkMapIndexDirty( gpItemPool->sGridNo );
|
|
}
|
|
|
|
//go to the next node. If at end of list, choose pIPHead
|
|
if( gpCurrItemPoolNode->next )
|
|
gpCurrItemPoolNode = gpCurrItemPoolNode->next;
|
|
else
|
|
gpCurrItemPoolNode = pIPHead;
|
|
//get the item pool at this node's gridno.
|
|
GetItemPoolFromGround( gpCurrItemPoolNode->sGridNo, &gpItemPool );
|
|
MarkMapIndexDirty( gpItemPool->sGridNo );
|
|
SpecifyItemToEdit( &gWorldItems[ gpItemPool->iItemIndex ].object, gpItemPool->sGridNo );
|
|
if( gsItemGridNo != -1 )
|
|
{
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
}
|
|
}
|
|
|
|
void SelectNextItemInPool()
|
|
{
|
|
if( gpItemPool )
|
|
{
|
|
if( gpItemPool->pNext )
|
|
{
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
else
|
|
{
|
|
GetItemPoolFromGround( gpItemPool->sGridNo, &gpItemPool );
|
|
}
|
|
SpecifyItemToEdit( &gWorldItems[ gpItemPool->iItemIndex ].object, gpItemPool->sGridNo );
|
|
MarkWorldDirty();
|
|
}
|
|
}
|
|
|
|
void SelectPrevItemInPool()
|
|
{
|
|
if( gpItemPool )
|
|
{
|
|
if( gpItemPool->pPrev )
|
|
{
|
|
gpItemPool = gpItemPool->pPrev;
|
|
}
|
|
else
|
|
{
|
|
GetItemPoolFromGround( gpItemPool->sGridNo, &gpItemPool );
|
|
while( gpItemPool->pNext )
|
|
{
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
}
|
|
SpecifyItemToEdit( &gWorldItems[ gpItemPool->iItemIndex ].object, gpItemPool->sGridNo );
|
|
MarkWorldDirty();
|
|
}
|
|
}
|
|
|
|
|
|
void FindNextItemOfSelectedType()
|
|
{
|
|
UINT16 usItem;
|
|
usItem = eInfo.pusItemIndex[ eInfo.sSelItemIndex ];
|
|
if( usItem == ACTION_ITEM || usItem == SWITCH )
|
|
{
|
|
if( eInfo.sSelItemIndex < PRESSURE_ACTION_ID )
|
|
{
|
|
INT8 bFrequency;
|
|
if( eInfo.sSelItemIndex < 2 )
|
|
bFrequency = PANIC_FREQUENCY;
|
|
else if( eInfo.sSelItemIndex < 4 )
|
|
bFrequency = PANIC_FREQUENCY_2;
|
|
else if( eInfo.sSelItemIndex < 6 )
|
|
bFrequency = PANIC_FREQUENCY_3;
|
|
else
|
|
bFrequency = (INT8)(FIRST_MAP_PLACED_FREQUENCY + (eInfo.sSelItemIndex-4) / 2);
|
|
SelectNextTriggerWithFrequency( usItem, bFrequency );
|
|
}
|
|
else
|
|
{
|
|
SelectNextPressureAction();
|
|
}
|
|
}
|
|
else if( Item[ usItem ].usItemClass == IC_KEY )
|
|
{
|
|
SelectNextKeyOfType( (UINT8)eInfo.sSelItemIndex );
|
|
}
|
|
else
|
|
{
|
|
SelectNextItemOfType( usItem );
|
|
}
|
|
}
|
|
|
|
void SelectNextItemOfType( UINT16 usItem )
|
|
{
|
|
IPListNode *curr;
|
|
OBJECTTYPE *pObject;
|
|
if( gpItemPool )
|
|
{
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //skip quickly to the same gridno as the item pool
|
|
if( curr->sGridNo == gWorldItems[ gpItemPool->iItemIndex ].sGridNo )
|
|
{
|
|
gpItemPool = gpItemPool->pNext;
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == usItem )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (another item in same itempool)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
break;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == usItem )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found another item before reaching the end of the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == usItem )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found first item in the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
|
|
void SelectNextKeyOfType( UINT8 ubKeyID )
|
|
{
|
|
IPListNode *curr;
|
|
OBJECTTYPE *pObject;
|
|
if( gpItemPool )
|
|
{
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //skip quickly to the same gridno as the item pool
|
|
if( curr->sGridNo == gWorldItems[ gpItemPool->iItemIndex ].sGridNo )
|
|
{
|
|
gpItemPool = gpItemPool->pNext;
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( Item[ pObject->usItem ].usItemClass == IC_KEY && (*pObject)[0]->data.key.ubKeyID == ubKeyID )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (another item in same itempool)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
break;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( Item[ pObject->usItem ].usItemClass == IC_KEY && (*pObject)[0]->data.key.ubKeyID == ubKeyID )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found another item before reaching the end of the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( Item[ pObject->usItem ].usItemClass == IC_KEY && (*pObject)[0]->data.key.ubKeyID == ubKeyID )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found first item in the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
|
|
void SelectNextTriggerWithFrequency( UINT16 usItem, INT8 bFrequency )
|
|
{
|
|
IPListNode *curr;
|
|
OBJECTTYPE *pObject;
|
|
if( gpItemPool )
|
|
{
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //skip quickly to the same gridno as the item pool
|
|
if( curr->sGridNo == gWorldItems[ gpItemPool->iItemIndex ].sGridNo )
|
|
{
|
|
gpItemPool = gpItemPool->pNext;
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == usItem && (*pObject)[0]->data.misc.bFrequency == bFrequency )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (another item in same itempool)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
break;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == usItem && (*pObject)[0]->data.misc.bFrequency == bFrequency )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found another item before reaching the end of the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == usItem && (*pObject)[0]->data.misc.bFrequency == bFrequency )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found first item in the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
|
|
void SelectNextPressureAction()
|
|
{
|
|
IPListNode *curr;
|
|
OBJECTTYPE *pObject;
|
|
if( gpItemPool )
|
|
{
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //skip quickly to the same gridno as the item pool
|
|
if( curr->sGridNo == gWorldItems[ gpItemPool->iItemIndex ].sGridNo )
|
|
{
|
|
gpItemPool = gpItemPool->pNext;
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == ACTION_ITEM && (*pObject)[0]->data.misc.bDetonatorType == BOMB_PRESSURE )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (another item in same itempool)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
break;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == ACTION_ITEM && (*pObject)[0]->data.misc.bDetonatorType == BOMB_PRESSURE )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found another item before reaching the end of the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
curr = pIPHead;
|
|
while( curr )
|
|
{ //search to the end of the list
|
|
GetItemPoolFromGround( curr->sGridNo, &gpItemPool );
|
|
while( gpItemPool )
|
|
{
|
|
pObject = &gWorldItems[ gpItemPool->iItemIndex ].object;
|
|
if( pObject->usItem == ACTION_ITEM && (*pObject)[0]->data.misc.bDetonatorType == BOMB_PRESSURE )
|
|
{
|
|
SpecifyItemToEdit( pObject, gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
|
|
CenterScreenAtMapIndex( gsItemGridNo );
|
|
return; //success! (found first item in the list)
|
|
}
|
|
gpItemPool = gpItemPool->pNext;
|
|
}
|
|
curr = curr->next;
|
|
}
|
|
}
|
|
|
|
UINT16 CountNumberOfItemPlacementsInWorld( UINT16 usItem, UINT16 *pusQuantity )
|
|
{
|
|
ITEM_POOL *pItemPool;
|
|
IPListNode *pIPCurr;
|
|
INT16 num = 0;
|
|
*pusQuantity = 0;
|
|
pIPCurr = pIPHead;
|
|
while( pIPCurr )
|
|
{
|
|
GetItemPoolFromGround( pIPCurr->sGridNo, &pItemPool );
|
|
while( pItemPool )
|
|
{
|
|
if( gWorldItems[ pItemPool->iItemIndex ].object.usItem == usItem )
|
|
{
|
|
num++;
|
|
*pusQuantity += gWorldItems[ pItemPool->iItemIndex ].object.ubNumberOfObjects;
|
|
}
|
|
pItemPool = pItemPool->pNext;
|
|
}
|
|
pIPCurr = pIPCurr->next;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
UINT16 CountNumberOfItemsWithFrequency( UINT16 usItem, INT8 bFrequency )
|
|
{
|
|
ITEM_POOL *pItemPool;
|
|
IPListNode *pIPCurr;
|
|
UINT16 num = 0;
|
|
pIPCurr = pIPHead;
|
|
while( pIPCurr )
|
|
{
|
|
GetItemPoolFromGround( pIPCurr->sGridNo, &pItemPool );
|
|
while( pItemPool )
|
|
{
|
|
if( gWorldItems[ pItemPool->iItemIndex ].object.usItem == usItem &&
|
|
gWorldItems[ pItemPool->iItemIndex ].object[0]->data.misc.bFrequency == bFrequency )
|
|
{
|
|
num++;
|
|
}
|
|
pItemPool = pItemPool->pNext;
|
|
}
|
|
pIPCurr = pIPCurr->next;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
UINT16 CountNumberOfPressureActionsInWorld()
|
|
{
|
|
ITEM_POOL *pItemPool;
|
|
IPListNode *pIPCurr;
|
|
UINT16 num = 0;
|
|
pIPCurr = pIPHead;
|
|
while( pIPCurr )
|
|
{
|
|
GetItemPoolFromGround( pIPCurr->sGridNo, &pItemPool );
|
|
while( pItemPool )
|
|
{
|
|
if( gWorldItems[ pItemPool->iItemIndex ].object.usItem == ACTION_ITEM &&
|
|
gWorldItems[ pItemPool->iItemIndex ].object[0]->data.misc.bDetonatorType == BOMB_PRESSURE )
|
|
{
|
|
num++;
|
|
}
|
|
pItemPool = pItemPool->pNext;
|
|
}
|
|
pIPCurr = pIPCurr->next;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
UINT16 CountNumberOfEditorPlacementsInWorld( UINT16 usEInfoIndex, UINT16 *pusQuantity )
|
|
{
|
|
UINT16 usNumPlacements;
|
|
if( eInfo.uiItemType == TBAR_MODE_ITEM_TRIGGERS )
|
|
{ //find identical items with same frequency
|
|
INT8 bFrequency;
|
|
if( usEInfoIndex < PRESSURE_ACTION_ID )
|
|
{
|
|
if( usEInfoIndex < 2 )
|
|
bFrequency = PANIC_FREQUENCY;
|
|
else if( usEInfoIndex < 4 )
|
|
bFrequency = PANIC_FREQUENCY_2;
|
|
else if( usEInfoIndex < 6 )
|
|
bFrequency = PANIC_FREQUENCY_3;
|
|
else
|
|
bFrequency = (INT8)(FIRST_MAP_PLACED_FREQUENCY + (usEInfoIndex-4) / 2);
|
|
usNumPlacements = CountNumberOfItemsWithFrequency( eInfo.pusItemIndex[usEInfoIndex], bFrequency );
|
|
*pusQuantity = usNumPlacements;
|
|
}
|
|
else
|
|
{
|
|
usNumPlacements = CountNumberOfPressureActionsInWorld();
|
|
*pusQuantity = usNumPlacements;
|
|
}
|
|
}
|
|
else if( eInfo.uiItemType == TBAR_MODE_ITEM_KEYS )
|
|
{
|
|
usNumPlacements = CountNumberOfKeysOfTypeInWorld( (UINT8)usEInfoIndex );
|
|
*pusQuantity = usNumPlacements;
|
|
}
|
|
else
|
|
{
|
|
usNumPlacements = CountNumberOfItemPlacementsInWorld( eInfo.pusItemIndex[ usEInfoIndex], pusQuantity );
|
|
}
|
|
return usNumPlacements;
|
|
}
|
|
|
|
UINT16 CountNumberOfKeysOfTypeInWorld( UINT8 ubKeyID )
|
|
{
|
|
ITEM_POOL *pItemPool;
|
|
IPListNode *pIPCurr;
|
|
INT16 num = 0;
|
|
pIPCurr = pIPHead;
|
|
while( pIPCurr )
|
|
{
|
|
GetItemPoolFromGround( pIPCurr->sGridNo, &pItemPool );
|
|
while( pItemPool )
|
|
{
|
|
if( Item[ gWorldItems[ pItemPool->iItemIndex ].object.usItem ].usItemClass == IC_KEY )
|
|
{
|
|
if( gWorldItems[ pItemPool->iItemIndex ].object[0]->data.key.ubKeyID == ubKeyID )
|
|
{
|
|
num++;
|
|
}
|
|
}
|
|
pItemPool = pItemPool->pNext;
|
|
}
|
|
pIPCurr = pIPCurr->next;
|
|
}
|
|
return num;
|
|
}
|
|
|
|
void DisplayItemStatistics()
|
|
{
|
|
BOOLEAN fUseSelectedItem;
|
|
INT16 usItemIndex;
|
|
CHAR16 pItemName[SIZE_ITEM_NAME];
|
|
INVTYPE *pItem;
|
|
|
|
if( !eInfo.fActive )
|
|
{
|
|
return;
|
|
}
|
|
|
|
//If there is nothing else currently highlited by the mouse, use the selected item.
|
|
fUseSelectedItem = eInfo.sHilitedItemIndex == -1 || eInfo.sHilitedItemIndex == eInfo.sSelItemIndex;
|
|
|
|
SetFont( SMALLCOMPFONT );
|
|
SetFontForeground( (UINT8)(fUseSelectedItem ? FONT_LTRED : FONT_YELLOW) );
|
|
|
|
//Extract all of the item information.
|
|
if( !eInfo.pusItemIndex )
|
|
return;
|
|
usItemIndex = eInfo.pusItemIndex[ fUseSelectedItem ? eInfo.sSelItemIndex : eInfo.sHilitedItemIndex ];
|
|
pItem = &Item[ usItemIndex ];
|
|
LoadItemInfo( usItemIndex, pItemName, NULL );
|
|
|
|
mprintf( iScreenWidthOffset + 50 - StringPixLength( pItemName , SMALLCOMPFONT )/2, 2 * iScreenHeightOffset + 403, pItemName );
|
|
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 410, pDisplayItemStatisticsTex[0]);
|
|
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 420, pDisplayItemStatisticsTex[1]);
|
|
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 430, pDisplayItemStatisticsTex[2]);
|
|
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 440, pDisplayItemStatisticsTex[3]);
|
|
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 450, pDisplayItemStatisticsTex[4]);
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|