From f8637e59725ff7af3445d5aa687fed48720c5ff9 Mon Sep 17 00:00:00 2001 From: sun-alf Date: Fri, 8 Sep 2023 21:53:38 +0300 Subject: [PATCH] [~] Performance optimizations around Attachment[] and Launchable[] arrays AIMNAS with its ~50K elements in Attachment[] suffered of performance drop when MOLLE stuff is in the visible inventory. To resolve it the following is done: * Introduce gMAXATTACHMENTS_READ with actual number of elements in Attachment[]; according refactoring. * Introduce gMAXLAUNCHABLES_READ with actual number of elements in Launchable[]; according refactoring. * Introduce std::multimap AttachmentBackmap for quick access to attachments using itemId as a key. * Sort Attachment[] by attachmentIndex right after loading from XML. According order in XML is not needed anymore. * Introduce FindAttachmentRange() for quick access to attachments using attachmentId as a key (binary search in Attachment[]). In a few words, GetHelpTextForItemInLaptop(), ValidAttachment(), SetAttachmentSlotsFlag() were heavily optimized. --- Laptop/BobbyRGuns.cpp | 155 +++++++++++++++-------------------- Tactical/Interface Items.cpp | 34 +++----- Tactical/Item Types.h | 24 +++++- Tactical/Items.cpp | 133 +++++++++++++++++++----------- Tactical/Items.h | 1 + Tactical/XML_Attachments.cpp | 41 ++++++--- Tactical/XML_Launchable.cpp | 6 +- 7 files changed, 224 insertions(+), 170 deletions(-) diff --git a/Laptop/BobbyRGuns.cpp b/Laptop/BobbyRGuns.cpp index 479a1ef7..01136a57 100644 --- a/Laptop/BobbyRGuns.cpp +++ b/Laptop/BobbyRGuns.cpp @@ -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; @@ -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; @@ -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 ); @@ -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) - { - if (wcslen( attachStr3 ) + wcslen(Item[usAttachment].szItemName) > 3800) - { - // 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); - } - } - } - - // Is the weapon we're checking the same as the one we're tooltipping? - usAttachment = 0; - if (Attachment[iLoop][1] == Item[usItemNumber].uiIndex) + std::pair::iterator, std::multimap::iterator> range; + std::multimap::iterator it; + range = AttachmentBackmap.equal_range(Item[usItemNumber].uiIndex); + for (it = range.first; it != range.second; it++) { - usAttachment = Attachment[iLoop][0]; - } - - // If the attachment is not hidden - if (usAttachment > 0 && !Item[ usAttachment ].hiddenaddon && !Item[ usAttachment ].hiddenattachment) - { - if (wcslen( attachStr3 ) + wcslen(Item[usAttachment].szItemName) > 3800) + UINT16 attachmentId = it->second.attachmentIndex; + if (!Item[attachmentId].hiddenaddon && !Item[attachmentId].hiddenattachment && ItemIsLegal(attachmentId, TRUE)) { - // 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[attachmentId].szItemName) == FALSE) + break; } } - - - iLoop++; - if (Attachment[iLoop][0] == 0 && Item[iLoop].usItemClass == 0) - { - // Reached end of list - break; - } } + else // old attachment system + { + for (UINT32 itemId = 1; itemId < gMAXITEMS_READ; itemId++) + { + // 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)) + { + fAttachmentsFound = TRUE; + if (DecorateAppendString(attachStr3, ATTACHMENTS_STRBUF_SIZE, Item[itemId].szItemName) == FALSE) + 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. diff --git a/Tactical/Interface Items.cpp b/Tactical/Interface Items.cpp index d71aa3ca..9b783204 100644 --- a/Tactical/Interface Items.cpp +++ b/Tactical/Interface Items.cpp @@ -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); @@ -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) { @@ -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 { @@ -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++; } diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h index 67e761d4..cdd3d2a1 100644 --- a/Tactical/Item Types.h +++ b/Tactical/Item Types.h @@ -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.*/ @@ -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 AttachmentBackmap; //WarmSteel - Here we have some definitions for NAS typedef struct diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp index ba9d4e00..dd56f7f7 100644 --- a/Tactical/Items.cpp +++ b/Tactical/Items.cpp @@ -566,7 +566,8 @@ AttachmentInfoStruct AttachmentInfo[MAXITEMS+1];// = AttachmentSlotStruct AttachmentSlots[MAXITEMS+1]; ItemReplacementStruct ItemReplacement[MAXATTACHMENTS]; -UINT16 Attachment[MAXATTACHMENTS][4];// = +AttachmentStruct Attachment[MAXATTACHMENTS];// = +std::multimap AttachmentBackmap; // key is itemId //{ // {SILENCER, GLOCK_17}, // {SILENCER, GLOCK_18}, @@ -2253,7 +2254,6 @@ INT32 GetAttachmentInfoIndex( UINT16 usItem ) //Determine if it is possible to add this attachment to the item. BOOLEAN ValidAttachment( UINT16 usAttachment, UINT16 usItem, UINT8 * pubAPCost ) { - INT32 iLoop = 0; if (pubAPCost) { *pubAPCost = (UINT8)APBPConstants[AP_RELOAD_GUN]; //default value } @@ -2269,40 +2269,26 @@ BOOLEAN ValidAttachment( UINT16 usAttachment, UINT16 usItem, UINT8 * pubAPCost ) *pubAPCost = Item[usAttachment].ubAttachToPointAPCost; return TRUE; } + // look for the section of the array pertaining to this attachment... - while( 1 ) - { - if (Attachment[iLoop][0] == usAttachment) - { - break; - } - ++iLoop; - if (Attachment[iLoop][0] == 0) - { - // the proposed item cannot be attached to anything! - return( FALSE ); - } - } + UINT32 startIndex = 0, endIndex = 0; + if (FindAttachmentRange(usAttachment, &startIndex, &endIndex) == FALSE) + return FALSE; + // now look through this section for the item in question - while( 1 ) + for (UINT32 iLoop = startIndex; iLoop <= endIndex; iLoop++) { - if (Attachment[iLoop][1] == usItem) + if (Attachment[iLoop].itemIndex == usItem) { - if ( UsingNewAttachmentSystem( ) || Attachment[iLoop][3] != 1 ) + if ( UsingNewAttachmentSystem( ) || Attachment[iLoop].NASOnly != 1 ) { if (pubAPCost) - *pubAPCost = (UINT8)Attachment[iLoop][2]; //Madd: get ap cost of attaching items :) - break; + *pubAPCost = (UINT8)Attachment[iLoop].APCost; //Madd: get ap cost of attaching items :) } - } - ++iLoop; - if (Attachment[iLoop][0] != usAttachment) - { - // the proposed item cannot be attached to the item in question - return( FALSE ); + return TRUE; } } - return( TRUE ); + return FALSE; } BOOLEAN ValidAttachment( UINT16 usAttachment, OBJECTTYPE * pObj, UINT8 * pubAPCost, UINT8 subObject, std::vector usAttachmentSlotIndexVector) @@ -5677,40 +5663,40 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac UINT64 SetAttachmentSlotsFlag(OBJECTTYPE* pObj) { UINT64 uiSlotFlag = 0; - UINT32 uiLoop = 0; - UINT32 fItem; if (pObj->exists() == false) return 0; - UINT64 point = GetAvailableAttachmentPoint(pObj, 0); - - while (uiLoop < gMAXITEMS_READ && Item[uiLoop].usItemClass != 0 || - uiLoop < MAXATTACHMENTS && Attachment[uiLoop][0] != 0 || - uiLoop < MAXITEMS + 1 && Launchable[uiLoop][0] != 0) + if (UsingNewAttachmentSystem()) { - if (uiLoop > 0 && uiLoop < gMAXITEMS_READ && IsAttachmentPointAvailable(point, uiLoop, TRUE)) + std::pair::iterator, std::multimap::iterator> range; + std::multimap::iterator it; + range = AttachmentBackmap.equal_range(pObj->usItem); + for (it = range.first; it != range.second; it++) { - fItem = uiLoop; - if (fItem && ItemIsLegal(fItem, TRUE)) - uiSlotFlag |= Item[fItem].nasAttachmentClass; + UINT16 attachmentId = it->second.attachmentIndex; + if (ItemIsLegal(attachmentId, TRUE)) + uiSlotFlag |= Item[attachmentId].nasAttachmentClass; } - if (uiLoop < MAXATTACHMENTS && Attachment[uiLoop][1] == pObj->usItem) + for (UINT32 i = 0; i < gMAXLAUNCHABLES_READ; i++) { - fItem = Attachment[uiLoop][0]; - if (fItem && ItemIsLegal(fItem, TRUE)) - uiSlotFlag |= Item[fItem].nasAttachmentClass; + if (Launchable[i][1] == pObj->usItem) + { + UINT16 attachmentId = Launchable[i][0]; + if (ItemIsLegal(attachmentId, TRUE)) + uiSlotFlag |= Item[attachmentId].nasAttachmentClass; + } } - - if (uiLoop < MAXITEMS + 1 && Launchable[uiLoop][1] == pObj->usItem) + } + else + { + UINT64 point = GetAvailableAttachmentPoint(pObj, 0); + for (UINT32 itemId = 1; itemId < gMAXITEMS_READ; itemId++) { - fItem = Launchable[uiLoop][0]; - if (fItem && ItemIsLegal(fItem, TRUE)) - uiSlotFlag |= Item[fItem].nasAttachmentClass; + if (ItemIsLegal(itemId, TRUE) && IsAttachmentPointAvailable(point, itemId, TRUE)) + uiSlotFlag |= Item[itemId].nasAttachmentClass; } - - uiLoop++; } return uiSlotFlag; @@ -16028,3 +16014,52 @@ UINT16 GetLaunchableOfExplosionType(UINT16 launcher, UINT8 explosionType) } return NOTHING; } + +BOOLEAN FindAttachmentRange(UINT16 usAttachment, UINT32* pStartIndex, UINT32* pEndIndex) +{ + BOOLEAN result = FALSE; + + INT32 leftMargin = 0; + INT32 rightMargin = (INT32)gMAXATTACHMENTS_READ - 1; + INT32 middle = 0; + // use binary search to locate the group of elements for given attachment item Id (usAttachment) + while (leftMargin <= rightMargin) + { + middle = leftMargin + (rightMargin - leftMargin) / 2; + + if (Attachment[middle].attachmentIndex == usAttachment) + { + result = TRUE; + break; + } + else if (Attachment[middle].attachmentIndex < usAttachment) + leftMargin = middle + 1; + else + rightMargin = middle - 1; + } + + if (result) + { + // now middle is an index somewhere within the group, seek for beginning and ending of the group + if (pStartIndex) + { + *pStartIndex = (UINT32)middle; + for (INT32 i = middle - 1; i >= leftMargin; i--) + if (Attachment[i].attachmentIndex == usAttachment) + *pStartIndex = (UINT32)i; + else + break; + } + if (pEndIndex) + { + *pEndIndex = (UINT32)middle; + for (INT32 i = middle + 1; i <= rightMargin; i++) + if (Attachment[i].attachmentIndex == usAttachment) + *pEndIndex = (UINT32)i; + else + break; + } + } + + return result; +} diff --git a/Tactical/Items.h b/Tactical/Items.h index bc0c49c6..ce23180f 100644 --- a/Tactical/Items.h +++ b/Tactical/Items.h @@ -568,6 +568,7 @@ INT32 GetPercentRangeBonus( OBJECTTYPE * pObj ); UINT8 GetInventorySleepModifier( SOLDIERTYPE *pSoldier ); void AttachDefaultAttachments(OBJECTTYPE *pObj, BOOLEAN fAllDefaultAttachments=TRUE);//dnl ch75 261013 +BOOLEAN FindAttachmentRange(UINT16 usAttachment, UINT32* pStartIndex, UINT32* pEndIndex); // Flugente: is this object useable by militia? BOOLEAN ObjectIsMilitiaRelevant( OBJECTTYPE *pObj ); diff --git a/Tactical/XML_Attachments.cpp b/Tactical/XML_Attachments.cpp index 7eaa8936..fdb28fc9 100644 --- a/Tactical/XML_Attachments.cpp +++ b/Tactical/XML_Attachments.cpp @@ -20,6 +20,8 @@ struct } typedef attachmentParseData; +UINT32 gMAXATTACHMENTS_READ = 0; + static void XMLCALL attachmentStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts) { @@ -93,9 +95,9 @@ attachmentEndElementHandle(void *userData, const XML_Char *name) if(pData->curIndex < pData->maxArraySize) { //DebugMsg(TOPIC_JA2, DBG_LEVEL_3,"AttachmentStartElementHandle: writing attachment to array"); - Attachment[pData->curIndex][0] = pData->curAttachment[0]; //write the attachment into the table - Attachment[pData->curIndex][1] = pData->curAttachment[1]; - Attachment[pData->curIndex][2] = pData->curAttachment[2]; + Attachment[pData->curIndex].attachmentIndex = pData->curAttachment[0]; //write the attachment into the table + Attachment[pData->curIndex].itemIndex = pData->curAttachment[1]; + Attachment[pData->curIndex].APCost = pData->curAttachment[2]; } } else if(strcmp(name, "attachmentIndex") == 0) @@ -127,7 +129,25 @@ attachmentEndElementHandle(void *userData, const XML_Char *name) } +static void MapAttachments() +{ + std::list stdList; + std::list::iterator it; + UINT32 i = 0; + for (i = 0; i < gMAXATTACHMENTS_READ; i++) + { + stdList.push_back(Attachment[i]); + AttachmentBackmap.insert(std::make_pair(Attachment[i].itemIndex, Attachment[i])); + } + + stdList.sort(); + + for (it = stdList.begin(), i = 0; it != stdList.end(); it++, i++) + { + Attachment[i] = *it; + } +} BOOLEAN ReadInAttachmentStats(STR fileName) { @@ -171,7 +191,6 @@ BOOLEAN ReadInAttachmentStats(STR fileName) XML_SetUserData(parser, &pData); - if(!XML_Parse(parser, lpcBuffer, uiFSize, TRUE)) { CHAR8 errorBuf[511]; @@ -183,13 +202,15 @@ BOOLEAN ReadInAttachmentStats(STR fileName) return FALSE; } + gMAXATTACHMENTS_READ = pData.curIndex + 1; + MapAttachments(); + MemFree(lpcBuffer); - - XML_ParserFree(parser); return( TRUE ); } + BOOLEAN WriteAttachmentStats() { HWFILE hFile; @@ -208,10 +229,10 @@ BOOLEAN WriteAttachmentStats() { FilePrintf(hFile,"\t\r\n"); - FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt][0]); - FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt][1]); - FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt][2]); - FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt][3]); + FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt].attachmentIndex); + FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt].itemIndex); + FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt].APCost); + FilePrintf(hFile,"\t\t%d\r\n", Attachment[cnt].NASOnly); FilePrintf(hFile,"\t\r\n"); } diff --git a/Tactical/XML_Launchable.cpp b/Tactical/XML_Launchable.cpp index bec05f33..26994d2d 100644 --- a/Tactical/XML_Launchable.cpp +++ b/Tactical/XML_Launchable.cpp @@ -19,6 +19,8 @@ struct } typedef launchableParseData; +UINT32 gMAXLAUNCHABLES_READ = 0; + static void XMLCALL launchableStartElementHandle(void *userData, const XML_Char *name, const XML_Char **atts) { @@ -168,9 +170,9 @@ BOOLEAN ReadInLaunchableStats(STR fileName) return FALSE; } + gMAXLAUNCHABLES_READ = pData.curIndex + 1; + MemFree(lpcBuffer); - - XML_ParserFree(parser); return( TRUE );