mirror of
https://github.com/1dot13/source.git
synced 2026-08-05 14:00:23 +02:00
HAM5.5b2 merged in!
Notes: -There may still be bugs!! (In fact, I almost guarantee it -- there's -Ammo box code added to HR's crate code -Splitting a crate/box also automatically refills half empty magazines -new pathing arrows for map screen not included -code for scouts to know where enemies are going doesn't appear to work... but i'm not sure it was completed. -lots of gobledy gook (chinese?) comments turned back to english -also added Bob's popups -other languages besides english still need to have there language.cpp files updated with array changes -AI enhancements by Warmsteel (reloading, suppression, roaming, avoiding gas, and other fixes) git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@5181 3b4a5df2-a311-0410-b5c6-a8a6f20db521
This commit is contained in:
+384
-19
@@ -55,6 +55,9 @@
|
||||
#include "debug control.h"
|
||||
|
||||
#include "math.h"
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
#include <map>
|
||||
#include "popup_definition.h"
|
||||
#endif
|
||||
|
||||
#ifdef JA2UB
|
||||
@@ -72,9 +75,19 @@ class SOLDIERTYPE;
|
||||
void SetNewItem( SOLDIERTYPE *pSoldier, UINT8 ubInvPos, BOOLEAN fNewItem );
|
||||
|
||||
extern SOLDIERTYPE *gpItemDescSoldier;
|
||||
// HEADROCK HAM 5: We need access to these values for item transformation purposes
|
||||
extern BOOLEAN gfItemDescObjectIsAttachment;
|
||||
extern OBJECTTYPE *gpItemDescObject;
|
||||
extern OBJECTTYPE *gpItemDescPrevObject;
|
||||
extern OBJECTTYPE *gpItemDescOrigAttachmentObject;
|
||||
extern OBJECTTYPE gCloneItemDescObject;
|
||||
extern BOOLEAN fShowMapInventoryPool;
|
||||
extern UINT32 guiCurrentItemDescriptionScreen;
|
||||
extern BOOLEAN AutoPlaceObjectInInventoryStash( OBJECTTYPE *pItemPtr, INT32 sGridNo );
|
||||
// HEADROCK HAM 5: Also need these to trigger Map Inventory changes appropriately.
|
||||
extern BOOLEAN fMapInventoryZoom;
|
||||
// HEADROCK HAM 5: And this, for checking whether an item is in the pool.
|
||||
extern std::vector<WORLDITEM> pInventoryPoolList;
|
||||
|
||||
UINT16 OldWayOfCalculatingScopeBonus(SOLDIERTYPE *pSoldier);
|
||||
// weight units are 100g each
|
||||
@@ -1154,6 +1167,8 @@ ComboMergeInfoStruct AttachmentComboMerge[MAXITEMS+1];// =
|
||||
// {NOTHING, {NOTHING, NOTHING}, NOTHING },
|
||||
//};
|
||||
|
||||
// HEADROCK HAM 5: Item Transformations table, containing all possible Transformations.
|
||||
TransformInfoStruct Transform[MAXITEMS+1];
|
||||
|
||||
UINT16 IncompatibleAttachments[MAXATTACHMENTS][2];// =
|
||||
//{
|
||||
@@ -1223,6 +1238,9 @@ std::vector<LBETYPE> LoadBearingEquipment;
|
||||
std::vector<POCKETTYPE> LBEPocketType;
|
||||
//TODO make the indices of this a define, because I do not know what is a large pocket (I guess 3)
|
||||
|
||||
// THE_BOB : added for pocket popup definitions
|
||||
std::map<UINT8,popupDef> LBEPocketPopup;
|
||||
|
||||
//POCKETTYPE LBEPocketType[MAXITEMS+1]; //=
|
||||
//{
|
||||
// { /* Blank Entry */ 0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} },
|
||||
@@ -4761,7 +4779,8 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, 0);
|
||||
|
||||
//AutoPlaceObject( pAttachment );
|
||||
//ADB ubWeight has been removed, see comments in OBJECTTYPE
|
||||
@@ -4866,7 +4885,7 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -4923,7 +4942,8 @@ BOOLEAN OBJECTTYPE::AttachObjectNAS( SOLDIERTYPE * pSoldier, OBJECTTYPE * pAttac
|
||||
|
||||
//WarmSteel - Replaced this with one that also checks default attachments, otherwise you could not replace built-in bonuses with default inseperable attachments.
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usResult);
|
||||
ReInitMergedItem(pSoldier, this, usOldItem);
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, subObject);
|
||||
|
||||
if ( ubType != TREAT_ARMOUR )
|
||||
{
|
||||
@@ -5296,7 +5316,9 @@ void RemoveProhibitedAttachments(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16
|
||||
//WarmSteel - Needed for merges, because the new items don't get their new default attachments.
|
||||
//This does the same as RemoveProhibitedAttachments but is a bit more thorough at it.
|
||||
//This is at the risk that items move around if more than one slot is valid, but since this is used for "new" guns after merges, that's acceptable.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem){
|
||||
// HEADROCK HAM 5: Added argument for statusindex.
|
||||
void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem, UINT8 ubStatusIndex)
|
||||
{
|
||||
|
||||
attachmentList tempAttachList;
|
||||
attachmentList tempSlotChangingAttachList;
|
||||
@@ -5304,18 +5326,18 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
UINT8 slotCount;
|
||||
std::vector<UINT16> usAttachmentSlotIndexVector = GetItemSlots(pObj);
|
||||
|
||||
if( !(*pObj)[0]->attachments.empty() ){
|
||||
if( !(*pObj)[ubStatusIndex]->attachments.empty() ){
|
||||
//Have to take all attachments off, because of possible incompatibilities with the default attachments (can't NOT attach a default attachment because some stupid item already attached is incompatible with it).
|
||||
|
||||
//Delete all default inseperable attachments from the old gun.
|
||||
//This is safe UNLESS the inseparable default attachments is not the only attachment of the same kind on the gun.
|
||||
//I can't think of any reason why this would happen, and if it does the worst that can happen is your attachment disappearing.
|
||||
for(slotCount = 0; slotCount < (*pObj)[0]->attachments.size(); slotCount++){
|
||||
UINT16 usAttach = (*pObj)[0]->GetAttachmentAtIndex(slotCount)->usItem;
|
||||
for(slotCount = 0; slotCount < (*pObj)[ubStatusIndex]->attachments.size(); slotCount++){
|
||||
UINT16 usAttach = (*pObj)[ubStatusIndex]->GetAttachmentAtIndex(slotCount)->usItem;
|
||||
if(Item[usAttach].inseparable){
|
||||
for(UINT16 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS && Item[usOldItem].defaultattachments[cnt] != 0; cnt++){
|
||||
if(Item[usOldItem].defaultattachments[cnt] == usAttach){
|
||||
(*pObj)[0]->RemoveAttachmentAtIndex(slotCount);
|
||||
(*pObj)[ubStatusIndex]->RemoveAttachmentAtIndex(slotCount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -5323,36 +5345,38 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
}
|
||||
slotCount = 0;
|
||||
//Put all other attachments into a temporary storage, so we can try to re-attach later.
|
||||
for(attachmentList::iterator iter = (*pObj)[0]->attachments.begin(); iter != (*pObj)[0]->attachments.end(); iter++, slotCount++) {
|
||||
for(attachmentList::iterator iter = (*pObj)[ubStatusIndex]->attachments.begin(); iter != (*pObj)[ubStatusIndex]->attachments.end(); iter++, slotCount++) {
|
||||
if(iter->exists()){
|
||||
UINT16 cnt = 0;
|
||||
tempAttachList.push_back((*iter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//clear the attachment list, we've saved the attachments somewhere safe now.
|
||||
(*pObj)[0]->attachments.clear();
|
||||
(*pObj)[ubStatusIndex]->attachments.clear();
|
||||
|
||||
//Make sure the attachment slot data is correct.
|
||||
//std::vector<UINT16> tempItemSlots = GetItemSlots(pObj);
|
||||
(*pObj)[0]->attachments.resize(usAttachmentSlotIndexVector.size());
|
||||
(*pObj)[ubStatusIndex]->attachments.resize(usAttachmentSlotIndexVector.size());
|
||||
//pObj->usAttachmentSlotIndexVector = tempItemSlots;
|
||||
|
||||
|
||||
//Now add all default attachments, but add them with the same status as the gun. We don't want to make repairing guns easy :)
|
||||
for(UINT16 cnt = 0; cnt < MAX_DEFAULT_ATTACHMENTS && Item[pObj->usItem].defaultattachments[cnt] != 0; cnt++){
|
||||
//Only add inseparable default attachments, because they are likely "part" of the gun.
|
||||
if(Item[Item[pObj->usItem].defaultattachments[cnt]].inseparable){
|
||||
static OBJECTTYPE defaultAttachment;
|
||||
CreateItem(Item [ pObj->usItem ].defaultattachments[cnt],(*pObj)[0]->data.objectStatus,&defaultAttachment);
|
||||
AssertMsg(pObj->AttachObject(NULL,&defaultAttachment, FALSE, 0, -1, FALSE), "A default attachment could not be attached after merging, this should not be possible.");
|
||||
CreateItem(Item [ pObj->usItem ].defaultattachments[cnt],(*pObj)[ubStatusIndex]->data.objectStatus,&defaultAttachment);
|
||||
AssertMsg(pObj->AttachObject(NULL,&defaultAttachment, FALSE, ubStatusIndex, -1, FALSE), "A default attachment could not be attached after merging, this should not be possible.");
|
||||
}
|
||||
}
|
||||
|
||||
//First re-attach any slot-changing attachments.
|
||||
for (attachmentList::iterator iter = tempSlotChangingAttachList.begin(); iter != tempSlotChangingAttachList.end();) {
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE )){
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex )){
|
||||
//This seems to be rather valid. Can't be 100% sure though.
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE)){
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE, ubStatusIndex)){
|
||||
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
|
||||
iter = tempSlotChangingAttachList.erase(iter);
|
||||
} else {
|
||||
@@ -5365,9 +5389,9 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
|
||||
//Time to re-attach the other attachments, if we can. I am the king of copy pasta.
|
||||
for (attachmentList::iterator iter = tempAttachList.begin(); iter != tempAttachList.end();) {
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE)){
|
||||
if( ValidItemAttachmentSlot(pObj, iter->usItem, TRUE, FALSE, ubStatusIndex)){
|
||||
//This seems to be rather valid. Can't be 100% sure though.
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE)){
|
||||
if(pObj->AttachObject(NULL, &(*iter), FALSE, ubStatusIndex)){
|
||||
//Ok now we can be sure, lets remove this object so we don't try to drop it later.
|
||||
iter = tempAttachList.erase(iter);
|
||||
} else {
|
||||
@@ -5385,7 +5409,9 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
if (pSoldier) {
|
||||
if ( !AutoPlaceObject( pSoldier, &(*iter), FALSE ) )
|
||||
{ // put it on the ground
|
||||
AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
// HEADROCK HAM 5: A much more suitable function. Works in both tactical and mapscreen!
|
||||
AutoPlaceObjectToWorld( pSoldier, &(*iter), true );
|
||||
//AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5397,11 +5423,14 @@ void ReInitMergedItem(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT16 usOldItem)
|
||||
if (pSoldier) {
|
||||
if ( !AutoPlaceObject( pSoldier, &(*iter), FALSE ) )
|
||||
{ // put it on the ground
|
||||
AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
// HEADROCK HAM 5: A much more suitable function. Works in both tactical and mapscreen!
|
||||
AutoPlaceObjectToWorld( pSoldier, &(*iter), true );
|
||||
//AddItemToPool( pSoldier->sGridNo, &(*iter), 1, pSoldier->pathing.bLevel, 0 , -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EjectAmmoAndPlace(SOLDIERTYPE* pSoldier, OBJECTTYPE* pObj, UINT8 subObject)
|
||||
@@ -12597,3 +12626,339 @@ FLOAT GetItemCooldownFactor( OBJECTTYPE * pObj )
|
||||
|
||||
return cooldownfactor;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// HEADROCK HAM 5: Item Transformation.
|
||||
// Item Transformation is a new way to interact with items. Where Merges combine two items into one, a Transformation
|
||||
// can turn one item into another item, or into more than one item.
|
||||
// To instigate a Transformation, the player uses a menu to choose the desired effect. Then the program comes here to
|
||||
// see how it's done.
|
||||
// The instructions for performing a specific transformation are drawn from XML and fed into this function as a pointer.
|
||||
// They tell us what items will result from this transformation, as well as the APBP cost.
|
||||
|
||||
BOOLEAN OBJECTTYPE::TransformObject( SOLDIERTYPE * pSoldier, UINT8 ubStatusIndex, TransformInfoStruct * Transform, OBJECTTYPE *pParent )
|
||||
{
|
||||
// The argument "Transform" is a pointer to an entry in the Transformation Data array. By looking at the pointer we
|
||||
// can determine all the data we need. Therefore, this pointer must not be null!
|
||||
AssertMsg( Transform != NULL, String( "OBJECTTYPE::TransformObject attempt with invalid Transformation data." ) );
|
||||
|
||||
// Booleans to track what happened during the transformation.
|
||||
BOOLEAN fSplit = FALSE;
|
||||
BOOLEAN fDropped = FALSE;
|
||||
BOOLEAN fRemoved = FALSE;
|
||||
BOOLEAN fItemInPool = FALSE;
|
||||
|
||||
// This boolean tracks whether we've managed to place an item in a soldier's inventory.
|
||||
BOOLEAN fFoundPlaceInInventory = FALSE;
|
||||
|
||||
// Constants for storing details about the original item.
|
||||
OBJECTTYPE TempItem;
|
||||
UINT16 usOrigItem = this->usItem;
|
||||
UINT32 uiOrigClass = Item[this->usItem].usItemClass;
|
||||
UINT8 ubOrigNumObjects = this->ubNumberOfObjects;
|
||||
|
||||
UINT16 usAPCost = 0;
|
||||
INT32 iBPCost = 0;
|
||||
|
||||
// An array to store all result items.
|
||||
UINT16 usResult[MAX_NUM_TRANSFORMATION_RESULTS];
|
||||
UINT32 iNumResults = 0;
|
||||
|
||||
// Start reading transformation data with APBP costs.
|
||||
usAPCost = Transform->usAPCost;
|
||||
iBPCost = Transform->iBPCost;
|
||||
|
||||
// Check whether our soldier can afford this transformation!
|
||||
if (!EnoughPoints( pSoldier, (INT16)usAPCost, iBPCost, true ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Soldier can afford the transformation. Deduct APBP as necessary.
|
||||
DeductPoints( pSoldier, (INT16)usAPCost, iBPCost, false );
|
||||
}
|
||||
|
||||
// Read all result items for this transformation. Record them into an array.
|
||||
for (UINT32 curResult = 0; curResult < MAX_NUM_TRANSFORMATION_RESULTS; curResult++)
|
||||
{
|
||||
if (Transform->usResult[curResult] > 0)
|
||||
{
|
||||
usResult[curResult] = Transform->usResult[curResult];
|
||||
// Count the number of valid result items
|
||||
iNumResults++;
|
||||
}
|
||||
}
|
||||
|
||||
// If there are no result items, the Transformation is illegal - we need at least one resulting item!
|
||||
AssertMsg( iNumResults, String( "OBJECTTYPE::TransformObject attempting to transform an object which has no resulting items defined!" ) );
|
||||
|
||||
if (iNumResults > 1)
|
||||
{
|
||||
fSplit = TRUE;
|
||||
}
|
||||
|
||||
// Play a gun-cocking sound, it's the best one we've got ATM.
|
||||
PlayJA2Sample( ATTACH_TO_GUN, RATE_11025, SoundVolume( MIDVOLUME, pSoldier->sGridNo ), 1, SoundDir( pSoldier->sGridNo ) );
|
||||
|
||||
// Before we continue, lets check whether our object is in the sector inventory.
|
||||
// Is the sector inventory open?
|
||||
if (fShowMapInventoryPool)
|
||||
{
|
||||
// Is our object currently in the pool?
|
||||
for (UINT32 x = 0; x < pInventoryPoolList.size(); x++)
|
||||
{
|
||||
if (pInventoryPoolList[x].object.exists())
|
||||
{
|
||||
if (&(pInventoryPoolList[x].object) == this)
|
||||
{
|
||||
// Aha! In that case, all transformations will be done directly at the sector pool,
|
||||
// with multiple results ending on the ground rather than in the inventory.
|
||||
fItemInPool = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// The Transformation itself
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// We're going to do the transformation in steps, going hierarchially down from the item's own attachments,
|
||||
// to itsself, then its parents, and finally resulting items and unrelated inventory.
|
||||
// Note that we'll need to change the item's usItem property several times during this process, so lets
|
||||
// record its original usItem now.
|
||||
UINT16 usOldItem = this->usItem;
|
||||
|
||||
// STEP 1: Attachments and subsidiary objects.
|
||||
|
||||
// First of all, if the original item is a gun, we'll need to see if it can hold the same magazine after the
|
||||
// transformation. If it can't, the magazine will be ejected immediately into the soldier's inventory.
|
||||
|
||||
// Is this a gun, AND does it have any ammo loaded?
|
||||
if ( Item[this->usItem].usItemClass == IC_GUN && (*this)[ubStatusIndex]->data.gun.usGunAmmoItem != NONE && (*this)[ubStatusIndex]->data.gun.ubGunShotsLeft > 0 )
|
||||
{
|
||||
// Is the resulting item not a gun, OR is the resulting item of a different caliber, OR is the resulting item's
|
||||
// magazine too small?
|
||||
if ( Item[usResult[0]].usItemClass != IC_GUN || Weapon[Item[usResult[0]].ubClassIndex].ubCalibre != Weapon[Item[this->usItem].ubClassIndex].ubCalibre || (*this)[ubStatusIndex]->data.gun.ubGunShotsLeft > Weapon[Item[usResult[0]].ubClassIndex].ubMagSize )
|
||||
{
|
||||
// item types/calibers/magazines don't match, spit out old ammo
|
||||
EjectAmmoAndPlace(pSoldier, this);
|
||||
}
|
||||
}
|
||||
|
||||
// STEP 2: Check the item's attachments to see whether they still fit.
|
||||
// We'll have to fool this function into thinking we've already changed the item.
|
||||
// Note that this function automatically drops invalid attachments to the ground.
|
||||
this->usItem = usResult[0];
|
||||
// Repeat for each object in the stack.
|
||||
for ( UINT8 x = 0; x < this->ubNumberOfObjects; x++ )
|
||||
{
|
||||
ReInitMergedItem(pSoldier, this, usOldItem, x);
|
||||
}
|
||||
this->usItem = usOldItem;
|
||||
|
||||
//RemoveProhibitedAttachments(pSoldier, this, usOldItem);
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// TRANSFORM
|
||||
this->usItem = usResult[0];
|
||||
// Record the new itemclass
|
||||
UINT32 uiNewClass = Item[this->usItem].usItemClass;
|
||||
// Make a clone of this object, so that we can point the DescBox to it later if we run into any problems.
|
||||
gCloneItemDescObject = *(this);
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////
|
||||
// Placement checks
|
||||
|
||||
// Is the item an attachment? If so, check its parent to see if it's still compatible.
|
||||
if (pParent != NULL)
|
||||
{
|
||||
// When transforming an attachment, "THIS" is actually a copy of the object, called Object2. So transforming
|
||||
// "this" would only yield, at most, a superficial change (Description Box will change). The attachment item
|
||||
// itself will not change at all.
|
||||
|
||||
// Lets change the attachment item directly, then.
|
||||
gpItemDescOrigAttachmentObject->usItem = usResult[0];
|
||||
// Make a copy of it, so we know what data it contained.
|
||||
OBJECTTYPE pClone = *gpItemDescOrigAttachmentObject;
|
||||
|
||||
// Test the parent now. See whether all attachments are still valid on it.
|
||||
ReInitMergedItem(pSoldier, pParent, pParent->usItem, ubStatusIndex);
|
||||
|
||||
gpItemDescOrigAttachmentObject = NULL;
|
||||
|
||||
// After reiniting the attachments on the parent, "this" still exists, but the actual object is gone.
|
||||
// Lets look through the parent's attachments list, and see if we can find it again.
|
||||
UINT8 ubNewAttachmentsIndex = 0;
|
||||
for(attachmentList::iterator iter = (*pParent)[ubStatusIndex]->attachments.begin(); iter != (*pParent)[ubStatusIndex]->attachments.end(); iter++, ubNewAttachmentsIndex++)
|
||||
{
|
||||
if(iter->exists())
|
||||
{
|
||||
// Compare it to the clone we made earlier.
|
||||
if (*(iter) == pClone)
|
||||
{
|
||||
// Yes, here it is!
|
||||
gpItemDescOrigAttachmentObject = (*pParent)[ubStatusIndex]->GetAttachmentAtIndex( ubNewAttachmentsIndex );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Have we failed to find our item on the reinited parent?
|
||||
if (gpItemDescOrigAttachmentObject == NULL)
|
||||
{
|
||||
// It has been removed. Lets reset all the Description Box extra variables.
|
||||
// Note that by doing this, we actually trigger closing the description box later down the line.
|
||||
pParent = NULL;
|
||||
gfItemDescObjectIsAttachment = NULL;
|
||||
gpItemDescPrevObject = NULL;
|
||||
fRemoved = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Our object is not an attachment. If it is on a soldier, it may still not fit in the pocket where
|
||||
// it is currently placed, so lets see if we have to move it.
|
||||
else if (!fItemInPool)
|
||||
{
|
||||
for (INT8 bPocket = HELMETPOS; bPocket < NUM_INV_SLOTS; bPocket++)
|
||||
{
|
||||
if (&(pSoldier->inv[bPocket]) == this)
|
||||
{
|
||||
// Found our item. Does it fit in this slot?
|
||||
if (!CanItemFitInPosition(pSoldier, this, bPocket, FALSE) )
|
||||
{
|
||||
if (!AutoPlaceObject( pSoldier, this, TRUE ))
|
||||
{
|
||||
fDropped = TRUE;
|
||||
|
||||
AutoPlaceObjectToWorld( pSoldier, this, TRUE );
|
||||
|
||||
//Unfortunately the above function will not erase the item in tactical mode, so lets
|
||||
//double-check.
|
||||
if (pSoldier->inv[bPocket].exists() )
|
||||
{
|
||||
DeleteObj( &(pSoldier->inv[bPocket]) );
|
||||
}
|
||||
}
|
||||
// Whatever we've done with it, THIS is no longer a valid item, so lets
|
||||
// fool the desc box by switching it with the clone.
|
||||
gpItemDescObject = &gCloneItemDescObject;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If either the new or old items were LBEs, lets check the entire LBE inventory for item-size compatibility!
|
||||
//if (uiOrigClass & IC_LBEGEAR || uiNewClass & IC_LBEGEAR )
|
||||
if (!fItemInPool)
|
||||
{
|
||||
for (INT8 bPocket = HELMETPOS; bPocket < NUM_INV_SLOTS; bPocket++)
|
||||
{
|
||||
if (pSoldier->inv[bPocket].exists())
|
||||
{
|
||||
// Found an item. Does it still fit inside its own slot?
|
||||
if (!CanItemFitInPosition(pSoldier, &(pSoldier->inv[bPocket]), bPocket, FALSE) )
|
||||
{
|
||||
if (!AutoPlaceObject( pSoldier, &(pSoldier->inv[bPocket]), TRUE ))
|
||||
{
|
||||
fDropped = TRUE;
|
||||
|
||||
AutoPlaceObjectToWorld( pSoldier, &(pSoldier->inv[bPocket]), TRUE );
|
||||
|
||||
//Unfortunately the above function will not erase the item in tactical mode, so lets
|
||||
//double-check.
|
||||
if (pSoldier->inv[bPocket].exists() )
|
||||
{
|
||||
DeleteObj( &(pSoldier->inv[bPocket]) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Multiple Results
|
||||
//
|
||||
// If the item has several transformation results defined, that means we're going to split it into two or
|
||||
// more items.
|
||||
|
||||
// We actually start with any results above the first. This occurs if the item is split into two or more other
|
||||
// items. We'll try to place them in the pSoldier's inventory if possible, otherwise they are dumped to the
|
||||
// sector pool.
|
||||
|
||||
// Iterate through the results array we've constructed earlier.
|
||||
for (UINT32 x = 1; x < iNumResults; x++)
|
||||
{
|
||||
for (UINT32 y = 0; y < ubOrigNumObjects; y++)
|
||||
{
|
||||
// Create the result item. Set its condition to match that of the original.
|
||||
CreateItem( usResult[x], (*this)[ubStatusIndex]->data.objectStatus, &gTempObject );
|
||||
|
||||
if (!fItemInPool)
|
||||
{
|
||||
// Try placing it in the soldier's invnetory.
|
||||
if (!AutoPlaceObject( pSoldier, &gTempObject, TRUE ))
|
||||
{
|
||||
// Failed to find a place in the inventory. Dump to sector pool.
|
||||
AutoPlaceObjectToWorld( pSoldier, &gTempObject, true );
|
||||
|
||||
fDropped = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AutoPlaceObjectToWorld( pSoldier, &gTempObject, true );
|
||||
}
|
||||
|
||||
// Cleanup after the autoplace has to occur in tactical mode.
|
||||
if (gTempObject.exists())
|
||||
{
|
||||
DeleteObj( &(gTempObject) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check the soldier to see how his stats have changed as a result of altering his gear.
|
||||
ApplyEquipmentBonuses(pSoldier);
|
||||
|
||||
if (fItemInPool && fSplit)
|
||||
{
|
||||
CHAR16 pStr[500];
|
||||
// Item was split apart. Since it was in the sector inventory, it's common sense that all results
|
||||
// are in the sector inventory as well, so no need to report anything extra.
|
||||
swprintf( pStr, gzTransformationMessage[ 1 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
ScreenMsg( FONT_ORANGE, MSG_INTERFACE, pStr );
|
||||
}
|
||||
else if (fSplit || fDropped)
|
||||
{
|
||||
CHAR16 pStr[500];
|
||||
if (fSplit && !fDropped)
|
||||
{
|
||||
// Item was split apart, but all subitems remained in the inventory.
|
||||
swprintf( pStr, gzTransformationMessage[ 2 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
ScreenMsg( FONT_ORANGE, MSG_INTERFACE, pStr );
|
||||
}
|
||||
else if (fDropped && !fSplit)
|
||||
{
|
||||
// Either the item itself or another item has been dropped to the sector inventory due to lack of
|
||||
// space.
|
||||
swprintf( pStr, gzTransformationMessage[ 3 ], pSoldier->name );
|
||||
DoScreenIndependantMessageBox( pStr, MSG_BOX_FLAG_OK, NULL );
|
||||
}
|
||||
else if (fDropped && fSplit)
|
||||
{
|
||||
// Item was split apart. Either the item itself or another item has been dropped to the sector
|
||||
// inventory due to lack of space.
|
||||
swprintf( pStr, gzTransformationMessage[ 4 ], Item[usOrigItem].szItemName, pSoldier->name );
|
||||
DoScreenIndependantMessageBox( pStr, MSG_BOX_FLAG_OK, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
// Signal a successful transformation.
|
||||
return TRUE;
|
||||
}
|
||||
Reference in New Issue
Block a user