Jump to content

Troubleshooting project build


Azworai

Recommended Posts

Okay, so... just to start off my foray into adding abilities, I was attempting to copy over Lucubration's Deep Reserves ability with his blessing, renaming it as I planned to change the skill a bit. However, the effect doesn't seem to be taking place... so I'll be copying several sets of code. Lucu's coding skills are beyond me, so I can't explain 100% how the code is supposed to function, but I was fairly certain I lifted what he said I needed to... so... many 'spoiler' dropdowns incoming.

 

X2Ability_HeavyClassAbilitySet

 

class X2Ability_HeavyClassAbilitySet extends X2Ability
config(HeavyClass);

var config float AdrenalineRushDamagePercentToHeal;
var config int AdrenalineRushMaxHealPerTurn;

static function array CreateTemplates()


{
local array Templates;
Templates.Length = 0;
Templates.AddItem(AdrenalineRush());

return Templates;
}
//---------------------------------------------------------------------------------------------------
// Adrenaline Rush
//---------------------------------------------------------------------------------------------------


static function X2AbilityTemplate AdrenalineRush()
{
local X2AbilityTemplate Template;
local X2Effect_AdrenalineRush Effect;

`CREATE_X2ABILITY_TEMPLATE(Template, 'AdrenalineRush');


Template.AbilitySourceName = 'eAbilitySource_Perk';
Template.eAbilityIconBehaviorHUD = eAbilityIconBehavior_NeverShow;
Template.Hostility = eHostility_Neutral;
Template.IconImage = "img:///UILibrary_PerkIcons.UIPerk_rapidregeneration";
Template.ShotHUDPriority = class'UIUtilities_Tactical'.const.CLASS_MAJOR_PRIORITY;

Template.AbilityToHitCalc = default.DeadEye;
Template.AbilityTargetStyle = default.SelfTarget;
Template.AbilityTriggers.AddItem(default.UnitPostBeginPlayTrigger);

// Combine stat change and event registration on the same effect
Effect = new class'X2Effect_AdrenalineRush';
Effect.EffectName = 'AdrenalineRush';
Effect.DuplicateResponse = eDupe_Ignore;
Effect.BuildPersistentEffect(1, true, false, , eGameRule_PlayerTurnBegin);
Effect.SetDisplayInfo(ePerkBuff_Passive, Template.LocFriendlyName, Template.GetMyLongDescription(), Template.IconImage,,,Template.AbilitySourceName);
Effect.HealAmountPerTurn = default.AdrenalineRushMaxHealPerTurn;
Effect.HealDamagePercent = default.AdrenalineRushDamagePercentToHeal;
Effect.HealthRegeneratedName = 'AdrenalineRushHealthRegenerated';
Effect.DamageTakenName = 'AdrenalineRushDamageTaken';
Template.AddTargetEffect(Effect);

Template.BuildNewGameStateFn = TypicalAbility_BuildGameState;
// NOTE: No visualization on purpose!

return Template;
}

 

 

X2Effect_AdrenalineRush

 

class X2Effect_AdrenalineRush extends X2Effect_Persistent;

// I can't get these to stick on persistent effects. Perhaps because of how I'm doing my testing? I'm sticking them on the state object for later persistence
var int HealAmountPerTurn;
var float HealDamagePercent;
var name HealthRegeneratedName;
var name DamageTakenName;

simulated protected function OnEffectAdded(const out EffectAppliedData ApplyEffectParameters, XComGameState_BaseObject kNewTargetState, XComGameState NewGameState, XComGameState_Effect NewEffectState)
{
local XComGameState_Unit TargetUnit;
local XComGameState_Effect_AdrenalineRush AdrenalineRushEffectState;
local X2EventManager EventMgr;
local Object ListenerObj;

if (GetAdrenalineRushComponent(NewEffectState) == none)
{
TargetUnit = XComGameState_Unit(kNewTargetState);

// Create component and attach it to GameState_Effect, adding the new state object to the NewGameState container
AdrenalineRushEffectState = XComGameState_Effect_AdrenalineRush(NewGameState.CreateStateObject(class'XComGameState_Effect_AdrenalineRush'));
AdrenalineRushEffectState.HealAmountPerTurn = HealAmountPerTurn;
AdrenalineRushEffectState.DamageTakenName = DamageTakenName;
AdrenalineRushEffectState.HealDamagePercent = HealDamagePercent;
AdrenalineRushEffectState.HealthRegeneratedName = HealthRegeneratedName;
AdrenalineRushEffectState.UnitRef = TargetUnit.GetReference();
NewEffectState.AddComponentObject(AdrenalineRushEffectState);
NewGameState.AddStateObject(AdrenalineRushEffectState);

EventMgr = `XEVENTMGR;

// The gamestate component should handle the callback
ListenerObj = AdrenalineRushEffectState;

EventMgr.RegisterForEvent(ListenerObj, 'UnitTakeEffectDamage', class'XComGameState_Effect_AdrenalineRush'.static.OnUnitTakeEffectDamage, ELD_OnStateSubmitted, , TargetUnit);

//`LOG("Heavy Class: Adrenaline Rush passive effect registered for events.");
}

super.OnEffectAdded(ApplyEffectParameters, kNewTargetState, NewGameState, NewEffectState);
}

function bool RegenerationTicked(X2Effect_Persistent PersistentEffect, const out EffectAppliedData ApplyEffectParameters, XComGameState_Effect kNewEffectState, XComGameState NewGameState, bool FirstApplication)
{
local XComGameState_Effect_AdrenalineRush AdrenalineRushEffectState;
local XComGameState_Unit OldTargetState, NewTargetState;
local UnitValue DamageTaken, HealthRegenerated;
local int MaxAmountToHeal, AmountToHeal, Healed;

//`LOG("Heavy Class: Adrenaline Rush regeneration ticked.");

AdrenalineRushEffectState = GetAdrenalineRushComponent(kNewEffectState);

OldTargetState = XComGameState_Unit(`XCOMHISTORY.GetGameStateForObjectID(ApplyEffectParameters.TargetStateObjectRef.ObjectID));

if (OldTargetState.IsDead())
{
//`LOG("Heavy Class: Adrenaline Rush unit not healed (unit is dead).");
return false;
}

OldTargetState.GetUnitValue(AdrenalineRushEffectState.DamageTakenName, DamageTaken);
OldTargetState.GetUnitValue(AdrenalineRushEffectState.HealthRegeneratedName, HealthRegenerated);

//`LOG("Heavy Class: Adrenaline Rush damage taken = " @ string(DamageTaken.fValue) @ ".");
//`LOG("Heavy Class: Adrenaline Rush health regenerated = " @ string(HealthRegenerated.fValue) @ ".");

// Max heal amount is determine based on this formula
MaxAmountToHeal = int((AdrenalineRushEffectState.HealDamagePercent * DamageTaken.fValue) - HealthRegenerated.fValue);
if (MaxAmountToHeal <= 0)
{
//`LOG("Heavy Class: Adrenaline Rush unit not healed (max amount to heal reached " @ string(AdrenalineRushEffectState.HealDamagePercent * DamageTaken.fValue) @").");
return false;
}

// Ensure the unit is not healed for more than the maximum allowed amount
AmountToHeal = min(AdrenalineRushEffectState.HealAmountPerTurn, MaxAmountToHeal);

// Perform the heal
NewTargetState = XComGameState_Unit(NewGameState.CreateStateObject(OldTargetState.Class, OldTargetState.ObjectID));
NewTargetState.ModifyCurrentStat(estat_HP, AmountToHeal);
NewGameState.AddStateObject(NewTargetState);

// Save how much the unit was healed
Healed = NewTargetState.GetCurrentStat(eStat_HP) - OldTargetState.GetCurrentStat(eStat_HP);

//`LOG("Heavy Class: Adrenaline Rush regeneration healed for " @ string(Healed) @ ".");

if (Healed > 0)
{
NewTargetState.SetUnitFloatValue(AdrenalineRushEffectState.HealthRegeneratedName, HealthRegenerated.fValue + Healed, eCleanup_BeginTactical);

//`LOG("Heavy Class: Adrenaline Rush total healed by unit " @ NewTargetState.GetFullName() @ " updated to " @ string(HealthRegenerated.fValue + Healed) @ ".");
}

return false;
}

static function XComGameState_Effect_AdrenalineRush GetAdrenalineRushComponent(XComGameState_Effect Effect)
{
if (Effect != none)
return XComGameState_Effect_AdrenalineRush(Effect.FindComponentObject(class'XComGameState_Effect_AdrenalineRush'));
return none;
}

simulated function AddX2ActionsForVisualization_Tick(XComGameState VisualizeGameState, out VisualizationTrack BuildTrack, const int TickIndex, XComGameState_Effect EffectState)
{
local XComGameState_Unit OldUnit, NewUnit;
local X2Action_PlaySoundAndFlyOver SoundAndFlyOver;
local int Healed;

OldUnit = XComGameState_Unit(BuildTrack.StateObject_OldState);
NewUnit = XComGameState_Unit(BuildTrack.StateObject_NewState);

Healed = NewUnit.GetCurrentStat(eStat_HP) - OldUnit.GetCurrentStat(eStat_HP);

if( Healed > 0 )
{
SoundAndFlyOver = X2Action_PlaySoundAndFlyOver(class'X2Action_PlaySoundAndFlyOver'.static.AddToVisualizationTrack(BuildTrack, VisualizeGameState.GetContext()));
SoundAndFlyOver.SetSoundAndFlyOverParameters(None, "+" $ Healed, '', eColor_Good);
}
}

defaultproperties
{
EffectName="Regeneration"
EffectTickedFn=RegenerationTicked
}

 

 

XComGameState_Effect_AdrenalineRush

 

class XComGameState_Effect_AdrenalineRush extends XComGameState_BaseObject
config (HeavyClass);

var int HealAmountPerTurn;
var float HealDamagePercent;
var name HealthRegeneratedName;
var name DamageTakenName;
var StateObjectReference UnitRef;

function EventListenerReturn OnUnitTakeEffectDamage(Object EventData, Object EventSource, XComGameState GameState, Name EventID)
{
local UnitValue LastEffectDamage, DamageTaken;
local XComGameState NewGameState;
local XComGameState_Unit Unit;

//`LOG("Heavy Class: Adrenaline Rush 'UnitTakeEffectDamage' event listener delegate invoked.");

// Grab the unit
Unit = XComGameState_Unit(EventSource);
if (Unit.ObjectID != UnitRef.ObjectID)
{
//`LOG("Heavy Class: Adrenaline Rush not activated (not Adrenaline Rush unit).");

return ELR_NoInterrupt;
}

// Get the damage taken from the effect
Unit.GetUnitValue('LastEffectDamage', LastEffectDamage);

// Get the total damage taken counter
Unit.GetUnitValue(DamageTakenName, DamageTaken);

// Update the total damage taken counter
NewGameState = class'XComGameStateContext_ChangeContainer'.static.CreateChangeState(string(GetFuncName()));
Unit = XComGameState_Unit(NewGameState.CreateStateObject(Unit.Class, Unit.ObjectID));
Unit.SetUnitFloatValue(DamageTakenName, DamageTaken.fValue + LastEffectDamage.fValue, eCleanup_BeginTactical);
NewGameState.AddStateObject(Unit);

`TACTICALRULES.SubmitGameState(NewGameState);

//`LOG("Heavy Class: Adrenaline Rush damage taken by unit " @ Unit.GetFullName() @ " updated to " @ string(DamageTaken.fValue + LastEffectDamage.fValue) @ ".");

return ELR_NoInterrupt;
}

 

 

HeavyClass_AbilitySet.ini

 

[HeavyClass.X2Ability_HeavyClassAbilitySet]
AdrenalineRushDamagePercentToHeal=0.75f
AdrenalineRushMaxHealPerTurn=3

 

 

I haven't yet done any localization for the ability, but I had assumed that only explains to the user what this passive-effect does(I want to do that eventually, but I want the effect to function before I worried about it.)

 

I am clueless as to where the error is... I apologize for the sheer amount of coding to sift through, but I'm lost. Thanks in advance!

Link to comment
Share on other sites

OK, if there are log statements in the code, that is good enough. In the steam library for xcom2, right click, properties menu, in the launch options field make sure "-log" is there. When you run the game, you should see an extra console window come up (you should put the game in windowed mode instead of full screen). Then you will be able to see the messages go by. Sometimes there are too many messages to see them all. After you exit the game, you can look in directory My Games\XCOM2\Logs (I believe), and the latest log file will be in launch.log. You can search for the log messages using your text editor.

 

If the messages you expect do not appear, then check to make sure the right lines are present in XComEngine.ini, etc.

Link to comment
Share on other sites

Okay, so... just to start off my foray into adding abilities, I was attempting to copy over Lucubration's Deep Reserves ability with his blessing, renaming it as I planned to change the skill a bit. However, the effect doesn't seem to be taking place... so I'll be copying several sets of code. Lucu's coding skills are beyond me, so I can't explain 100% how the code is supposed to function, but I was fairly certain I lifted what he said I needed to... so... many 'spoiler' dropdowns incoming.

 

Aside from the issues you are experiencing, I strongly suggest you get my latest version to work from. My previous versions had a bug which showed up over time and ended up causing CTDs because they weren't cleaning up the effect gamestate objects correctly. This turns out to be a very important detail, much worse than the effect just not working.

Link to comment
Share on other sites

 

 

Aside from the issues you are experiencing, I strongly suggest you get my latest version to work from. My previous versions had a bug which showed up over time and ended up causing CTDs because they weren't cleaning up the effect gamestate objects correctly. This turns out to be a very important detail, much worse than the effect just not working.

 

I was pulling from your version 1.1, have you released a newer version since then? I had noticed a CTD after completing my last mission in one of my playthroughs, but I had been attributing the crash to me breaking my heavy class with my attempted yet incomplete project.

Link to comment
Share on other sites

A comment on the Mod IDE:

 

We in turn were disappointed at some of the issues that are apparent in VS isolated shell custom project library that Modbuddy is using. Some of the basic project operations that have problems were expected to work "out of the box" but sadly it wasn't so ... and fixing them couldn't be worked into the schedule alongside the game.

 

Either way, when we have bandwidth to fix the custom project code we'll take care of it. And long term - ultimately, our goal is to replace our internal code workflow ( uses a lot of tools that cannot be distributed ) with what Modbuddy uses and then this issue will be resolved.

Link to comment
Share on other sites

 

 

 

Aside from the issues you are experiencing, I strongly suggest you get my latest version to work from. My previous versions had a bug which showed up over time and ended up causing CTDs because they weren't cleaning up the effect gamestate objects correctly. This turns out to be a very important detail, much worse than the effect just not working.

 

I was pulling from your version 1.1, have you released a newer version since then? I had noticed a CTD after completing my last mission in one of my playthroughs, but I had been attributing the crash to me breaking my heavy class with my attempted yet incomplete project.

 

Yes, version 1.3 has the fixes for that CTD. There's basically another event registration after creating the GameState object that will clean it up in the history after the mission ends; otherwise, as Amineri found out for us, it will hang around and eventually cause the CTD some time down the line (typically the start or the end of the next mission).

Link to comment
Share on other sites

That error, was it an Unhandled win32 exception in XCom2.ece [3836]?

 

Odd that it's occuring for me, since I don't even HAVE Deep Reserves selected on any soldiers. Was just doing a playthrough. Ohwell. For some reason I suspect I'll still have issues implementing the code into my heavy class with 1.3, if anyone could troubleshoot what I linked for errors, I'd appreciate it.

Link to comment
Share on other sites

Either way, when we have bandwidth to fix the custom project code we'll take care of it. And long term - ultimately, our goal is to replace our internal code workflow ( uses a lot of tools that cannot be distributed ) with what Modbuddy uses and then this issue will be resolved.

 

Please do so... along with some other "priority" stuff that were mentionned by many people in various threads here;

 

1) Straight Hooks to Texture libraries (addressable through new INI capacity if possible but still highly desirable)

--- Pet-Peeve of mine (( ex;http://forums.nexusmods.com/index.php?/topic/3847470-help-adding-a-simple-ui-texture/?p=35050245 )).

2) Intellisense IDE. Or whatever else can clear up the fog-of-Unreal-cloud for a bit and for a full srl byte stack push worth.

3) More explicit documentation details on a variety of subjects. We got ourselves cool PPT gimmicks, yet seriously... nothing like a crash course in a wild CHM that (could) reveals much more operands and instructions and declarations block.. -- you name it.

 

I understand Firaxis isn't really there to teach most or a few of us how to deal with some minimal Modding skills... but i'm fairly certain a LOT of splendid concepts and ideas would never come to reality just because the daunting tasks and logic essentials aren't easy to grasp by a fair chunk of the fan-base.

 

The game itself is amazing and IMHO, deserves the best follow-up mod potentials it can (or should) receive.

 

Thanks for passing-by and visiting our precious Nexus community. :smile:

Edited by Zyxpsilon
Link to comment
Share on other sites

  • Recently Browsing   0 members

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