Jump to content

Mod help: conditional Blademaster?


SteelRook

Recommended Posts

For a few days now, I've been working on a mod to enhance the Blademaster skill in a conditional fashion. The long and short of it is I want the skill to do more than just +2 damage with swords, depending on the sword tech level. In the simplest of terms, I want the following:

 

  • +2 +0 damage for conventiona swords
  • +2 +1 damage for magnetic swords
  • +2 +2 damage for Beam swords
  • +0 +0 armour pierce for conventional swords
  • +0 +1 armour pierce for magnetic swords
  • +0 +2 armour pierce for beam swords

I've done quite a bit of work to make that happen already. I added six new stats to the XComGameData_WeaponData.ini file, which will handle the added stats for each type of sword. In order to save them, I created a new class specifically for swords, called X2SwordTemplate which extends the X2SwordTemplate class. I modelled this after the X2GremlinTemplate class, which means I basically made a special kind of weapon which holds two extra variables - one for extra damage, one for extra armour penetration. In order to build the all three types of sword as my new class, I had to overwrite the X2Item_DefaultWeapons class and alter all three sword template creation functions. They now use the new X2SwordTemplate class and stock it with bonus variables pulled from the ini file. All of this works so far, and hasn't been too difficult to set up once I figured out the syntax.

 

The problem is getting the ability to actually work. It's pretty obvious I'd need to overwrite the X2Ability_RangerAbilitySet class and tweak the Blademaster() function in there. The problem is I don't know how. The current Blademaster() function is fairly simple. It creates an ability template and stuffs a single X2Effect_BonusWeaponDamage object in there. I looked up X2Effect_BonusWeaponDamage in the hopes of making that damage effect "more conditional" than it already is and found it to have a single function to return damage if the source weapon mathces the weapon that the ability requires. This is where my problems lie - I don't understand how this check is done, and I don't know how to extend it. Let me post some code so we're all on the same page.

class X2Effect_BonusWeaponDamage extends X2Effect_Persistent;

var int BonusDmg;

function int GetAttackingDamageModifier(XComGameState_Effect EffectState, XComGameState_Unit Attacker, Damageable TargetDamageable, XComGameState_Ability AbilityState, const out EffectAppliedData AppliedData, const int CurrentDamage) 
{ 
	if (AbilityState.SourceWeapon == EffectState.ApplyEffectParameters.ItemStateObjectRef)
		return BonusDmg;

	return 0; 
}

This is what X2Effect_BonusWeaponDamage does. I checked X2Effect_Persistent and all it does is define a bunch of functions which return nothing, intended to be overwritten with proper returns. Fair enough. The GetAttackingDamageModifier() function checks if the weapon which spawned the ability matches the required weapon, and if so returns the bonus damage, which in this case is 2. That's not enough for me. I need to check the weapon itself for internal stats. I need access to the weapon's template so I can check for the two new variables I put in, and add them in as even more extra damage and even more extra armour pierce (which will come in a separate function). The problem is that the way this method gets the source weapon is AbilityState.SourceWeapon, which returns an object of type StateObjectReference, which I have no idea what that is. It's not defined anywhere in the XCOM 2 source code which leads me to believe it's something specific to the more general UnrealScript code, and I don't know how to reach the template that this weapon was made from, such that I know what its other settings are.

 

I was trying to copy the way that Specialist Gremlins handle their tech-dependent stats, but they seem to work in very... Odd ways that I don't fully understand. Moreover, I can't find anywhere in the skill definitions what weapons they're supposed to be executed by. I mean Blademaster gives me +2 damage with swords but not with shotguns, yet I don't see that specified anywhere in the code. So this is my question:

 

How can I make Blademaster's damage bonus dependent on the weapon's tech level? What am I doing wrong?

 

*edit*

My plan is to make a lot of skills in the game scale up with weapon level. Blademaster just seemed like a good proof of concept.

Edited by SteelRook
Link to comment
Share on other sites

  • Replies 84
  • Created
  • Last Reply

Top Posters In This Topic

if you say :

if (AbilityState.SourceWeapon== howEverYouDefineTheFirstSword)
    return BaseDamage;
else if (AbilityState.SourceWeapon== howEverYouDefineTheSecondSword)
    return BaseDamage+1;
else if (AbilityState.SourceWeapon== howEverYouDefineTheThirdSword)
    return BaseDamage+2;

it should return the damage, now i dont think you can do armor pierce in any way but taking the target and for each sword add damage like that:

ExtraAntiArmorDMG=min(Target.Armor, MySword.ArmorPen)

BaseDamage+=ExtraAntiArmorDMG;
Link to comment
Share on other sites

I don't know if it will help, but armor selection does vary by tech. That is, there is a reference to a tech field, in file X2SimpleBodyPartFilter.uc, function FilterByTech. This fetches the required tech from the armor part, and checks to see if that tech is researched yet. I suppose weapons may have the same, or similar variables. I haven't been able to see where the armor pieces are defined yet, but maybe you can find useful breadcrumbs from here.

Link to comment
Share on other sites

Armour Piercing shouldn't actually be an issue. I checked the definition for AP rounds (I forget the class name where that's defined) and all it does is use its own unique subclass of the X2Effect_Persistent class. The X2Effect_Persistent class already has functions for adding extra damage, adding extra shred, allowing reaction fire and - nestled among them - one for adding extra armour piercing. GetExtraArmorPiercing() by default returns 0, and all AP Rounds do is override this function to return 5 extra armour piercing if the character has the right item equipped. As a point of fact, I can bundle both effects into the same object by simply overriding both functions within my theoretical subclass, which I think I called something like X2Effect_Blademaster.

Also:

if you say :

if (AbilityState.SourceWeapon== howEverYouDefineTheFirstSword)
    return BaseDamage;
else if (AbilityState.SourceWeapon== howEverYouDefineTheSecondSword)
    return BaseDamage+1;
else if (AbilityState.SourceWeapon== howEverYouDefineTheThirdSword)
    return BaseDamage+2;


All three of my swords use the exact same class - X2SwordTemplate. If you're referring to the special sword names, I'm using the default ones - Sword_CV, Sword_MG, Sword_BM. However, I need to not just check if these are the correct swords. I want to access the special fields inside the sword template itself. I've done this for the sake of modularity, so that if I want to change how much extra damage or AP the swords get, I don't have to dig through the UnrealScript code, but can instead just alter the ini. This is more in case a mod user wants to tweak the mod.

 

Even the logical checks concern me a little, though. You mention "owEverYouDefineTheFirstSword" but I've defined it as a child of X2WeaponTemplate. AbilityState.SourceWeapon gives me an object of type StateObjectReference. I don't know what that is, and I don't know what I'm supposed to compare it to. Do I compare it to the sword name? I thought I was supposed to compare it to another object of StateObjectReference. I guess the code bit there confuses me considerably. Do you know of a way to get access to the weapon's actual template through its StateObjectReference representation? Typecasting obviously doesn't work, and I know of no other way to transition between the two.

Link to comment
Share on other sites

I don't know if it will help, but armor selection does vary by tech. That is, there is a reference to a tech field, in file X2SimpleBodyPartFilter.uc, function FilterByTech. This fetches the required tech from the armor part, and checks to see if that tech is researched yet. I suppose weapons may have the same, or similar variables. I haven't been able to see where the armor pieces are defined yet, but maybe you can find useful breadcrumbs from here.

 

Not a bad idea, though it's a different situation. FilterByTech(X2BodyPartTemplate Template) actually requires that the template itself be passed to it as a function parameter. It already has access to the template of the armour suit it's trying to investigate, so it can just ask for its internal stats directly. I can't reach the template of SourceWeapon in the function, or at least I don't know how to do that. If I can get the weapon template, then everything else is dirt simple. I'm trying to do something similar to the way Aid Protocol is handled in X2Effect_AidProtocol. The OnEffectAdded() function does offer me a means of obtaining the source weapon, but it does so through an object of type XComGameState, which X2Effect_Persistent.GetAttackingDamageModifier doesn't have access to as a function parameter.

 

Is there maybe some way I can pull that out of history?

 

*edit*

StateObjectReference is a reference to an object, you can get that object by StateObjectReference.ObjectID and looking for that id in `XCOMHISTORY (or whatever that macro is called)

 

And I get an answer before I even asked the question! :) Thank you, I'll try that.

Edited by SteelRook
Link to comment
Share on other sites

Well, I got the mod to compile, but I'm having strange issues with it. Is there any way I can print output directly to the screen during compilation so I can see the values in my various variables? Something's not getting the proper variables that it should be, but I can't tell what or when.

 

*edit*

I got the mod working for the most part. The problem, though, is that I can't seem to get the values to go through. I can put in any amount of armour penetration that I want to, I can get in any amount of extra damage, but the problem is that I can't get the sword-specific stats to carry over. Obviously something along the chain is breaking, and it seems to be the ability to pull data from the actual template. That's why I need to be able to see what the values are at run-time, but I can't for the life of me figure out how debugging even works. The debugger seems to quit as soon as I start the game.

Edited by SteelRook
Link to comment
Share on other sites

OK, now for some reason I can't override X2Item_DefaultWeapons any more. It worked before, but now it doesn't. Do I have to do anything special to override it? I thought all I had to do was put:

[Engine.Engine]
+ModClassOverrides=(BaseGameClass="X2Item_DefaultWeapons", ModClass="X2Item_DefaultWeapons_BE")

In XComEngine.ini, which I did before... And it worked before. But it doesn't work now. What gives? I mean I presume it doesn't work. None of the changes I make to weapon stats have any effect, and they used to. What am I doing wrong?

Link to comment
Share on other sites

You can use X2Conditions to add conditional effects to an ability. Take a look at the PsiOperative's 'Insanity' ability to see an example, whereby it adds an effect for 'Rupture' to insanity, which has the condition that the caster must have the ability 'schism'.

Many other abilities use similar conditionals, but I noticed that Firaxis wrote only the Condition classes that they needed, so you may need to extend their X2Condition classes with your own.

For instance, the Condition "X2Condition_UnitStatCheck" checks a stat on the target of the ability, so it's no good for checking for a stat on the user of the ability.
To get around this, I implemented a variant of the class that flips 'CallMeetsConditionWithSource' and 'CallMeetsCondition' around.

CallMeetsCondition = Check the target
CallMeetsConditionWithSource = Check the source (user of ability, when used in ability/effect conditions)

The best way to figure this stuff out is to look at some of the existing abiltiy defintions by Firaxis and see how they implemented conditional effects on those.~

Edit:

----
ModOverrides just stopped working for me sometime over the weekend as well and I just gave up on using that approach entirely. ScreenListeners with hackish injection of code is the way to go until Firaxis does something to improve the reliability of ModOverrides, I think.

Edited by Kvalyr
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...