Jump to content
ℹ️ Intermittent Download History issues ×

Buildable Alien Grenades, Possible?


Yzaxtol

Recommended Posts

I did a bit of research, trying to trace this m_iFragGrenades. Well, first I've checked it works. Function UpdateItemsCharge (XComGame >> XGUnit) calls SetFragGrenades, which is the setter for XGUnitNativeBase.m_iFragGrenades. And changing this WORKS. I've tested giving 3 grenades with grenadier perk and it works, so the variable is readen in the tactical game, and changing it affects number of grenades. But then I also made a search through XComGame.upk and XComStrategyGame.upk searching for key words "frag" and "gren", in hopes I'd find something to correlate those variables in the strategy game but I couldn't find anything related, so that makes me think the game no longer cares about m_iFragGrenade once the mission is finished, and the only thing that matters is the item equipped in the slot.

 

Anyway I've found this in XGUnitNativeBase

 

replication
{
    // Pos:0x000
    if(bNetDirty && Role == ROLE_Authority)
        m_aAbilities, m_aAbilitiesAffecting, 
        m_aAbilitiesApplied, m_aAbilitiesOnCooldown, 
        m_aCurrentStats, m_aHeightBonusStats, 
        m_aInventoryStats, m_arrBonuses, 
        m_arrCiviliansInRangeReplicated, m_arrEnemiesEngagedByReplicated, 
        m_arrEnemiesInCloseRangeReplicated, m_arrEnemiesInRangeReplicated, 
        m_arrEnemiesRevealedWhileMovingReplicated, m_arrEnemiesSeenByReplicated, 
        m_arrFlankingUnitsReplicated, m_arrFriendsInRangeReplicated, 
        m_arrFriendsSeenByReplicated, m_arrPassives, 
        m_arrPenalties, m_arrSuppressingEnemies, 
        m_arrSuppressionExecutingEnemies, m_arrSuppressionTargets, 
        m_arrVisibleCiviliansReplicated, m_arrVisibleEnemiesReplicated, 
        m_arrVisibleFriendsReplicated, m_bBattleScanner, 
        m_bForceHidden, m_bHasChryssalidEgg, 
        m_bInCombatDrugs, m_bInDenseSmoke, 
        m_bInSmokeBomb, m_bIsInOverwatch, 
        m_bRunAndGunUsedMove, m_bSprinting, 
        m_bStabilized, m_iAlienGrenades, 
        m_iArcThrowerCharges, m_iBattleScanners, 
        m_iBuildAbilityNotifier, m_iCurrentCoverValue, 
        m_iFireActionsPerformed, m_iFragGrenades, 
        m_iGhostCharges, m_iImmuneToDisable, 
        m_iMediKitCharges, m_iMoves, 
        m_iMovesActionsPerformed, m_iNumAbilities, 
        m_iNumAbilitiesAffecting, m_iNumAbilitiesApplied, 
        m_iNumAbilitiesOnCooldown, m_iNumOfBonuses, 
        m_iNumOfPenalties, m_iNumTimesUsedInTheZone, 
        m_iNumTimesUsedPistolInTheZone, m_iPanicCounter, 
        m_iRift, m_iRockets, 
        m_iShredderRocketCtr, m_iShredderRockets, 
        m_iSmokeGrenades, m_iTelekineticField, 
        m_iTracerBeamCtr, m_iUseAbilities, 
        m_kArmor, m_kBehavior, 
        m_kCustomAbility, m_kDynamicSpawnedBattleScanner, 
        m_kDynamicSpawnedSmokeGrenade, m_kPlayerNativeBase, 
        m_numSuppressingEnemies, m_numSuppressionExecutingEnemies, 
        m_numSuppressionTargets

    // Pos:0x020
    if((bNetDirty && !bNetOwner) && Role == ROLE_Authority)
        m_bDashing, m_bReactionFireStatus

    // Pos:0x051
    if(bNetInitial && Role == ROLE_Authority)
        m_kCharacter, m_kNetExecActionQueue, 
        m_kPathingPawn, m_kPawn, 
        m_kSquad
}

dunno what replication is, but it's the only place where that m_iFragGrenades var is referenced besides it's getter and setter

Link to comment
Share on other sites

Another example of how the game treats grenades as item charges. XComGame >> XGAbility

 

simulated function int GetCharge()
{
    switch(GetType())
    {
        // End:0x39
        case 40:
            return m_kUnit.GetGhostCharges();
        // End:0x3E
        case 9:
        // End:0x43
        case 10:
        // End:0x68
        case 42:
            return m_kUnit.GetArcThrowerCharges();
        // End:0x6D
        case 41:
        // End:0x72
        case 37:
        // End:0x97
        case 36:
            return m_kUnit.GetMediKitCharges();
        // End:0xBC
        case 22:
            return m_kUnit.GetFragGrenades();
        // End:0xE1
        case 24:
            return m_kUnit.GetAlienGrenades();
        // End:0x106
        case 66:
            return m_kUnit.GetShredderRockets();
        // End:0x12B
        case 25:
            return m_kUnit.GetRockets();
        // End:0x150
        case 71:
            return m_kUnit.GetBattleScannerCharges();
        // End:0x175
        case 23:
            return m_kUnit.GetSmokeGrenadeCharges();
        // End:0xFFFF
        default:
            return 0;
    }
    //return ReturnValue;    
}

I totaly ignore whether this function is actually called, but it just strenghten my suspicions. Maybe we'll have to code it out inside the tactical game, and check if m_iFragGrenades < getSmallItems[item(85)] then removeItem from inventory/backpack.

Link to comment
Share on other sites

The replication functions (as near as I can tell) are used to pass data between classes, when it would normally be out of scope. I think it also might be used in some cases for saving / loading the game.

 

It is definitely possible to jack up the number of charges. Some items lend themselves very naturally to a "charge" mechanic. To use an Arc Thrower more than once, you don't need to bring multipler Arc Throwers. With ammo removed (and all of its micromanagement), then rockets (a sort of ammo) and grenades (even more weakly) followed the same streamlining, I guess. It would be a bit odd to have consumable grenades, and require players to build them, when you don't have consumable rockets, nor need to build rockets.

 

Anyhow ... one thing I thought of-- when you have the grenadier perk, does the "double equip" consume two grenades out of storage, or just one? I suspect it only consumes one.

 

-------------------------------------------------------------------------------------------------

 

To make the item consumable on the strategic level (it's already consumable at tactical), you really have to modify the count stored in XGStorage(). The current mechanic for XGStorage is:

1) There are three item arrays, and one dynamic array

1a) m_arrItems[195] holds count of items that have been built or recovered (or supplied at start of game)

1b) m_arrItemArchives[195] holds count of items ever possessed
1c) m_arrClaims[195] holds count of items currently equipped on soldiers
1d) m_arrInfiniteItems ((dynamic array)) tracks which items are available in unlimited amounts
2) Items are added to m_arrItems when created in Engineering or when recovered from missions

3) Items are added to m_arrClaims when equipped to a solider

4) Items are removed from m_arrClaims when a soldier is "unloaded" after returning from battle (or is dismissed)

5) Items are removed from m_arrItems if soldier goes MIA, or is killed with SW option Total Loss turned on

 

This all occurs in XcomStrategyGame.upk, as a part of the Dropship returning from a mission. Unfortunately it does not seem possible to call from XcomGame.upk to XcomStrategyGame.upk. While in the tactical game, only tactical game info can be referenced (this is why it's been so difficult to upgrade alien stats as time progresses).

 

------------------------------------------------------------------------------------------------------------------

 

It -is- possible to access the tactical game data from the strategy game. Unfortunately, all of the tactical battle info will have been destroyed before the program begins executing the strategy game (I think). Information about the battle results is passed back from tactical to strategy via

 

Here is the whole call sequence going back to strategy game:

 

 

XGGeoscape().SkyrangerArrival() calls XGShip_Dropship().Land()
XGShip_Dropship().Land() calls XGFacility_Hanger().LandDropShip()
XGFacility_Hanger().LandDropShip() calls XGFacility_Barracks().LandSoldiers()
XGFacility_Barracks().LandSoldiers() calls XGFacility_Barracks().ClearSquad() ((also CancelSquadSelection() calls ClearSquad() ))
XGFacility_Barracks().ClearSquad() checks location of each soldier (1 -> UnloadSoldier, Unload adds to fallen array if dead, 3-> Add to Fallen array ::: for each in Fallen, RemoveSoldier), RemoveSoldier is only otherwise called with Dismiss
XGFacility_Barracks().UnloadSoldier calls ReleaseLoadout or RemoveLoadout ||||||||||| XGFacility_Barracks().RemoveSoldier calls XGFacility_Barracks().RemoveTank()
Picking out LandSoldiers(), it's only argument is a variable of type XGDropship (defined in XGShip_Dropship). Unless you can access the remains of the tactical game battle, you have to live with the information passed back through the XGDropship. The relevant info is all in CargoInfo and m_arrSoldiers, I think.
Link to comment
Share on other sites

Yep, equipping a grenade with the grenadier ability only takes 1 grenade from storage, not 2.

Following this sequence I end at releaseLoadout, where the num of grenades don't appear at all.

As I said before, it seems to me the game handles separately grenade items and grenade charges, because of the grenadier ability, bacause in UpdateItemCharges() each unit has SetGrenades(num.grenade items), and more. So I think the way to go with this should be:

- removing grenade items from units inventory during tactical game, either right after activating the grenade ability or at the end of the mission.

- If possible check if ( unit.getFragGrenades() < unit.inventory.smallItems(type(85)) ) to see if num of items on inventory matches grenade charges, and then removeItem if the unit has spent the grenade.

 

I'm gonna try a crude approach, just skipping this line in XGStorage.ReleaseItem(), in the small items check

 

TACTICAL().TInventorySmallItemsSetItem(kSoldier.m_kChar.kInventory, I, 0);

so every small item equipped is spent at the end of each mission. It is not a perfect solution, but with appropiate lower item prices (specially armor vests) and before we can remove items on the fly as they're used, it doesn't seem as bad. The choice is not whether using the grenade or not, but rather equipping it or leaving it for further missions.

Link to comment
Share on other sites

  • 2 weeks later...

Success, at last!!

 

It is still in a preeliminary phase and it needs more testing and a bit more of elaboration, but it works. It would need some further edit and maybe a general re-planning if it were to fix MIA soldiers lost equipment and that SW option 15 (those were bugged, right?).

 

Well, to the point. Tracing back function calls (see Amineri's last post) it leads to UnloadSoldier (in XGFacility_Barracks), where it removes (in theory) dead soldier's equipment, and it "releases" shivs and injured soldier's equipment (so they are no longer attached to the unit but are available in storage), BUT there is no call for alive units. See the code:

 

 

function bool UnloadSoldier(XGStrategySoldier kSoldier)
{
    local XGParamTag kTag;
    local XGShip_Dropship kSkyranger;
    local bool bFound;
    local int I;

    bFound = false;
    kSkyranger = HANGAR().m_kSkyranger;
    I = 0;
    J0x40:
    // End:0xC0 [Loop If]
    if(I < kSkyranger.m_arrSoldiers.Length)
    {
        // End:0xB2
        if(kSkyranger.m_arrSoldiers[i] == kSoldier)
        {
            bFound = true;
            // [Explicit Break]
            goto J0xC0;
        }
        ++ I;
        J0xC0:
        // [Loop Continue]
        goto J0x40;
    }
    // End:0xF8
    if(bFound)
    {
        kSkyranger.m_arrSoldiers.RemoveItem(kSoldier);
    }
    // End:0x109
    if(!bFound)
    {
        return true;
    }
    // End:0x184
    if(ISCONTROLLED())
    {
        // End:0x184
        if((kSkyranger.m_iNumMissions == 1) && kSoldier.GetCurrentStat(0) > 0)
        {
            kSoldier.LevelUp(2);
        }
    }
    // End:0x4D7
    if(kSoldier.GetCurrentStat(0) <= 0)
    {
        kTag = XGParamTag(XComEngine(class'Engine'.static.GetEngine()).LocalizeContext.FindTag("XGParam"));
        kTag.IntValue0 = GEOSCAPE().m_kDateTime.GetDay();
        kTag.IntValue1 = GEOSCAPE().m_kDateTime.GetMonth();
        kTag.IntValue2 = GEOSCAPE().m_kDateTime.GetYear();
        kSoldier.SetHQLocation(3);
        kSoldier.m_strKIAReport = kSkyranger.m_strLastOpName;
        kSoldier.m_strKIADate = class'XComLocalizer'.static.ExpandString(m_strKIADateTimeFormat);
        m_arrFallen.AddItem(kSoldier);
        // End:0x483
        if(!kSoldier.IsATank())
        {
            // End:0x457
            if(kSoldier.m_bMIA || IsOptionEnabled(15))
            {
                STORAGE().RemoveLoadout(kSoldier);
            }
            // End:0x480
            else
            {
                STORAGE().ReleaseLoadout(kSoldier);
            }
        }
        // End:0x4AC
        else
        {
            STORAGE().ReleaseLoadout(kSoldier);
        }
        m_arrFallen.Sort(SortTheFallen);
        UpdateMemorialPictures();
    }
    // End:0x532
    else
    {
        // End:0x50F
        if(kSoldier.IsInjured())
        {
            MoveToInfirmary(kSoldier);
        }
        // End:0x532
        else
        {
            kSoldier.SetHQLocation(0);
        }
    }
    return true;
    //return ReturnValue;    
}

 

So what I've made is to replace that ISCONTROLLED() check (it seems to boost promotions after 1st mission ¿if in the tutorial?) anyway I've deleted it to make room for a call to STORAGE().RemoveLoadout(kSoldier);

 

Replaced Code:

 

 

Before:
    // End:0x184
    if(ISCONTROLLED())
    {
        // End:0x184
        if((kSkyranger.m_iNumMissions == 1) && kSoldier.GetCurrentStat(0) > 0)
        {
            kSoldier.LevelUp(2);
        }
    }
Now:
    STORAGE().RemoveLoadout(kSoldier);
    kSoldier
    kSoldier
    kSoldier
    kSoldier
    kSoldier

 

Then I changed RemoveLoadout fuction so it only removes small items, not weapons, armor or large items (which I suspect refers to rocket launchers)

Code:

 

 

Original code:
function RemoveLoadout(XGStrategySoldier kSoldier)
{
    local TInventory kTempInv;
    local int I;

    kTempInv = kSoldier.m_kChar.kInventory;
    ReleaseLoadout(kSoldier);
    RemoveItem(kTempInv.iArmor);
    RemoveItem(kTempInv.iPistol);
    I = 0;
    J0xA7:
    // End:0x110 [Loop If]
    if(I < kTempInv.iNumLargeItems)
    {
        RemoveItem(kTempInv.arrLargeItems[i]);
        ++ I;
        // [Loop Continue]
        goto J0xA7;
    }
    I = 0;
    J0x11B:
    // End:0x184 [Loop If]
    if(I < kTempInv.iNumSmallItems)
    {
        RemoveItem(kTempInv.arrSmallItems[i]);
        ++ I;
        // [Loop Continue]
        goto J0x11B;
    }
    //return;    
}[/code[/spoiler]
I *think* what bugged the lost equipment option is that call to ReleaseLoadout. Anyway I've removed it, and then I've swapped every call to RemoveItem to ReleaseItem except for the last one inside the small items loop, just for testing and it works. Code is currently left as:
[spoiler][code]function RemoveLoadout(XGStrategySoldier kSoldier)
{
    local TInventory kTempInv;
    local int I;

    kTempInv = kSoldier.m_kChar.kInventory;
    kSoldier                                        
    ReleaseItem(kTempInv.iArmor);
    ReleaseItem(kTempInv.iPistol);
    I = 0;
    J0xA7:
    // End:0x110 [Loop If]
    if(I < kTempInv.iNumLargeItems)
    {
        ReleaseItem(kTempInv.arrLargeItems[i]);
        ++ I;
        // [Loop Continue]
        goto J0xA7;
    }
    I = 0;
    J0x11B:
    // End:0x184 [Loop If]
    if(I < kTempInv.iNumSmallItems)
    {
        RemoveItem(kTempInv.arrSmallItems[i]);
        ++ I;
        // [Loop Continue]
        goto J0x11B;
    }
    //return;    
}

 

And finally I changed XGStorage.IsInfinite to read: return false (04 28); just that (plus header and footer).

 

As I said before this isn't an ideal solution, quite far from that, but it is indeed a confirmation that it can be done, so I thought you'd like to know.

 

From here now there are several possible options, ... right now it doesn't check it the item was actualy used or not, it just removes every small item in soldier's inventory once the mission is finished. I think this isn't ideal but it's ok, since items can be given a low price and it could be arguable that some items must be discarded just for safety after certain period of time, whatever you want, just turning the decision to equip an item or not equiping it into a strategical decision as another form of resource management.

 

If choosing to make every small item dissappear I thik it all could be fixed by making so the ReleaseLoadout function skips releasing small items, and then run a RemoveLoadout to every unit, so only those alive get the ReleaseLoadout call... what it means is just editing this two functions and UnloadSoldier...

 

I admit it would be cool if items were removed just if they were used, or if the unit was hit or wounded for armor and/or armor items, etc, but I haven't seen space enough to implement that using current functions, so that would probably mean creating a new function just to perform those checks. I think it's doable but it'd need some extra work... basically just finding the space to write it.

 

Thought about it?

 

edit: formatting

Edited by anUser
Link to comment
Share on other sites

You'd really need to find some place in the StrategyGameTransport to store the number of charges used by each soldier during the tactical game.

 

I've had some success with using the RecapSaveData to store the number of days elapsed in the mission (that's how I finally got that working), but I've had several failures trying to modify values here as well. Once I caused Abduction Missions to be uncomplete-able, and once I caused 5 duplicate XCOM soldiers to spawn in a terror mission.

 

That said, I see two places to look into to pass the information back. Both are in the XGDropShipCargo class. What makes this whole exercise somewhat maddening is that there are two instances of the class XGDropshipCargo in the StrategyGameTransport.

 

StrategyGameTransport has the variable var XGDropShipCargo m_kCargo defined directly, but also

 

StrategyGameTransport has the variable var XGBattleDesc m_kBattleDesc, and then XGBattleDesc has the variable var XGDropshipCargoInfo m_kDropShipCargoInfo

 

This means that both:

m_kStrategyTransport.m_kCargo

m_kStrategyTransport.m_kBattleDesc.m_kDropShipCargo

 

point to the same type class -- XGDropShipCargo. However, they need not contain the same data. It's somewhat unclear when each copy is used. So, beware ...

 

------------------

 

Having said that, in XGDropShipCargo, the variables:

array<TTransferSoldier> m_arrSoldiers

array<int> m_arrArtifacts

 

appear to be the most promising (to me).

 

m_arrSoldiers stores each individual soldier's info (both pre-battle info used to create the soldiers, and post-battle info containing wounds taken, XP earned, critical wound info, etc)

This array is of type TTransferSoldier, which contains a TCharacter variable and a TSoldier variable.

TCharacter does store the soldier inventory in the TInventory variable, so it might have possibilities.

TSoldier has info like appearance, class, name, xp, rank, so isn't terribly promising.

 

------------------------------------------------------

m_arrArtifacts stores items collected during the mission (weapon fragments, alien corpses, alien captives, alien grenades, various plasma weapons, alloys and elerium from enemy robots, etc)

In CollectArtifactsFromDeadAliens(), Desc().m_kDropShipCargoInfo.m_arrArtifacts.Add(195); is set. m_arrArtifacts is a dynamic array, but it is being set to store the 195 game-items as defined in the enum EItem. Since it is a dynamic array, you might be able to create more entries, and then set them yourself (and then modify the strategy-side game to read the extra entries).

Link to comment
Share on other sites

I'm in no good terms at all with arrays, struct tokens and member tokens beyond the first nesting. By now I'll elaborate the solution I proposed above to tidy up code a bit, and I'll go with complete items removal after each mission. Thanks to jhonnylump I could change the number of initial storage and I'm looking forward to start a new game starting with only 4 rifles and 10 grenades in stock, being able to build smoke grenades, rockets and battle scanner from the begginig and using them just equipping the items, and yeah, spending every single item in the inventory each mission. There's still a few changes I've to make, so I'm not taking this for now.

 

btw, ue explorer misses some information when showing arrays and structs right? I'm not quite getting how they work. Some tip?

Link to comment
Share on other sites

  • 2 weeks later...

Leaving besides the removable item stuff, I found a piece of code that could be tweaked to make alien grenades buildable after researching the alien grenades project. Problem is I don't know how to write it in hex, and I'm not sure the changes would be permanent.

 

Code is in XComStrategyGame >> XGFacility_Engineering >> OnFoundryProjectCompleted

if(m_arrFoundryProjects[iProject].eTech == 2)
{
    STORAGE().m_arrInfiniteItems.AddItem(88);
    BARRACKS().UpdateGrenades(88);
}
which I planned to replace with:
STORAGE().m_arrItems[88].iHours = xxx; (being that xxx a direct value or a call to GetItemBuildTime)
So in theory if alien grenade was given -1 build time by default it could be changed once the foundry project is completed. But now that we know the ini settings overwrite BuildItem calls, would this be overwritten as well I guess ¿? I'm thinking that perhaps there's some combination where a value can be left unassigned in the ini so it's not overwritten later... for example, not setting the num of engineers on ini, setting it to -1 in buildItems, and later setting it to 10 via this function... would it work?

 

btw that updateGrenades(88) can go away as it replaces soldier's frag grenade with alien grenades in inventory, and it seems to do so regadless the number of grenades in stock, and the infiniteItems array can go away as well because it's of no use with consumible items

Link to comment
Share on other sites

I've tried my best here but so far I've been unable to remove small items from inventory after each mission. The success I claimed a few posts and some more days ago didn't last more than a couple of missions. Since then I've had invisible soldiers, unselectable soldiers and tons of crashes, but I couldn't make it consistently removed every equipped small item after a mission, and that was just meant to be a temporary solution before we can make it removes only those items effectively used during mission.

 

Anyway, the case is there's still something about how the game keeps track of items that eludes me. I post here my latest attempt in case someone sees what's wrong with it.

 

I found this function ReleaseSmallItems in XGStorage that is included in the Table view but isn't called (at least not from XComGame or XComStrategyGame), which I changed to read as follows:

 

function ReleaseSmallItems(XGStrategySoldier kSoldier)
{
    local int I;
    local XComGame.XGGameData.EItemType eItem;

    I = 0;
    J0x0B:
    // End:0x156 [Loop If]
    if(I < kSoldier.m_kChar.kInventory.iNumSmallItems)
    {
        eItem = byte(kSoldier.m_kChar.kInventory.arrSmallItems[i]);
        // End:0x148
        if(!IsInfinite(eItem))
        {
            RemoveItem(eItem, 1);
            kSoldier
            TACTICAL().TInventorySmallItemsSetItem(kSoldier.m_kChar.kInventory, I, 0);
        }
        ++ I;
        // [Loop Continue]
        goto J0x0B;
    }
    //return;    
}

hex code:

SF: 1B 99 22 00 00 00 00 00 00 38 3A 00 A8 40 00 00 00 AA 40 00 00 16
RW: 1B AE 22 00 00 00 00 00 00 00 A8 40 00 00 2C 01 16 00 AA 40 00 00
check your hex the function code may not be the same, the trick is just removing the casting item to add the integer, and moving the variable outside the function call. Notice 0xAE - 0x99 = 0x15 ergo 21 index offset.

 

And then I called this function from XGFacility_Barracks.UnloadSoldier

 

 

function bool UnloadSoldier(XGStrategySoldier kSoldier)
{
    local XGParamTag kTag;
    local XGShip_Dropship kSkyranger;
    local bool bFound;
    local int I;

    bFound = false;
    kSkyranger = HANGAR().m_kSkyranger;
    I = 0;
    J0x40:
    // End:0xC0 [Loop If]
    if(I < kSkyranger.m_arrSoldiers.Length)
    {
        // End:0xB2
        if(kSkyranger.m_arrSoldiers[i] == kSoldier)
        {
            bFound = true;
            // [Explicit Break]
            goto J0xC0;
        }
        ++ I;
        J0xC0:
        // [Loop Continue]
        goto J0x40;
    }
    // End:0xF8
    if(bFound)
    {
        kSkyranger.m_arrSoldiers.RemoveItem(kSoldier);
    }
    // End:0x109
    if(!bFound)
    {
        return true;
    }
    STORAGE().ReleaseSmallItems(kSoldier);
    kSoldier
    kSoldier
    kSoldier
    kSoldier
    kSoldier                                                                                                                                                    
    // End:0x4D7
    if(kSoldier.GetCurrentStat(0) <= 0)
    {
        kTag = XGParamTag(XComEngine(class'Engine'.static.GetEngine()).LocalizeContext.FindTag("XGParam"));
        kTag.IntValue0 = GEOSCAPE().m_kDateTime.GetDay();
        kTag.IntValue1 = GEOSCAPE().m_kDateTime.GetMonth();
        kTag.IntValue2 = GEOSCAPE().m_kDateTime.GetYear();
        kSoldier.SetHQLocation(3);
        kSoldier.m_strKIAReport = kSkyranger.m_strLastOpName;
        kSoldier.m_strKIADate = class'XComLocalizer'.static.ExpandString(m_strKIADateTimeFormat);
        m_arrFallen.AddItem(kSoldier);
        // End:0x483
        if(!kSoldier.IsATank())
        {
            // End:0x457
            if(kSoldier.m_bMIA || IsOptionEnabled(15))
            {
                STORAGE().RemoveLoadout(kSoldier);
            }
            // End:0x480
            else
            {
                STORAGE().ReleaseLoadout(kSoldier);
            }
        }
        // End:0x4AC
        else
        {
            STORAGE().ReleaseLoadout(kSoldier);
        }
        m_arrFallen.Sort(SortTheFallen);
        UpdateMemorialPictures();
    }
    // End:0x532
    else
    {
        // End:0x50F
        if(kSoldier.IsInjured())
        {
            MoveToInfirmary(kSoldier);
        }
        // End:0x532
        else
        {
            kSoldier.SetHQLocation(0);
        }
    }
    return true;
    //return ReturnValue;    
}

In theory the ReleaseSmallItems function should remove the items #1) calling RemoveItem, which in turn sets m_arrItems[item] -= Quantity (1, could use emptyParam as well), and #2) setting the item in the inventory to 0 by means of native function TInventorySmallItemsSetItem (not sure if it does what it's suposed to do). But as I said, despite indeed removing the items, this has strange effects. I've to say I was happy with the idea of every item being spent at end of mission, I make them all cost 5~10 and it's cheap but fair, but I coulnd't get even this... it's getting quite frustrating. With this last change after finishing a mission I can only select already used soldiers, so in my 2nd mission I could play with only 3 units 'cause I got 1 injured from 1st mission....

 

Well, if someone with a better understanding of this tangled items tracking system the game uses can give some insight I'd truly appeciate it.

 

ps: I recall seeing some function with a check that excluded soldiers without armor. I don't know if it has to do at all with this but I mention 'cause I couldn't find it anymore.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...