davidlallen Posted March 13, 2016 Share Posted March 13, 2016 I am trying to replace inventory items by an effect at the start of tactical, and it is not working. Any help would be appreciated. In the playable advent mod, there is a playable viper which has poison spit. The normal viper spit is implemented with both an ability and a grenade (/shrug). So with help from lucubration (thanks!) I copied both of these into my soldier class. When the soldier is created, I put the grenade into the inventory slot eInvSlot_Unknown so it can't be unequipped and other classes can't equip it. This is working fine in the published mod. Now, I have made an advanced spit (blinding spit) which does more damage and applies the disorient effect. I can start out the viper with this and it works correctly. But, I want to grant this new ability+grenade pair as a level bonus. So, when the viper solider reaches sergeant, one of the two possible new abilities is Blinding Spit. This should replace the original spit. The only way I could think of to implement this is with an effect on the level bonus ability that triggers at the start of tactical play. It looks in the inventory, and if it finds the basic poison spit grenade, it replaces it with the new blinding spit grenade. Unfortunately this generates a redscreen when I add the new grenade: [0218.38] Warning: Redscreen: GameState submitted containing un-added state objects: ==> PA_BlindingSpitAbility ( XGUnit_11 - ObjectID: 41205 ) -- XComGameState_Item_8614Stack:Script call stack: (X2TacticalGameRuleset_0) X2GameRuleset::SubmitGameStateInternal (X2TacticalGameRuleset_0) X2GameRuleset::SubmitGameStateContext (XComGameState_Ability_2673) XComGameState_Ability::MaybeApplyAbilityToUnitState (XComGameState_Ability_2673) XComGameState_Ability::OnUnitBeginPlay (X2TacticalGameRuleset_0) X2GameRuleset::SubmitGameStateInternal (X2TacticalGameRuleset_0) X2GameRuleset::SubmitGameStateContext (XComGameState_Ability_2648) XComGameState_Ability::MaybeApplyAbilityToUnitState (XComGameState_Ability_2648) XComGameState_Ability::OnUnitBeginPlay (X2TacticalGameRuleset_0) X2GameRuleset::SubmitGameStateInternal (X2TacticalGameRuleset_0) X2GameRuleset::SubmitGameStates (X2TacticalGameRuleset_0) X2GameRuleset::SubmitGameState (X2TacticalGameRuleset_0) X2TacticalGameRuleset::BeginTacticalPlay I know the soldier has the ability PA_BlindingSpitAbility; but maybe I haven't submitted it in the proper gamestate or some such. Can anybody suggest the reason? If you would like to look in the code, see the full modbuddy directory here: http://jendaveallen.com/Temp/PlayableAdvent0313.zip File PA_BlindingSpitEffect.uc contains the code generating the redscreen. File PA_Weapons.uc contains the two relevant weapons PA_PoisonSpitGlob and PA_BlindingSpitGlob.File PA_ViperTech.uc shows how the PA_PoisonSpitGlob is added to the new soldier.File PA_Abilities.uc contains the three abilities PA_PoisonSpit, PA_BlindingSpitItem and PA_BlindingSpitAbility. In case the code by itself may illuminate the problem, here is the entire contents of PA_BlindingSpitEffect.uc: class PA_BlindingSpitEffect extends X2Effect; simulated protected function OnEffectAdded(const out EffectAppliedData ApplyEffectParameters, XComGameState_BaseObject kNewTargetState, XComGameState NewGameState, XComGameState_Effect NewEffectState) { local XComGameState_Ability Ability; local XComGameState_Unit TargetUnit; local array<XComGameState_Item> Items; local XComGameState_Item Item; local int i; local name nm; local X2ItemTemplateManager ItemTemplateManager; local X2ItemTemplate ItemTemplate; local XComGameState_Item ItemState; Ability = XComGameState_Ability(NewGameState.GetGameStateForObjectID(ApplyEffectParameters.AbilityStateObjectRef.ObjectID)); TargetUnit = XComGameState_Unit(kNewTargetState); if (Ability != none && TargetUnit != none) { `log ("davea debug blinding effect enter for " @ TargetUnit.GetLastName()); Items = TargetUnit.GetAllItemsInSlot(eInvSlot_Unknown); for (i=0; i<Items.Length; i++) { Item = Items[i]; nm = Item.GetMyTemplateName(); if (nm == 'PA_PoisonSpitGlob') { `log ("davea debug found old poison spit"); TargetUnit.RemoveItemFromInventory(Item); // now add the replacement item ItemTemplateManager = class'X2ItemTemplateManager'.static.GetItemTemplateManager(); ItemTemplate = ItemTemplateManager.FindItemTemplate('PA_BlindingSpitGlob'); ItemState = ItemTemplate.CreateInstanceFromTemplate(NewGameState); TargetUnit.AddItemToInventory(ItemState, eInvSlot_Unknown, NewGameState); `log ("davea debug done adding new blinding spit"); break; } } } } Link to comment Share on other sites More sharing options...
Lucubration Posted March 14, 2016 Share Posted March 14, 2016 Try adding this after creating the instance of the item: NewGameState.AddStateObject(ItemState); Link to comment Share on other sites More sharing options...
davidlallen Posted March 15, 2016 Author Share Posted March 15, 2016 Doh! OK, that got rid of the redscreen, but there is still no effect. Changed code (one line change) now inhttp://jendaveallen.com/PlayableAdvent0314.zipI make two free vipers; "levelupaliens 3"; promote one viper up the left ability tree to get blinding spit; promote the other viper up the right ability tree to not get blinding spit; take both on a mission; and they both have poison spit. The `log statements are firing to tell me I am substituting blinding spit on the first viper, but it has no actual effect. Is "start of tactical" too late to go switching inventory around? Link to comment Share on other sites More sharing options...
Lucubration Posted March 15, 2016 Share Posted March 15, 2016 (edited) No, that's where I swap inventory around for doing my "transient items", which work perfectly fine for creating brand new items that are usable during tactical. Lemme take a closer look at what you linked. Edit: Ah, before I even do that, I have an idea where your problem may lie. Prior to entering tactical, all of the unit's items are merged (for ammo) and each resultant item is scanned for granted abilities. Those abilities are granted to the unit prior to entering tactical. If the blinding spit item actually grants a different ability, then you would also have to create the ability state and add it to the unit at the start of tactical when you grant the item. I think that you might have an easier time of it if you just put a new multi-target effect on the basic poison spit ability that caused blinding and gave it a 'X2Condition_AbilityProperty' for the Viper to have the blinding spit ability, which can just be a passive at that point. Edited March 15, 2016 by Lucubration Link to comment Share on other sites More sharing options...
davidlallen Posted March 15, 2016 Author Share Posted March 15, 2016 TBH the approach you described sounds way complicated and I didn't understand it fully. But, if custom gamestates and all that is needed, and there really isn't anything simpler, then I will dig in more. Any guidance you can offer will be appreciated. Link to comment Share on other sites More sharing options...
Lucubration Posted March 15, 2016 Share Posted March 15, 2016 (edited) No, custom gamestates shouldn't be needed. Let me show you real quick what I mean by adding the blinding effect to the poison spit. static function X2AbilityTemplate PA_PoisonSpit() { local X2AbilityTemplate Template; local X2StatusEffects DisorientedEffect; local X2Condition_AbilityProperty BlindingSpitCondition; ... // PA was Template.AddMultiTargetEffect(class'X2StatusEffects'.static.CreatePoisonedStatusEffect()); Template.AddMultiTargetEffect(CreatePA_PoisonStatusEffect(3)); // PA this only applies the normal poison effect, not mine Template.AddMultiTargetEffect(new class'X2Effect_ApplyPoisonToWorld'); // Lucubration: New effect that only happens if the Viper has Blinding Spit ability DisorientedEffect = class'X2StatusEffects'.static.CreateDisorientedStatusEffect(); BlindingSpitCondition = new class'X2Condition_AbilityProperty'; BlindingSpitCondition.OwnerHasSoldierAbilities.AddItem('PA_BlindingSpitAbility'); DisorientedEffect.TargetConditions.AddItem(BlindingSpitCondition); Template.AddMultiTargetEffect(DisorientedEffect); ... return Template; } That's basically just like how Holotargeting is added to primary weapon attacks, for example, but in this case you're only causing disorient when the poison spit ability is used if the unit has PA_BlindingSpitAbility. Edited March 15, 2016 by Lucubration Link to comment Share on other sites More sharing options...
davidlallen Posted March 15, 2016 Author Share Posted March 15, 2016 I think that you might have an easier time of it if you just put a new multi-target effect on the basic poison spit ability that caused blinding and gave it a 'X2Condition_AbilityProperty' for the Viper to have the blinding spit ability, which can just be a passive at that point. If only there were a guide for this kind of stuff ... I like the sound of this idea, but I have no idea what a X2Condition_AbilityProperty is. I have barely struggled through simple effects and conditions. If it gets easier, I would probably wind up with 3-4 different spit effects. Although the fact that ApplyPoisonToWorld is itself hard coded to apply CreatePoisonedStatusEffect makes it more complicated. Simply changing the poison status effect itself does not seem to change this, with the result that units *directly* hit by the poison would get the new effect, but units walking through the cloud later would get the basic viper effect. Link to comment Share on other sites More sharing options...
davidlallen Posted March 15, 2016 Author Share Posted March 15, 2016 OK, we are overlapping, and it's past my bedtime, so I will pick it up tomorrow. Thanks a million though. Link to comment Share on other sites More sharing options...
Lucubration Posted March 15, 2016 Share Posted March 15, 2016 (edited) I think that you might have an easier time of it if you just put a new multi-target effect on the basic poison spit ability that caused blinding and gave it a 'X2Condition_AbilityProperty' for the Viper to have the blinding spit ability, which can just be a passive at that point. If only there were a guide for this kind of stuff ... I like the sound of this idea, but I have no idea what a X2Condition_AbilityProperty is. I have barely struggled through simple effects and conditions. If it gets easier, I would probably wind up with 3-4 different spit effects. Although the fact that ApplyPoisonToWorld is itself hard coded to apply CreatePoisonedStatusEffect makes it more complicated. Simply changing the poison status effect itself does not seem to change this, with the result that units *directly* hit by the poison would get the new effect, but units walking through the cloud later would get the basic viper effect. Ah, I put it in a post just prior to yours. The ideas is that you're not changing the poison status effect, you're adding a whole new disorient effect (just like you did in the Blinding Spit item ability) to the Poison Spit item ability, and it is only conditionally applied based on whether the Viper took the Blinding Spit ability (in this case to the multi-targets). This way you don't have to mess with swapping out different items, it's all just attaching extra effects to the base ability by the unit taking extra abilities. You're right that units walking through the poison wouldn't get the extra effect. Hmm... that's going to take some more thinking. Alright, how I would handle it would be to copy the X2Effect_ApplyPoisonToWorld class wholecloth and update the 'GetTileEnteredEffects()' method to also apply blinding in addition to poison. Then I would create a new X2Condition class that only returned success if the soldier didn't have an ability. That way you could have the poison spit ability either apply "poison" or "blinding poison" to the world, depending on whether or not the Viper had the upgraded ability. You're welcome, and good luck. Edited March 15, 2016 by Lucubration Link to comment Share on other sites More sharing options...
davidlallen Posted March 15, 2016 Author Share Posted March 15, 2016 (edited) BlindingSpitCondition.OwnerHasSoldierAbilities.AddItem('PA_BlindingSpitAbility'); https://www.youtube.com/watch?v=GuAXcZmLNmM[/youtube] That works! Thanks a bunch. There is one small problem. Holotargeting, and the other uses, want to piggyback on an existing ability invisibly. However, for this application, I kind of need to change the ability button name and hover description. In other words, there is only one real ability in the button bar which is the basic poison one. It has the right name and hover description. But, when a soldier has the advanced blinding spit, their button still has the basic poison name and hover description. I need to change the name and hover description of the basic ability, when the soldier has the advanced ability. Any thoughts? Edited March 15, 2016 by davidlallen Link to comment Share on other sites More sharing options...
Recommended Posts