Files
source/Editor/EditorItems.cpp
T
lalien 0530b53b9c bug fixes from Overhaul:
- Data type changes 
- Templates removed

git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@871 3b4a5df2-a311-0410-b5c6-a8a6f20db521
2007-05-09 13:16:37 +00:00

1657 lines
46 KiB
C++

// WANNE: EDITOR?
#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"
#endif
#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
{
INT16 sGridNo;
struct IPListNode *next;
}IPListNode;
IPListNode *pIPHead = NULL;
IPListNode *gpCurrItemPoolNode = NULL;
ITEM_POOL *gpItemPool = NULL;
void BuildItemPoolList()
{
ITEM_POOL *temp;
IPListNode *tail;
UINT16 i;
KillItemPoolList();
for( i = 0; i < WORLD_MAX; i++ )
{
if( GetItemPool( i, &temp , 0) )
{
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 )
{
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( 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_GRENADE:
case IC_BOMB:
eInfo.sNumExplosives++;
break;
case IC_MEDKIT:
case IC_KIT:
case IC_FACE:
case IC_MISC:
case IC_MONEY:
if( eInfo.sNumEquipment1 < 30 )
eInfo.sNumEquipment1++;
else if( eInfo.sNumEquipment2 < 30 )
eInfo.sNumEquipment2++;
else
eInfo.sNumEquipment3++;
break;
//case IC_KEY:
// eInfo.sNumKeys++;
// break;
}
}
eInfo.sNumKeys = NUM_KEYS;
}
}
// WANNE: EDITOR?
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_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.
// WANNE: EDITOR?
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 );
//Calculate the center position of the graphic in a 60 pixel wide area.
sWidth = hVObject->pETRLEObject[item->ubGraphicNum].usWidth;
sOffset = hVObject->pETRLEObject[item->ubGraphicNum].sOffsetX;
sStart = x + (60 - sWidth - sOffset*2) / 2;
BltVideoObjectOutlineFromIndex( eInfo.uiBuffer, uiVideoObjectIndex, item->ubGraphicNum, sStart, y+2, 0, FALSE );
//cycle through the various slot positions (0,0), (0,40), (60,0), (60,40), (120,0)...
// WANNE: EDITOR?
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 )
{
// 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_GRENADE:
case IC_BOMB:
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_EXPLOSIVES;
break;
case IC_MEDKIT:
case IC_KIT:
case IC_FACE:
case IC_MISC:
case IC_MONEY:
if( usCounter == ACTION_ITEM || usCounter == SWITCH )
break;
if( iEquipCount < 30 )
fTypeMatch = eInfo.uiItemType == TBAR_MODE_ITEM_EQUIPMENT1;
else if( iEquipCount < 60 )
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, L"Pressure Action" );
}
else if( i < 2 )
{
if( usCounter == SWITCH )
swprintf( pStr, L"Panic Trigger1" );
else
swprintf( pStr, L"Panic Action1" );
}
else if( i < 4 )
{
if( usCounter == SWITCH )
swprintf( pStr, L"Panic Trigger2" );
else
swprintf( pStr, L"Panic Action2" );
}
else if( i < 6 )
{
if( usCounter == SWITCH )
swprintf( pStr, L"Panic Trigger3" );
else
swprintf( pStr, L"Panic Action3" );
}
else
{
if( usCounter == SWITCH )
swprintf( pStr, L"Trigger%d", (i-4)/2 );
else
swprintf( pStr, L"Action%d", (i-4)/2 );
}
}
// WANNE: EDITOR?
DisplayWrappedString(x, (UINT16)(y+25), 60, 2, SMALLCOMPFONT, FONT_WHITE, pStr, FONT_BLACK, TRUE, CENTER_JUSTIFIED );
//Calculate the center position of the graphic in a 60 pixel wide area.
sWidth = hVObject->pETRLEObject[item->ubGraphicNum].usWidth;
sOffset = hVObject->pETRLEObject[item->ubGraphicNum].sOffsetX;
sStart = x + (60 - sWidth - sOffset*2) / 2;
if( sWidth )
{
BltVideoObjectOutlineFromIndex( eInfo.uiBuffer, uiVideoObjectIndex, item->ubGraphicNum, sStart, y+2, 0, FALSE );
}
// WANNE: EDITOR?
//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;
}
}
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;
}
// WANNE: EDITOR?
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;
sWidth = hVObject->pETRLEObject[item->ubGraphicNum].usWidth;
sOffset = hVObject->pETRLEObject[item->ubGraphicNum].sOffsetX;
sStart = x + (60 - sWidth - sOffset*2) / 2;
if( sWidth )
{
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, item->ubGraphicNum, 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;
sWidth = hVObject->pETRLEObject[item->ubGraphicNum].usWidth;
sOffset = hVObject->pETRLEObject[item->ubGraphicNum].sOffsetX;
sStart = x + (60 - sWidth - sOffset*2) / 2;
if( sWidth )
{
BltVideoObjectOutlineFromIndex( FRAME_BUFFER, uiVideoObjectIndex, item->ubGraphicNum, 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_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
// WANNE: EDITOR????
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( INT16 sGridNo )
{
ITEM_POOL *pItemPool;
if( !GetItemPool( sGridNo, &pItemPool, 0 ) )
{
return FALSE;
}
while( pItemPool )
{
if( gWorldItems[ pItemPool->iItemIndex ].o.usItem == SWITCH )
{
return TRUE;
}
pItemPool = pItemPool->pNext;
}
return FALSE;
}
void AddSelectedItemToWorld( INT16 sGridNo )
{
OBJECTTYPE tempObject;
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 );
//memset( &tempObject, 0, sizeof( OBJECTTYPE ) );
if( eInfo.uiItemType == TBAR_MODE_ITEM_KEYS )
{
CreateKeyObject( &tempObject, 1, (UINT8)eInfo.sSelItemIndex );
}
else
{
CreateItem( eInfo.pusItemIndex[eInfo.sSelItemIndex], 100, &tempObject );
}
usFlags = 0;
switch( tempObject.usItem )
{
case MINE:
if ( bVisibility == BURIED )
{
usFlags |= WORLD_ITEM_ARMED_BOMB;
}
break;
case MONEY:
case SILVER:
case GOLD:
tempObject.bStatus[0] = 100;
tempObject.uiMoneyAmount = 100 + Random( 19901 );
break;
case OWNERSHIP:
tempObject.ubOwnerProfile = NO_PROFILE;
bVisibility = BURIED;
break;
case SWITCH:
if( TriggerAtGridNo( sGridNo ) )
{ //Restricted to one action per gridno.
return;
}
bVisibility = BURIED;
tempObject.bStatus[0] = 100;
tempObject.ubBombOwner = 1;
if( eInfo.sSelItemIndex < 2 )
tempObject.bFrequency = PANIC_FREQUENCY;
else if( eInfo.sSelItemIndex < 4 )
tempObject.bFrequency = PANIC_FREQUENCY_2;
else if( eInfo.sSelItemIndex < 6 )
tempObject.bFrequency = PANIC_FREQUENCY_3;
else
tempObject.bFrequency = (INT8)(FIRST_MAP_PLACED_FREQUENCY + (eInfo.sSelItemIndex-4) / 2);
usFlags |= WORLD_ITEM_ARMED_BOMB;
break;
case ACTION_ITEM:
bVisibility = BURIED;
tempObject.bStatus[0] = 100;
tempObject.ubBombOwner = 1;
tempObject.bTrap = gbDefaultBombTrapLevel;
if( eInfo.sSelItemIndex < PRESSURE_ACTION_ID )
{
tempObject.bDetonatorType = BOMB_REMOTE;
if( eInfo.sSelItemIndex < 2 )
tempObject.bFrequency = PANIC_FREQUENCY;
else if( eInfo.sSelItemIndex < 4 )
tempObject.bFrequency = PANIC_FREQUENCY_2;
else if( eInfo.sSelItemIndex < 6 )
tempObject.bFrequency = PANIC_FREQUENCY_3;
else
tempObject.bFrequency = (INT8)(FIRST_MAP_PLACED_FREQUENCY + (eInfo.sSelItemIndex-4) / 2);
}
else
{
tempObject.bDetonatorType = BOMB_PRESSURE;
tempObject.bDelay = 0;
}
ChangeActionItem( &tempObject, gbActionItemIndex );
tempObject.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, &tempObject, bVisibility, 0, usFlags, 0, &iItemIndex );
if( tempObject.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->ubShotsLeft[0] = Magazine[ pItem->ubClassIndex ].ubMagSize;
}
else
{
pObject->ubShotsLeft[0] = (UINT8) Random( Magazine[ pItem->ubClassIndex ].ubMagSize );
}
}
else
{
pObject->bStatus[0] = (INT8)(70 + Random( 26 ));
}
if( pItem->usItemClass & IC_GUN )
{
if ( pObject->usItem == ROCKET_LAUNCHER )
{
pObject->ubGunShotsLeft = 1;
}
else
{
pObject->ubGunShotsLeft = (UINT8)(Random( Weapon[ pObject->usItem ].ubMagSize ));
}
}
if( !GetItemPool( sGridNo, &pItemPool, 0 ) )
Assert( 0 );
while( pItemPool )
{
if( &(gWorldItems[ pItemPool->iItemIndex ].o) == 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( INT16 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.
GetItemPool( sGridNo, &pItemPool, 0 );
}
}
else if( !GetItemPool( sGridNo, &pItemPool, 0 ) )
{
//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 ].o, 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...
INT16 sGridNo;
//save the mapindex
if( gpItemPool->pNext )
{
SpecifyItemToEdit( &gWorldItems[ gpItemPool->pNext->iItemIndex ].o, gpItemPool->sGridNo );
}
sGridNo = gpItemPool->sGridNo;
//remove the item
if( gWorldItems[ gpItemPool->iItemIndex ].o.usItem == ACTION_ITEM )
{
if( gWorldItems[ gpItemPool->iItemIndex ].o.bActionValue == ACTION_ITEM_SMALL_PIT )
Remove3X3Pit( gWorldItems[ gpItemPool->iItemIndex ].sGridNo );
else if( gWorldItems[ gpItemPool->iItemIndex ].o.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( !GetItemPool( sGridNo, &gpItemPool , 0 ) )
{ //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 )
{
GetItemPool( gpCurrItemPoolNode->sGridNo, &gpItemPool, 0 );
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.
GetItemPool( gpCurrItemPoolNode->sGridNo, &gpItemPool, 0 );
MarkMapIndexDirty( gpItemPool->sGridNo );
SpecifyItemToEdit( &gWorldItems[ gpItemPool->iItemIndex ].o, gpItemPool->sGridNo );
if( gsItemGridNo != -1 )
{
CenterScreenAtMapIndex( gsItemGridNo );
}
}
void SelectNextItemInPool()
{
if( gpItemPool )
{
if( gpItemPool->pNext )
{
gpItemPool = gpItemPool->pNext;
}
else
{
GetItemPool( gpItemPool->sGridNo, &gpItemPool, 0 );
}
SpecifyItemToEdit( &gWorldItems[ gpItemPool->iItemIndex ].o, gpItemPool->sGridNo );
MarkWorldDirty();
}
}
void SelectPrevItemInPool()
{
if( gpItemPool )
{
if( gpItemPool->pPrev )
{
gpItemPool = gpItemPool->pPrev;
}
else
{
GetItemPool( gpItemPool->sGridNo, &gpItemPool, 0 );
while( gpItemPool->pNext )
{
gpItemPool = gpItemPool->pNext;
}
}
SpecifyItemToEdit( &gWorldItems[ gpItemPool->iItemIndex ].o, 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 ].o;
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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
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 ].o;
if( Item[ pObject->usItem ].usItemClass == IC_KEY && pObject->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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
if( Item[ pObject->usItem ].usItemClass == IC_KEY && pObject->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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
if( Item[ pObject->usItem ].usItemClass == IC_KEY && pObject->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 ].o;
if( pObject->usItem == usItem && pObject->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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
if( pObject->usItem == usItem && pObject->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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
if( pObject->usItem == usItem && pObject->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 ].o;
if( pObject->usItem == ACTION_ITEM && pObject->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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
if( pObject->usItem == ACTION_ITEM && pObject->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
GetItemPool( curr->sGridNo, &gpItemPool, 0 );
while( gpItemPool )
{
pObject = &gWorldItems[ gpItemPool->iItemIndex ].o;
if( pObject->usItem == ACTION_ITEM && pObject->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 )
{
GetItemPool( pIPCurr->sGridNo, &pItemPool, 0 );
while( pItemPool )
{
if( gWorldItems[ pItemPool->iItemIndex ].o.usItem == usItem )
{
num++;
*pusQuantity += gWorldItems[ pItemPool->iItemIndex ].o.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 )
{
GetItemPool( pIPCurr->sGridNo, &pItemPool, 0 );
while( pItemPool )
{
if( gWorldItems[ pItemPool->iItemIndex ].o.usItem == usItem &&
gWorldItems[ pItemPool->iItemIndex ].o.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 )
{
GetItemPool( pIPCurr->sGridNo, &pItemPool, 0 );
while( pItemPool )
{
if( gWorldItems[ pItemPool->iItemIndex ].o.usItem == ACTION_ITEM &&
gWorldItems[ pItemPool->iItemIndex ].o.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 )
{
GetItemPool( pIPCurr->sGridNo, &pItemPool, 0 );
while( pItemPool )
{
if( Item[ gWorldItems[ pItemPool->iItemIndex ].o.usItem ].usItemClass == IC_KEY )
{
if( gWorldItems[ pItemPool->iItemIndex ].o.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, L"Status Info Line 1");
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 420, L"Status Info Line 2");
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 430, L"Status Info Line 3");
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 440, L"Status Info Line 4");
mprintf( iScreenWidthOffset + 2, 2 * iScreenHeightOffset + 450, L"Status Info Line 5");
}
#endif