diff --git a/GameVersion.cpp b/GameVersion.cpp
index 5e336ad2..c878b97a 100644
--- a/GameVersion.cpp
+++ b/GameVersion.cpp
@@ -23,7 +23,7 @@ INT16 zVersionLabel[256] = { L"Beta v. 0.98" };
#else
//RELEASE BUILD VERSION
- INT16 zVersionLabel[256] = { L"Release v1.13.466" };
+ INT16 zVersionLabel[256] = { L"Release v1.13.472" };
#endif
diff --git a/Tactical/Item Types.h b/Tactical/Item Types.h
index 175c8a19..dcc2bc05 100644
--- a/Tactical/Item Types.h
+++ b/Tactical/Item Types.h
@@ -843,7 +843,7 @@ typedef enum
USE_ITEM_HARD
} MergeType;
-extern UINT16 Merge[MAXITEMS+1][4];
+extern UINT16 Merge[MAXITEMS+1][6];
typedef struct
{
diff --git a/Tactical/Items.cpp b/Tactical/Items.cpp
index f8a40443..caccef8d 100644
--- a/Tactical/Items.cpp
+++ b/Tactical/Items.cpp
@@ -1042,7 +1042,7 @@ UINT16 CompatibleFaceItems[MAXITEMS+1][2];// =
//};
-UINT16 Merge[MAXITEMS+1][4];// =
+UINT16 Merge[MAXITEMS+1][6];// =
//{ // first item second item resulting item, merge type
// {FIRSTAIDKIT, FIRSTAIDKIT, FIRSTAIDKIT, COMBINE_POINTS},
// {MEDICKIT, MEDICKIT, MEDICKIT, COMBINE_POINTS},
@@ -2120,7 +2120,7 @@ UINT16 GetLauncherFromLaunchable( UINT16 usLaunchable )
-BOOLEAN EvaluateValidMerge( UINT16 usMerge, UINT16 usItem, UINT16 * pusResult, UINT8 * pubType )
+BOOLEAN EvaluateValidMerge( UINT16 usMerge, UINT16 usItem, UINT16 * pusResult, UINT16 * pusResult2, UINT8 * pubType, UINT8 * pubAPCost )
{
// NB "usMerge" is the object being merged with (e.g. compound 18)
// "usItem" is the item being merged "onto" (e.g. kevlar vest)
@@ -2161,15 +2161,17 @@ BOOLEAN EvaluateValidMerge( UINT16 usMerge, UINT16 usItem, UINT16 * pusResult, U
}
}
*pusResult = Merge[iLoop][2];
- *pubType = (UINT8) Merge[iLoop][3];
+ *pusResult2 = Merge[iLoop][3];
+ *pubType = (UINT8) Merge[iLoop][4];
+ *pubAPCost = (UINT8) Merge[iLoop][5];
return( TRUE );
}
BOOLEAN ValidMerge( UINT16 usMerge, UINT16 usItem )
{
- UINT16 usIgnoreResult;
- UINT8 ubIgnoreType;
- return( EvaluateValidMerge( usMerge, usItem, &usIgnoreResult, &ubIgnoreType ) );
+ UINT16 usIgnoreResult, usIgnoreResult2;
+ UINT8 ubIgnoreType, ubIgnoreAPCost;
+ return( EvaluateValidMerge( usMerge, usItem, &usIgnoreResult, &usIgnoreResult2, &ubIgnoreType, &ubIgnoreAPCost ) );
}
UINT8 CalculateObjectWeight( OBJECTTYPE *pObject )
@@ -3151,9 +3153,9 @@ BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYP
BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYPE * pAttachment, BOOLEAN playSound )
{
INT8 bAttachPos, bSecondAttachPos;//, bAbility, bSuccess;
- UINT16 usResult;
+ UINT16 usResult, usResult2;
INT8 bLoop;
- UINT8 ubType, ubLimit;
+ UINT8 ubType, ubLimit, ubAPCost;
INT32 iCheckResult;
INT8 bAttachInfoIndex = -1, bAttachComboMerge;
BOOLEAN fValidLaunchable = FALSE;
@@ -3301,16 +3303,16 @@ BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYP
}
}
// check for merges
- else if (EvaluateValidMerge( pAttachment->usItem, pTargetObj->usItem, &usResult, &ubType ))
+ else if (EvaluateValidMerge( pAttachment->usItem, pTargetObj->usItem, &usResult, &usResult2, &ubType, &ubAPCost ))
{
if ( ubType != COMBINE_POINTS )
{
- if ( !EnoughPoints( pSoldier, AP_MERGE, 0, TRUE ) )
+ if ( !EnoughPoints( pSoldier, ubAPCost, 0, TRUE ) )
{
return( FALSE );
}
- DeductPoints( pSoldier, AP_MERGE, 0 );
+ DeductPoints( pSoldier, ubAPCost, 0 );
}
switch( ubType )
@@ -3337,6 +3339,9 @@ BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYP
StatChange( pSoldier, WISDOMAMT, 5, FALSE );
}
+
+ //Madd: note that use_item cannot produce two different items!!! so it doesn't use usResult2
+
//Madd: unload guns after merge if ammo caliber or mag size don't match
if ( Item[pTargetObj->usItem].usItemClass == IC_GUN && pTargetObj->usGunAmmoItem != NONE && pTargetObj->ubGunShotsLeft > 0 )
{
@@ -3462,6 +3467,7 @@ BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYP
// fall through
default:
// the merge will combine the two items
+ //Madd: usResult2 only works for standard merges -> item1 + item2 = item3 + item4
//Madd: unload guns after merge if ammo caliber or mag size don't match
if ( Item[pTargetObj->usItem].usItemClass == IC_GUN && pTargetObj->usGunAmmoItem != NONE && pTargetObj->ubGunShotsLeft > 0 )
@@ -3507,8 +3513,64 @@ BOOLEAN AttachObject( SOLDIERTYPE * pSoldier, OBJECTTYPE * pTargetObj, OBJECTTYP
{
pTargetObj->bStatus[0] = (pTargetObj->bStatus[0] + pAttachment->bStatus[0]) / 2;
}
- DeleteObj( pAttachment );
+
pTargetObj->ubWeight = CalculateObjectWeight( pTargetObj );
+
+ if ( usResult2 != NOTHING )
+ {
+ //Madd: usResult2 is what the original attachment/source item turns into
+
+ //Madd: unload guns after merge if ammo caliber or mag size don't match
+ if ( Item[pAttachment->usItem].usItemClass == IC_GUN && pAttachment->usGunAmmoItem != NONE && pAttachment->ubGunShotsLeft > 0 )
+ {
+ if ( Item[usResult2].usItemClass != IC_GUN || Weapon[Item[usResult2].ubClassIndex].ubCalibre != Weapon[Item[pAttachment->usItem].ubClassIndex].ubCalibre || pAttachment->ubGunShotsLeft > Weapon[Item[usResult2].ubClassIndex].ubMagSize )
+ { // item types/calibers/magazines don't match, spit out old ammo
+ OBJECTTYPE newObj;
+ CreateItem(pAttachment->usGunAmmoItem, 100, &newObj);
+ newObj.ubShotsLeft[0] = pAttachment->ubGunShotsLeft;
+ pAttachment->ubGunShotsLeft = 0;
+ pAttachment->usGunAmmoItem = NONE;
+ if ( !AutoPlaceObject( pSoldier, &newObj, FALSE ) )
+ { // put it on the ground
+ AddItemToPool( pSoldier->sGridNo, &newObj, 1, pSoldier->bLevel, 0 , -1 );
+ }
+ }
+ }
+
+ //Madd: remove any prohibited attachments
+ for (bAttachPos = 0; bAttachPos < MAX_ATTACHMENTS; bAttachPos++)
+ {
+ if (pAttachment->usAttachItem[ bAttachPos ] != NOTHING && !ValidAttachment(pAttachment->usAttachItem[ bAttachPos ],usResult2) && !ValidLaunchable(pAttachment->usAttachItem[ bAttachPos ],usResult2) )
+ {
+ if ( !Item[pAttachment->usAttachItem[ bAttachPos ]].inseparable )
+ {//remove it
+ OBJECTTYPE newObj;
+ RemoveAttachment(pAttachment,bAttachPos,&newObj);
+ if ( !AutoPlaceObject( pSoldier, &newObj, FALSE ) )
+ { // put it on the ground
+ AddItemToPool( pSoldier->sGridNo, &newObj, 1, pSoldier->bLevel, 0 , -1 );
+ }
+ }
+ else
+ {//destroy it
+ pAttachment->usAttachItem[bAttachPos] = NOTHING;
+ pAttachment->bAttachStatus[bAttachPos] = 0;
+ }
+ }
+ }
+
+
+
+ pAttachment->usItem = usResult2;
+ if ( ubType != TREAT_ARMOUR )
+ {
+ pAttachment->bStatus[0] = (pAttachment->bStatus[0] + pTargetObj->bStatus[0]) / 2;
+ }
+ pAttachment->ubWeight = CalculateObjectWeight( pAttachment );
+ }
+ else
+ DeleteObj( pAttachment );
+
if (pSoldier && pSoldier->bTeam == gbPlayerNum)
{
DoMercBattleSound( pSoldier, BATTLE_SOUND_COOL1 );
diff --git a/Tactical/Items.h b/Tactical/Items.h
index 8bf43ccd..c6c4f216 100644
--- a/Tactical/Items.h
+++ b/Tactical/Items.h
@@ -135,7 +135,7 @@ BOOLEAN ValidLaunchable( UINT16 usLaunchable, UINT16 usItem );
UINT16 GetLauncherFromLaunchable( UINT16 usLaunchable );
BOOLEAN ValidMerge( UINT16 usMerge, UINT16 usItem );
-BOOLEAN EvaluateValidMerge( UINT16 usMerge, UINT16 usItem, UINT16 * pusResult, UINT8 * pubType );
+BOOLEAN EvaluateValidMerge( UINT16 usMerge, UINT16 usItem, UINT16 * pusResult, UINT16 * pusResult2, UINT8 * pubType, UINT8 * pubAPCost );
// is the item passed a medical/ first aid kit? and what type?
diff --git a/Tactical/XML_Merge.cpp b/Tactical/XML_Merge.cpp
index b7c85db1..a4eaea9d 100644
--- a/Tactical/XML_Merge.cpp
+++ b/Tactical/XML_Merge.cpp
@@ -85,7 +85,9 @@ mergeStartElementHandle(void *userData, const char *name, const char **atts)
else if(pData->curElement == ELEMENT &&
(strcmp(name, "firstItemIndex") == 0 ||
strcmp(name, "secondItemIndex") == 0 ||
- strcmp(name, "resultingItemIndex") == 0 ||
+ strcmp(name, "firstResultingItemIndex") == 0 ||
+ strcmp(name, "secondResultingItemIndex") == 0 ||
+ strcmp(name, "APCost") == 0 ||
strcmp(name, "mergeType") == 0 ))
{
pData->curElement = ELEMENT_PROPERTY;
@@ -147,16 +149,26 @@ mergeEndElementHandle(void *userData, const char *name)
pData->curElement = ELEMENT;
pData->curMerge[1] = (UINT16) atol(pData->szCharData);
}
- else if(strcmp(name, "resultingItemIndex") == 0)
+ else if(strcmp(name, "firstResultingItemIndex") == 0)
{
pData->curElement = ELEMENT;
pData->curMerge[2] = (UINT16) atol(pData->szCharData);
}
- else if(strcmp(name, "mergeType") == 0)
+ else if(strcmp(name, "secondResultingItemIndex") == 0)
{
pData->curElement = ELEMENT;
pData->curMerge[3] = (UINT16) atol(pData->szCharData);
}
+ else if(strcmp(name, "mergeType") == 0)
+ {
+ pData->curElement = ELEMENT;
+ pData->curMerge[4] = (UINT16) atol(pData->szCharData);
+ }
+ else if(strcmp(name, "APCost") == 0)
+ {
+ pData->curElement = ELEMENT;
+ pData->curMerge[5] = (UINT16) atol(pData->szCharData);
+ }
pData->maxReadDepth--;
}
@@ -248,8 +260,10 @@ BOOLEAN WriteMergeStats()
FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][0]);
FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][1]);
- FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][2]);
- FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][3]);
+ FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][2]);
+ FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][3]);
+ FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][4]);
+ FilePrintf(hFile,"\t\t%d\r\n", Merge[cnt][5]);
FilePrintf(hFile,"\t\r\n");
}