E3245 Posted April 5, 2016 Share Posted April 5, 2016 Hello everyone, I'm trying to get this script for custom attachments to work. It compiles without any problems in Modbuddy, but when I run the game, it doesn't show up. I think I'm missing something here. I've added it to the X2DownloadableContentInfo, but it still doesn't show up. Here's the script in question. I put it inside the spoiler tag since it was big: X2Items_M16_Upgrades: //============================================================================================= // This *.uc demonstrates the ability to use custom attachements for weapons. Work in Progress. // This is a script that works almost like the ExampleWeapon *.uc script, except that it is // used for weapon attachments instead. Use the examples from the Weapon script to make // adjustments to the bonuses of each attachment. // If there are any bugs, please report it to the author. // AUTHOR: E3245 // ============================================================================================ class X2Item_M16_Upgrades extends X2Item; //Template classes are searched for by the game when it starts. Any derived classes have their CreateTemplates function called //on the class default object. The game expects CreateTemplates to return a list of templates that it will add to the manager //reponsible for those types of templates. Later, these templates will be automatically picked up by the game mechanics and systems. static function array<X2DataTemplate> CreateTemplates() { local array<X2DataTemplate> M16ModItems; M16ModItems.AddItem(CreateM16CritUpgrade()); M16ModItems.AddItem(CreateM16AimUpgrade()); M16ModItems.AddItem(CreateM16ClipSizeUpgrade()); M16ModItems.AddItem(CreateM16ReloadUpgrade()); return M16ModItems; } //Template creation functions form the bulk of a template class. The following attachments in order. // //Crit Upgrade // static function X2DataTemplate CreateM16CritUpgrade() { local X2WeaponUpgradeTemplate Template; `CREATE_X2TEMPLATE(class'X2WeaponUpgradeTemplate', Template, 'CritUpgrade_M16'); SetUpCritUpgrade(Template); class'X2Item_DefaultUpgrades'.static.SetUpTier1Upgrade(Template); Template.BonusAbilities.AddItem('LaserSight_Bsc'); Template.strImage = "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_OpticB_inv"; Template.CritBonus = class'X2Item_DefaultUpgrades'.default.CRIT_UPGRADE_BSC; return Template; } //Template creation functions form the bulk of a template class. The following attachments in order. // //Aim Upgrade // static function X2DataTemplate CreateM16AimUpgrade() { local X2WeaponUpgradeTemplate Template; `CREATE_X2TEMPLATE(class'X2WeaponUpgradeTemplate', Template, 'AimUpgrade_M16'); SetUpAimBonusUpgrade(Template); class'X2Item_DefaultUpgrades'.static.SetUpTier1Upgrade(Template); Template.strImage = "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_OpticC_inv"; Template.AimBonus = class'X2Item_DefaultUpgrades'.default.AIM_UPGRADE_BSC; Template.AimBonusNoCover = class'X2Item_DefaultUpgrades'.default.AIM_UPGRADE_NOCOVER_BSC; return Template; } //Template creation functions form the bulk of a template class. The following attachments in order. // //Extended Mags Upgrade // static function X2DataTemplate CreateM16ClipSizeUpgrade() { local X2WeaponUpgradeTemplate Template; `CREATE_X2TEMPLATE(class'X2WeaponUpgradeTemplate', Template, 'ClipSizeUpgrade_M16'); SetUpClipSizeBonusUpgrade(Template); class'X2Item_DefaultUpgrades'.static.SetUpTier1Upgrade(Template); Template.strImage = "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_MagB_inv"; Template.ClipSizeBonus = class'X2Item_DefaultUpgrades'.default.CLIP_SIZE_BSC; return Template; } //Template creation functions form the bulk of a template class. The following attachments in order. // //Dual Mag Upgrade // static function X2DataTemplate CreateM16ReloadUpgrade() { local X2WeaponUpgradeTemplate Template; `CREATE_X2TEMPLATE(class'X2WeaponUpgradeTemplate', Template, 'ReloadUpgrade_M16'); SetUpReloadUpgrade(Template); class'X2Item_DefaultUpgrades'.static.SetUpTier1Upgrade(Template); Template.strImage = "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_MagC_inv"; Template.NumFreeReloads = class'X2Item_DefaultUpgrades'.default.FREE_RELOADS_BSC; return Template; } // ####################################################################################### // -------------------- CRIT UPGRADE ---------------------------------------------------- // ####################################################################################### static function SetUpCritUpgrade(out X2WeaponUpgradeTemplate Template) { class'X2Item_DefaultUpgrades'.static.SetUpWeaponUpgrade(Template); //Stuff from X2Item_DefaultUpgrades. Item effects. Template.AddCritChanceModifierFn = class'X2Item_DefaultUpgrades'.static.CritUpgradeModifier; Template.GetBonusAmountFn = class'X2Item_DefaultUpgrades'.static.GetCritBonusAmount; //Something happens here. Also calls from CreateM16CritUpgrade() Template.MutuallyExclusiveUpgrades.AddItem('CritUpgrade_M16'); // M16 Optics Assault Rifle //Template.AddUpgradeAttachment Parameters: //(Socket, UIArmoryCameraPointTag, MeshName, ProjectileName, Weapon Template, AttachToPawn(true or false), IconName, InventoryIconName, InventoryCategoryIcon, Validate Upgrade Status) Template.AddUpgradeAttachment('Optic', 'UIPawnLocation_WeaponUpgrade_AssaultRifle_Optic', "ConvAssaultRifle.Meshes.SM_ConvAssaultRifle_OpticB", "", 'BOM16', , "img:///UILibrary_Common.ConvAssaultRifle.ConvAssault_OpticB", "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_OpticB_inv", "img:///UILibrary_StrategyImages.X2InventoryIcons.Inv_weaponIcon_scope"); } // ####################################################################################### // -------------------- AIM BONUS UPGRADE ------------------------------------------------ // ####################################################################################### static function SetUpAimBonusUpgrade(out X2WeaponUpgradeTemplate Template) { class'X2Item_DefaultUpgrades'.static.SetUpWeaponUpgrade(Template); //Stuff from X2Item_DefaultUpgrades. Item effects. Template.AddHitChanceModifierFn = class'X2Item_DefaultUpgrades'.static.AimUpgradeHitModifier; Template.GetBonusAmountFn = class'X2Item_DefaultUpgrades'.static.GetAimBonusAmount; //Something happens here. Also calls from CreateM16AimUpgrade() Template.MutuallyExclusiveUpgrades.AddItem('AimUpgrade_M16'); //M16 ACOG Template.AddUpgradeAttachment('Optic', 'UIPawnLocation_WeaponUpgrade_AssaultRifle_Optic', "ConvAssaultRifle.Meshes.SM_ConvAssaultRifle_OpticC", "", 'BOM16', , "img:///UILibrary_Common.ConvAssaultRifle.ConvAssault_OpticC", "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_OpticC_inv", "img:///UILibrary_StrategyImages.X2InventoryIcons.Inv_weaponIcon_scope"); } // ####################################################################################### // -------------------- EXTENDED MAG UPGRADE --------------------------------------------- // ####################################################################################### static function SetUpClipSizeBonusUpgrade(X2WeaponUpgradeTemplate Template) { class'X2Item_DefaultUpgrades'.static.SetUpWeaponUpgrade(Template); //Stuff from X2Item_DefaultUpgrades. Item effects. Template.AdjustClipSizeFn = class'X2Item_DefaultUpgrades'.static.AdjustClipSize; Template.GetBonusAmountFn = class'X2Item_DefaultUpgrades'.static.GetClipSizeBonusAmount; Template.MutuallyExclusiveUpgrades.AddItem('ClipSizeUpgrade_M16'); //Parameter 10 calls from X2Item_DefaultUpgrades.uc so we don't have to rewrite functions. //M16 Extended Mags Template.AddUpgradeAttachment('Mag', 'UIPawnLocation_WeaponUpgrade_AssaultRifle_Mag', "ConvAssaultRifle.Meshes.SM_ConvAssaultRifle_MagB", "", 'BOM16', , "img:///UILibrary_Common.ConvAssaultRifle.ConvAssault_MagB", "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_MagB_inv", "img:///UILibrary_StrategyImages.X2InventoryIcons.Inv_weaponIcon_clip", class'X2Item_DefaultUpgrades'.static.NoReloadUpgradePresent); } // ####################################################################################### // -------------------- DUAL MAG UPGRADE ------------------------------------------------- // ####################################################################################### static function SetUpReloadUpgrade(out X2WeaponUpgradeTemplate Template) { class'X2Item_DefaultUpgrades'.static.SetUpWeaponUpgrade(Template); Template.FreeReloadCostFn = class'X2Item_DefaultUpgrades'.static.FreeReloadCost; Template.FriendlyRenameFn = class'X2Item_DefaultUpgrades'.static.Reload_FriendlyRenameAbilityDelegate; Template.GetBonusAmountFn = class'X2Item_DefaultUpgrades'.static.GetReloadBonusAmount; Template.MutuallyExclusiveUpgrades.AddItem('ReloadUpgrade'); //Parameter 10 calls from X2Item_DefaultUpgrades.uc so we don't have to rewrite functions. //M16 Dual Mags Template.AddUpgradeAttachment('Mag', 'UIPawnLocation_WeaponUpgrade_AssaultRifle_Mag', "BlackOpsWeapons_M16_Data.Meshes.XCOMM16_FP_ExtendedMags", "", 'BOM16', , "img:///UILibrary_Common.ConvAssaultRifle.ConvAssault_MagC", "img:///UILibrary_StrategyImages.X2InventoryIcons.ConvAssault_MagC_inv", "img:///UILibrary_StrategyImages.X2InventoryIcons.Inv_weaponIcon_clip", class'X2Item_DefaultUpgrades'.static.NoClipSizeUpgradePresent); //M16 Extended Dual Mags Template.AddUpgradeAttachment('Mag', 'UIPawnLocation_WeaponUpgrade_AssaultRifle_Mag', "ConvAssaultRifle.Meshes.SM_ConvAssaultRifle_MagD", "", 'BOM16', , "img:///UILibrary_Common.UI_MagAssaultRifle.MagAssaultRifle_MagD", "img:///UILibrary_StrategyImages.X2InventoryIcons.MagAssaultRifle_MagD_inv", "img:///UILibrary_StrategyImages.X2InventoryIcons.Inv_weaponIcon_clip", class'X2Item_DefaultUpgrades'.static.ClipSizeUpgradePresent); } X2DownloadableContentInfo_BlackOpsWeaponM16: //--------------------------------------------------------------------------------------- // FILE: XComDownloadableContentInfo_ExampleWeapon.uc // AUTHOR: Ryan McFall // // Demonstrates how to use the X2DownloadableContentInfo class to specify unique mod // behavior when the player creates a new campaign or loads a saved game. // //--------------------------------------------------------------------------------------- // Copyright (c) 2016 Firaxis Games, Inc. All rights reserved. //--------------------------------------------------------------------------------------- class X2DownloadableContentInfo_BlackOpsWeaponM16 extends X2DownloadableContentInfo; /// <summary> /// This method is run if the player loads a saved game that was created prior to this DLC / Mod being installed, and allows the /// DLC / Mod to perform custom processing in response. This will only be called once the first time a player loads a save that was /// create without the content installed. Subsequent saves will record that the content was installed. /// </summary> static event OnLoadedSavedGame() { local XComGameStateHistory History; local XComGameState NewGameState; local XComGameState_HeadquartersXCom OldXComHQState; local XComGameState_HeadquartersXCom NewXComHQState; local XComGameState_Item ItemState; local X2ItemTemplateManager ItemMgr; local X2ItemTemplate ItemTemplate; //In this method, we demonstrate functionality that will add ExampleWeapon to the player's inventory when loading a saved //game. This allows players to enjoy the content of the mod in campaigns that were started without the mod installed. ItemMgr = class'X2ItemTemplateManager'.static.GetItemTemplateManager(); History = `XCOMHISTORY; //Create a pending game state change NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Adding M-16 Rifle"); //Get the previous XCom HQ state - we'll need it's ID to create a new state for it OldXComHQState = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom')); //Make the new XCom HQ state. This starts out as just a copy of the previous state. NewXComHQState = XComGameState_HeadquartersXCom(NewGameState.CreateStateObject(class'XComGameState_HeadquartersXCom', OldXComHQState.ObjectID)); //Make the changes to the HQ state. Here we add items to the HQ's inventory ItemTemplate = ItemMgr.FindItemTemplate('BOM16'); ItemTemplate = ItemMgr.FindItemTemplate('CritUpgrade_M16'); ItemTemplate = ItemMgr.FindItemTemplate('AimUpgrade_M16'); ItemTemplate = ItemMgr.FindItemTemplate('ClipSizeUpgrade_M16'); ItemTemplate = ItemMgr.FindItemTemplate('ReloadUpgrade_M16'); //Instantiate a new item state object using the template. ItemState = ItemTemplate.CreateInstanceFromTemplate(NewGameState); NewGameState.AddStateObject(ItemState); //Add the newly created item to the HQ inventory NewXComHQState.AddItemToHQInventory(ItemState); //Commit the new HQ state object to the state change that we built NewGameState.AddStateObject(NewXComHQState); //Commit the state change into the history. History.AddGameStateToHistory(NewGameState); } /// <summary> /// Called when the player starts a new campaign while this DLC / Mod is installed /// </summary> static event InstallNewCampaign(XComGameState StartState) { //Don't need to do anything - the weapon should be picked up and placed into the HQ inventory when starting a new campaign. } Link to comment Share on other sites More sharing options...
CaveRat Posted April 6, 2016 Share Posted April 6, 2016 (edited) First, make sure that you load a save which was created before enabling the mod, otherwise OnLoadedSaveGame() won't work. I'd also put a log statement there somewhere to see if it runs at all; because people have reported having strange issues with this function. Second, not sure about Templates but you can't do something like this: //Make the changes to the HQ state. Here we add items to the HQ's inventory ItemTemplate = ItemMgr.FindItemTemplate('BOM16'); ItemTemplate = ItemMgr.FindItemTemplate('CritUpgrade_M16'); ItemTemplate = ItemMgr.FindItemTemplate('AimUpgrade_M16'); ItemTemplate = ItemMgr.FindItemTemplate('ClipSizeUpgrade_M16'); ItemTemplate = ItemMgr.FindItemTemplate('ReloadUpgrade_M16'); This will only pick up the last ItemTemplate, so theoretically, ReloadUpgrade should've been present ???I'd probably replace ItemTemplate with X2WeaponUpgradeTemplate. And you need to instantiate each one separately and add it to XcomHQState. local X2WeaponUpgradeTemplate WeponUpgradeTemplate; // .. skip WeaponUpgradeTemplate = X2WeaponUpgradeTemplate(ItemMgr.FindItemTemplate('BOM16')); ItemState = WeaponUpgradeTemplate.CreateInstanceFromTemplate(NewGameState); NewGameState.AddStateObject(ItemState); NewXComHQState.AddItemToHQInventory(ItemState); // next template WeaponUpgradeTemplate = X2WeaponUpgradeTemplate(ItemMgr.FindItemTemplate('CritUpgrade_M16')); ItemState = WeaponUpgradeTemplate.CreateInstanceFromTemplate(NewGameState); NewGameState.AddStateObject(ItemState); NewXComHQState.AddItemToHQInventory(ItemState); ^ this is just to illustrate. Obviously, it would be better to create some sort of FOR loop to handle it. Edited April 6, 2016 by CaveRat Link to comment Share on other sites More sharing options...
E3245 Posted April 7, 2016 Author Share Posted April 7, 2016 (edited) Thanks for pointing me in the right direction. This is all new to me, so bear with me. Here's what I've come up with. ItemTemplateNumber = 0; //Start of the Switch. To add more items, you must make a new case number from the last case, and add your ItemTemplate. Example: //case 5: // ItemTempate = ItemMgr.FindItemTemplate('YourItemTemplateName'); // goto AddItemtoHQInventory; //####################################################################### //# NOTE: LEAVING OUT THE goto COMMAND WILL CAUSE THIS SCRIPT TO BREAK! # //####################################################################### StartLoop: switch (ItemTemplateNumber) { case 0: ItemTemplate = ItemMgr.FindItemTemplate('BOM16'); `log("Adding M16 to HQ Inventory"); goto AddItemtoHQInventory; case 1: ItemTemplate = ItemMgr.FindItemTemplate('CritUpgrade_M16'); `log("Adding M16A1 Red Dot Sight to HQ Inventory"); goto AddItemtoHQInventory; case 2: ItemTemplate = ItemMgr.FindItemTemplate('AimUpgrade_M16'); `log("Adding M16A1 ACOG Scope to HQ Inventory"); goto AddItemtoHQInventory; case 3: ItemTemplate = ItemMgr.FindItemTemplate('ClipSizeUpgrade_M16'); `log("Adding M16A1 Extended Magazine to HQ Inventory"); goto AddItemtoHQInventory; case 4: ItemTemplate = ItemMgr.FindItemTemplate('ReloadUpgrade_M16'); `log("Adding M16A1 Dual Magazines to HQ Inventory"); goto AddItemtoHQInventory; default: goto EndScript; break; } //Loop Function AddItemtoHQInventory: //label `log( "Adding Item to HQ Inventory" ); for( ItemTemplateNumber=ItemTemplateNumber; ItemTemplateNumber<5; ItemTemplateNumber++ ) { ItemState = ItemTemplate.CreateInstanceFromTemplate(NewGameState); NewGameState.AddStateObject(ItemState); NewXComHQState.AddItemToHQInventory(ItemState); ItemTemplateNumber++; goto StartLoop; } `log( "All done."); EndScript: //Instantiate a new item state object using the template. //Try to create a loop function for every Item Template that exist //ItemState = ItemTemplate.CreateInstanceFromTemplate(NewGameState); //NewGameState.AddStateObject(ItemState); //Add the newly created item to the HQ inventory //NewXComHQState.AddItemToHQInventory(ItemState); //Commit the new HQ state object to the state change that we built NewGameState.AddStateObject(NewXComHQState); //Commit the state change into the history. History.AddGameStateToHistory(NewGameState); `log( "Script has completed. Can't log errors yet."); Kinda nasty, but it should get the job done. It compiles without any issues, so I'm hoping that this doesn't break the game. I'm wondering though, should I add the NewGameState.AddStateObject(NewXComHQState) and the History.AddGameStateToHistory(NewGameState) to the loop as well? Or leave it outside the loop? Edited April 7, 2016 by E3245 Link to comment Share on other sites More sharing options...
zingfharn Posted April 7, 2016 Share Posted April 7, 2016 Goto? What about break? You need to AddStateObject for every state item which changes. You can submit the changes after adding lots of state objects. So CreateChangeObject Loop { // Do stuff Add state object } SubmitChanges Link to comment Share on other sites More sharing options...
CaveRat Posted April 7, 2016 Share Posted April 7, 2016 @E3245, I've never seen GoTo and Labels used outside Actor state coding. You might wanna check Unreal Script reference. https://udn.epicgames.com/Three/UnrealScriptReference.html I would've probably done something like this: static event OnLoadedSavedGame() { local XComGameStateHistory History; local XComGameState NewGameState; local XComGameState_HeadquartersXCom XComHQ; local XComGameState_Item ItemState; local X2ItemTemplateManager ItemMgr; local WeaponUpgradeTemplate Template; local array<name> TemplateNames; local int idx; ItemMgr = class'X2ItemTemplateManager'.static.GetItemTemplateManager(); History = `XCOMHISTORY; //Create a pending game state change NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState("Adding M-16 Rifle"); XComHQ = XComGameState_HeadquartersXCom(History.GetSingleGameStateObjectForClass(class'XComGameState_HeadquartersXCom')); XComHQ = XComGameState_HeadquartersXCom(NewGameState.CreateStateObject(class'XComGameState_HeadquartersXCom', XComHQ.ObjectID)); TemplateNames.Add('BOM16'); TemplateNames.Add('CritUpgrade_M16'); TemplateNames.Add('AimUpgrade_M16'); TemplateNames.Add('ClipSizeUpgrade_M16'); TemplateNames.Add('ReloadUpgrade_M16'); //Instantiate a new item state object using the template. for (idx = 0; i < TemplateNames.Length; i++) { Template = X2WeaponUpgradeTemplate(ItemMgr.FindItemTemplate(TemplateNames[i])) if (Template == none) continue; ItemState = Template.CreateInstanceFromTemplate(NewGameState); NewGameState.AddStateObject(ItemState); //Add the newly created item to the HQ inventory XComHQ.AddItemToHQInventory(ItemState); } //Commit the new HQ state object to the state change that we built NewGameState.AddStateObject(XComHQ); //Commit the state change into the history. History.AddGameStateToHistory(NewGameState); } Link to comment Share on other sites More sharing options...
Recommended Posts