Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 64 additions & 83 deletions Laptop/BobbyRGuns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,29 @@ void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber );
void HandleBobbyRGunsKeyBoardInput();
void HandleBobbyRayMouseWheel(void);

// Appends source STR16 to target STR16 using decorators ("\n" and "...").
// Returns TRUE if everything fits target, FALSE otherwise.
static BOOLEAN DecorateAppendString(STR16 target, size_t targetCapacity, STR16 source, UINT32 frontDecoratorsCnt = 1)
{
const CHAR16 DECORATOR0[] = L"\n";
const CHAR16 DECORATOR1[] = L"\n...";
BOOLEAN result = FALSE;
size_t decoratorLen = wcslen(DECORATOR0) * frontDecoratorsCnt;

if (wcslen(target) + decoratorLen + wcslen(source) + 1 < targetCapacity)
{
for (UINT32 i = 0; i < frontDecoratorsCnt; i++)
wcscat(target, DECORATOR0);
wcscat(target, source);
result = TRUE;
}
else if (wcslen(target) + wcslen(DECORATOR1) + 1 < targetCapacity)
{
wcscat(target, DECORATOR1);
} // otherwise don't even touch the target
return result;
}

void GameInitBobbyRGuns()
{
guiTempCurrentMode=0;
Expand Down Expand Up @@ -4088,7 +4111,8 @@ void HandleBobbyRayMouseWheel(void)
}

void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber )
{
{
const size_t ATTACHMENTS_STRBUF_SIZE = 3800;
CHAR16 zItemName[ SIZE_ITEM_NAME ];
UINT8 ubItemCount=0;

Expand All @@ -4115,12 +4139,9 @@ void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber )
// HEADROCK HAM 3: Variables for "Possible Attachment List"
BOOLEAN fAttachmentsFound = FALSE;
// Contains entire string of attachment names
CHAR16 attachStr[3900];
// Contains current attachment string
CHAR16 attachStr2[100];
CHAR16 attachStr[ATTACHMENTS_STRBUF_SIZE];
// Contains temporary attachment list before added to string constant from text.h
CHAR16 attachStr3[3900];
UINT16 usAttachment;
CHAR16 attachStr3[ATTACHMENTS_STRBUF_SIZE];

CreateItem(usItemNumber, 100, &pObject);
INT16 ubAttackAPs = BaseAPsToShootOrStab( APBPConstants[DEFAULT_APS], APBPConstants[DEFAULT_AIMSKILL], &pObject, NULL );
Expand All @@ -4146,109 +4167,69 @@ void GetHelpTextForItemInLaptop( STR16 pzStr, UINT16 usItemNumber )
else
wcscat( apStr, L" / -" );

// HEADROCK HAM 3: Empty these strings first, to avoid crashes. Please keep this here.
swprintf( attachStr, L"" );
swprintf( attachStr2, L"" );
swprintf( attachStr3, L"" );
attachStr[0] = 0;
attachStr3[0] = 0;

// HEADROCK HAM 3: Generate list of possible attachments to a gun (Guns only!)
if (gGameExternalOptions.fBobbyRayTooltipsShowAttachments)
{
UINT16 iLoop = 0;
// Check entire attachment list
while( 1 )
if (UsingNewAttachmentSystem())
{
//Madd: Common Attachment Framework
//TODO: Note that the items in this list will be duplicated if they are present in both the CAF and the old attachment method
//need to refactor this to work more like the NAS attachment slots method
usAttachment = 0;
if ( IsAttachmentPointAvailable(Item[usItemNumber].uiIndex, iLoop) )
{
usAttachment = iLoop;
// If the attachment is not hidden
if (usAttachment > 0 && !Item[ usAttachment ].hiddenaddon && !Item[ usAttachment ].hiddenattachment)
std::pair<std::multimap<UINT16, AttachmentStruct>::iterator, std::multimap<UINT16, AttachmentStruct>::iterator> range;
std::multimap<UINT16, AttachmentStruct>::iterator it;
range = AttachmentBackmap.equal_range(Item[usItemNumber].uiIndex);
for (it = range.first; it != range.second; it++)
{
UINT16 attachmentId = it->second.attachmentIndex;
if (!Item[attachmentId].hiddenaddon && !Item[attachmentId].hiddenattachment && ItemIsLegal(attachmentId, TRUE))
{
if (wcslen( attachStr3 ) + wcslen(Item[usAttachment].szItemName) > 3800)
{
// End list early to avoid stack overflow
wcscat( attachStr3, L"\n..." );
fAttachmentsFound = TRUE;
if (DecorateAppendString(attachStr3, ATTACHMENTS_STRBUF_SIZE, Item[attachmentId].szItemName) == FALSE)
break;
}
else
{// Add the attachment's name to the list.
fAttachmentsFound = TRUE;
swprintf( attachStr2, L"\n%s", Item[ usAttachment ].szItemName );
wcscat( attachStr3, attachStr2);
}
}
}

// Is the weapon we're checking the same as the one we're tooltipping?
usAttachment = 0;
if (Attachment[iLoop][1] == Item[usItemNumber].uiIndex)
{
usAttachment = Attachment[iLoop][0];
}

// If the attachment is not hidden
if (usAttachment > 0 && !Item[ usAttachment ].hiddenaddon && !Item[ usAttachment ].hiddenattachment)
}
else // old attachment system
{
for (UINT32 itemId = 1; itemId < gMAXITEMS_READ; itemId++)
{
if (wcslen( attachStr3 ) + wcslen(Item[usAttachment].szItemName) > 3800)
// If the attachment is not hidden and attachable to the gun (usItemNumber)
if (!Item[itemId].hiddenaddon && !Item[itemId].hiddenattachment &&
ItemIsLegal(itemId, TRUE) && IsAttachmentPointAvailable(Item[usItemNumber].uiIndex, itemId))
{
// End list early to avoid stack overflow
wcscat( attachStr3, L"\n..." );
break;
}
else
{// Add the attachment's name to the list.
fAttachmentsFound = TRUE;
swprintf( attachStr2, L"\n%s", Item[ usAttachment ].szItemName );
wcscat( attachStr3, attachStr2);
if (DecorateAppendString(attachStr3, ATTACHMENTS_STRBUF_SIZE, Item[itemId].szItemName) == FALSE)
break;
}
}


iLoop++;
if (Attachment[iLoop][0] == 0 && Item[iLoop].usItemClass == 0)
{
// Reached end of list
break;
}
}

if (fAttachmentsFound)
{
// Add extra empty line and attachment list title
swprintf( attachStr, L"\n \n%s", gWeaponStatsDesc[ 14 ] );
wcscat( attachStr, attachStr3 );
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, gWeaponStatsDesc[14], 2); // 2 new lines and "Attachments:" title
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, attachStr3, 0); // no new line, list of attachments (starts with new line)
}
}

//Sum up default attachments.
BOOLEAN fFoundDefault = FALSE;
swprintf( attachStr2, L"" );
swprintf( attachStr3, L"" );
for(UINT8 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS; cnt++){
if(Item[usItemNumber].defaultattachments[cnt] != 0){
if (wcslen( attachStr ) + wcslen(attachStr3) + wcslen(Item[ Item[usItemNumber].defaultattachments[cnt] ].szItemName) > 3800)
{
// End list early to avoid stack overflow
wcscat( attachStr3, L"\n..." );
attachStr3[0] = 0;
for (UINT8 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS; cnt++)
{
if (Item[usItemNumber].defaultattachments[cnt] != 0)
{
if (DecorateAppendString(attachStr3, ATTACHMENTS_STRBUF_SIZE, Item[Item[usItemNumber].defaultattachments[cnt]].szItemName) == FALSE)
break;
}
fFoundDefault = TRUE;
swprintf( attachStr2, L"\n%s", Item[ Item[usItemNumber].defaultattachments[cnt] ].szItemName );
wcscat( attachStr3, attachStr2 );
} else {
//If we found an empty entry, we can assume the rest will be empty too.
break;
}
else // If we found an empty entry, we can assume the rest will be empty too.
break;
}
if(fFoundDefault){
//Found at least one default attachment, write it to the attachment string.
CHAR16 defaultStr[50];
swprintf( defaultStr, L"\n \n%s", gWeaponStatsDesc[ 17 ] );
wcscat( attachStr, defaultStr );
wcscat( attachStr, attachStr3 );

if (fFoundDefault)
{
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, gWeaponStatsDesc[17], 2); // 2 new lines and "Default:" title
DecorateAppendString(attachStr, ATTACHMENTS_STRBUF_SIZE, attachStr3, 0); // no new line, list of attachments (starts with new line)
}

// HEADROCK HAM 3: Added last string (attachStr), for display of the possible attachment list.
Expand Down
34 changes: 13 additions & 21 deletions Tactical/Interface Items.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2913,20 +2913,16 @@ void HandleAnyMercInSquadHasCompatibleStuff( UINT8 ubSquad, OBJECTTYPE *pObject,

BOOLEAN IsMutuallyValidAttachmentOrLaunchable(UINT16 usAttItem, UINT16 usItem)//dnl ch76 091113
{
UINT32 uiLoop = 0;
while ( Attachment[uiLoop][0] )
for (UINT32 uiLoop = 0; uiLoop < gMAXATTACHMENTS_READ; uiLoop++)
{
if(Attachment[uiLoop][0] == usAttItem && Attachment[uiLoop][1] == usItem || Attachment[uiLoop][0] == usItem && Attachment[uiLoop][1] == usAttItem )
if (Attachment[uiLoop].attachmentIndex == usAttItem && Attachment[uiLoop].itemIndex == usItem || Attachment[uiLoop].attachmentIndex == usItem && Attachment[uiLoop].itemIndex == usAttItem)
return(TRUE);
++uiLoop;
}

uiLoop = 0;
while ( Launchable[uiLoop][0] )
for (UINT32 uiLoop = 0; uiLoop < gMAXLAUNCHABLES_READ; uiLoop++)
{
if ( Launchable[uiLoop][0] == usAttItem && Launchable[uiLoop][1] == usItem || Launchable[uiLoop][0] == usItem && Launchable[uiLoop][1] == usAttItem )
return(TRUE);
++uiLoop;
}

return(FALSE);
Expand Down Expand Up @@ -5765,12 +5761,8 @@ void UpdateAttachmentTooltips(OBJECTTYPE *pObject, UINT8 ubStatusIndex)
}

// sevenfm: check launchables
for (UINT16 usLoop = 0; usLoop < MAXITEMS + 1; usLoop++)
for (UINT16 usLoop = 0; usLoop < gMAXLAUNCHABLES_READ; usLoop++)
{
// check that reached end of valid launchables
if (Launchable[usLoop][0] == 0)
break;

usAttachment = 0;
if (Launchable[usLoop][1] == pObject->usItem && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Launchable[usLoop][0]].nasAttachmentClass)
{
Expand Down Expand Up @@ -5801,17 +5793,14 @@ void UpdateAttachmentTooltips(OBJECTTYPE *pObject, UINT8 ubStatusIndex)
}

// check all attachments
for (UINT16 usLoop = 0; usLoop < MAXATTACHMENTS; usLoop++)
//TODO: should be optimized using AttachmentBackmap and/or possibly FindAttachmentRange()
for (UINT32 uiLoop = 0; uiLoop < gMAXATTACHMENTS_READ; uiLoop++)
{
// check that reached end of valid attachments
if (Attachment[usLoop][0] == 0)
break;

usAttachment = 0;
if (Attachment[usLoop][1] == pObject->usItem && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[usLoop][0]].nasAttachmentClass)
if (Attachment[uiLoop].itemIndex == pObject->usItem && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[uiLoop].attachmentIndex].nasAttachmentClass)
{
//search primary item attachments.xml
usAttachment = Attachment[usLoop][0];
usAttachment = Attachment[uiLoop].attachmentIndex;
}
else
{
Expand All @@ -5820,8 +5809,11 @@ void UpdateAttachmentTooltips(OBJECTTYPE *pObject, UINT8 ubStatusIndex)
UINT16* p = cnt ? &attachedList.front() : NULL;
while (cnt)
{
if (Attachment[usLoop][1] == *p && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[usLoop][0]].nasAttachmentClass)
usAttachment = Attachment[usLoop][0];
if (Attachment[uiLoop].itemIndex == *p && AttachmentSlots[usLoopSlotID].nasAttachmentClass & Item[Attachment[uiLoop].attachmentIndex].nasAttachmentClass)
{
usAttachment = Attachment[uiLoop].attachmentIndex;
break;
}

cnt--, p++;
}
Expand Down
24 changes: 23 additions & 1 deletion Tactical/Item Types.h
Original file line number Diff line number Diff line change
Expand Up @@ -1724,9 +1724,30 @@ typedef enum
MAXITEMS = 16001
} ITEMDEFINE;

struct AttachmentStruct
{
UINT16 attachmentIndex;
UINT16 itemIndex;
UINT16 APCost;
UINT16 NASOnly;

bool operator<(const AttachmentStruct& a) const
{
bool result = false;
if (attachmentIndex < a.attachmentIndex)
result = true;
else if (attachmentIndex == a.attachmentIndex)
result = itemIndex < a.itemIndex;

return result;
}
};

// Flugente: in order not to loop over MAXITEMS items if we only have a few thousand, remember the actual number of items in the xml
extern UINT32 gMAXITEMS_READ;
extern UINT32 gMAXAMMOTYPES_READ;
extern UINT32 gMAXATTACHMENTS_READ;
extern UINT32 gMAXLAUNCHABLES_READ;

/* CHRISL: Arrays to track ic group information. These allow us to determine which LBE slots control which pockets and
what LBE class the pockets are.*/
Expand Down Expand Up @@ -1781,7 +1802,8 @@ const INT16 icDefault[NUM_INV_SLOTS] = {
#define MAXATTACHMENTS 60000

extern INVTYPE Item[MAXITEMS];
extern UINT16 Attachment[MAXATTACHMENTS][4];
extern AttachmentStruct Attachment[MAXATTACHMENTS];
extern std::multimap<UINT16, AttachmentStruct> AttachmentBackmap;

//WarmSteel - Here we have some definitions for NAS
typedef struct
Expand Down
Loading