PDA

View Full Version : Creative Assembly AntiTraits : now what the heck is happening here ?



Kobal2fr
12-21-2006, 19:16
Buggy as hell, or I don't get how things should work ?

My understanding was that when a character had a given trait, and gained one point in it's anti-trait, then said trait gets -1, anti-trait 0, and that's it.

But I'm beginning to believe that when you gain 1 point in an anti-trait, the trait simply disappears altogether ! Which would explain why Assassins failing their missions go from "Experienced Assassin" to "Simpleton".

Case in point : start a campaign as Scotland. The prince has 2 StrategyDread, 2 BattleDread. I use him to capture York. Win, choose Occupy City, which gives 1 StrategyChivalry : all StrategyDread vanishes, instead of being reduced to 1.

So, are antitraits really meant to be "remove all levels of opposing traits when you gain this" ?
Because if that's the case... maaaan does there need to be a LOT more triggers and fixes to the traits files :/

And if they aren't, CA needs to be told FAST.

How were they used in RTW, does anyone know ?

alpaca
12-21-2006, 19:45
Yes I suspect that, too.
In RTW they worked differently (1 point in AntiTrait resulted in -1 in the Trait), but maybe they changed that behaviour deliberately in MTW2, because you can use negative affects values to make traits go lower.
However, I don't think that is the case and it is indeed a bug.

Bob the Insane
12-22-2006, 17:21
In Vices & Virtues FIXES v1.0 -

See:

https://forums.totalwar.org/vb/showthread.php?t=75661

and:

https://forums.totalwar.org/vb/local_links.php?catid=135


The author stats:

"Assasssins / Princesses / Diplomats losing all Good- traits instead of one point on unsuccessful mission: Now working as intended, failed missions now only reduce trait by one point."

Could this be related?

Jace11
12-22-2006, 19:26
Was it not working ok in 1.0? I seem to remember my assassins kept missing but didn't lose all their skills..

Foz
12-22-2006, 22:44
LOL! You're always a step ahead of me, Kobal. I was thinking yesterday that I would come on today and start up a thread about antitraits since I wasn't sure how exactly they were working or were supposed to be working. I show up, and voila, you already have one up. Good stuff.

As for the potential bug where agents commonly lose massive amounts of skill by failing, I'm fairly certain the antitraits code is at fault as you've suggested. We can presumably see all the pertinent triggers in the traits file for various agents failing missions. None of them give more than 1 point to any of the bad traits, nor do I see any particular failure situation that should result in 3 or more triggers (they could gang up to produce the effect we're all noticing - I use 3, because I know I've witnessed an agent lose at least that much skill from 1 failure before)... yet I too have noticed whole trait lines just vanish. So what is going on? If nothing we can see in the traits file can cause it to happen, it must be something we can't see, and antitraits code is about the only thing we can't see that would be A. associated with traits in any way and B. also designed to affect them. So in the presence of a very likely theory and the absence of any other reasonable explanation, I think we should operate under this assumption until we have reason not to.

Next topic: is the effect of antitraits as intended? I say no. It creates a ridiculous back-and-forth effect in traits, as a powerful line can just immediately vanish, and the character starts down the opposite road. The fact that RTW used them as the 3 of us intuitively think it should be is another indicator that it hasn't ended up doing what they intended. Why would the devs intentionally change a mechanic that is liked well enough and functions properly? I would also suggest that we ought to change it, even if it is as intended - a majority of people seem to not like the harsh punishment for agent failures, and agree that it is suspicious and unbalanced at best. I'm open to hear views though, if anyone isn't as sure that we should find a workaround.

So... if we are to make it work as we think it was intended, then what must be done? My idea is to avoid the antitrait mechanic by just giving -1 point to the appropriate trait in any situation where its opposite would normally receive an antitrait point. As far as I can see, the workaround goes like this:

- Remove all antitrait references from the trait entries. This is because we will have to set them up without using the antitrait mechanic to avoid the problematic code that we can't get at. Note that this is the last thing to do, so you don't lose track of what traits are opposites!

- Duplicate each trigger that contains an antitrait (not the word, but a trait that has one or more opposite) so you end up with a pair of triggers per antitrait it can give a point (or more) to: i.e. 3 possible antitraits makes 2(3) = 6 triggers necessary. This is because we will use "Affects OppositeTrait -1 Chance n" to work around the antitrait code. Since you want to still allow bad traits to happen, the extra triggers will be necessary to determine when a trait already has point(s) and should be decremented instead of the opposite trait being incremented.

- Setup the triggers for each event in pairs (one is for the antitrait being > 0, the other for not > 0), and change the Affects lines accordingly.

So if the original trigger could give BadAdministrator and BadTaxman, each pair of new triggers now corresponds to one of the two traits' anti-traits: The first pair will check for GoodAdministrator > 0, while the second checks for GoodTaxman > 0. If either one is true, we'll subtract from the Good trait instead of adding to the Bad one (which would cause the anti-trait code we're working around). So a trigger like this:

Trigger trigger1
When ToTest CharacterTurnEnd

Condition Original_Conditions

Affects BadAdministrator 1 Chance 3
Affects BadTaxman 1 Chance 3

Becomes something like this:

Trigger trigger1
WhenToTest CharacterTurnEnd

Condition Original_Conditions
and not GoodAdministrator > 0

Affects BadAdministrator 1 Chance 3

Trigger trigger2
WhenToTest CharacterTurnEnd

Condition Original_Conditions
and GoodAdministrator > 0

Affects GoodAdministrator -1 Chance 3

Trigger trigger3
WhenToTest CharacterTurnEnd

Condition Original_Conditions
and not GoodTaxman > 0

Affects BadTaxman 1 Chance 3

Trigger trigger4
WhenToTest CharacterTurnEnd

Condition Original_Conditions
and GoodTaxman > 0
Affects GoodTaxman -1 Chance 3

If I'm wrong on any of this, just let me know.

Also as a side note... each trigger with n different possible anti-trait effects now will require 2n separate triggers. IIRC some triggers have as many as 5 traits, so this might be a lot of additions...

Shahed
12-23-2006, 00:39
Something I wanted to add.

No going back levels are not working either. It happens that you've reached the no going back level for a trait, but if you pop an anti-trait it can completely remove your trait line, even though your character is supposed to have passed the threshold for possible loss of this trait.

pellik
12-23-2006, 08:16
The traits have been bothering me a good deal as well.
I've made myself a small trait editing program (of sorts), and I don't see why I can't extend it to fix the traits as you've mentioned. (Actually I've been doing just that since before I read this post, but thats beside the point.)

Unfortunately I am away from home for the holiday and I don't have access to the game for another few days. This means that I can't test either the fixes I think should work nor test the ideas I think might work. If any of you other guys fooling around with the traits file want to test a few things for me then I can probably get a mod traits up on Sunday evening.

Before I do something so klunky as duplicating half the triggers I want to find out a few things that might make this far more elequent:

1) Can we use the docudemon commands in the traits file? An IF in the traits would not only make this fix clean, it will open doors for other modders.

2) Can we use conditions in the trait definition instead of the trigger definition? This will also keep the file more human parsable then duplicating triggers. Although the usefullness of a condition is somewhat limited without some sort of an else.

3) Does condition placement effect only lines after the condition?
For example:
Trigger MyTrigger
WhenToTest CharacterTurnEnd

Affects BattleChivalry 1 Chance 100

Condition Trait BattleDread >=1

Affects BattleChivalry -1 Chance 100
Affects BattleDread 1 Chance 100

Much thanks if someone could let me know.

Sorry if this doesn't make sense. I am very tired.

Kobal2fr
12-23-2006, 11:13
@Bob : yeah, that's what ticked me off on the antitraits not working actually. I checked what he did to make the assassins go -1 instead of all the way down, and sure enough, he's duplicated all assassin/diplo/spy mission triggers to check if trait>0 then trait -1 if trait=0 then antitrait 1.

Which is exactly what the_foz suggests, and what I'd been thinking as well. The problems are :

1) that's a truckload of triggers to duplicate/quadruple/sextuple, with min AND max conditions if nogoinback doesn't work either. We'd basically double/treble the size of the file, and more triggers mean more checks mean more time spent checking. Also means more work to change otherwise simple paramaters.

2) there are some triggers that are just plain too relying on antitrait code to fix easily. I'm thinking of the marriage ones here, with a slew of "if Drink =2 Then Sober 8 60%" "if Drink = 3 then Sober 12 60%" etc... which rely on the antitrait system not only to reduce a given trait, but actively give the relevant antitrait.

And something like :

Condition Drink = 3

Affects Drink -3 60%
Affects Sober 4 60%


Doesn't work, because you could get one or the other :/

The only thing to do here would be to duplicate once more, have these triggers give an unused trait like GoodGunpowderGeneral 60% (trait which can't be used/made to work for lack of the relevant trooptype variable). Then make another trigger right under it with same condition that also checks wether GoodGunpowderGeneral exists, and if so then Drink -3 100% Sober 4 100% GoodGunpowderGeneral -1 100%.

But like I said, that's a LOT of triggers to rework, meaning also a LOT more chances to bork stuff up. Plus the lazyness in me cries out : "Let CA fix their mess first ! Tell'em it dun't work properly ! Less work for us both, K. Have a pretzel instead." :)

@pellik :
1) perhaps, but ifs and whiles and loops tend to hog a lot of proc time when let loose, dont' they ? if so we'd have to ask ourselves if it wouldn't bring a lesser comp than ours to its knees, or unduly lenghten the between-turns time since triggers also affect the AI

2) big no-no. You don't mix actual code in the definition of a variable :) I mean, I'm not sure it's not possible, I'm not home so I can't check, but I'm certain it's Bad programming form

3) hmm good question. I don't think it's possible, triggers being very simple "when if do" syntax from what I can see, in fact it seems adding more than 3 Affects to the same trigger is not advised (hence the 20 or 30 birth triggers instead of just a big one). But it's a good idea nevertheless, I'll test that ASAP when I get home on tuesday

pellik
12-23-2006, 12:13
Kobal2fr:

At #1 again:
I'm disinclined to believe that the traits file is responsible for much of the overall workload between turns. But I guess the test could be to remove all triggers and play the game without traits. (Just removing triggers so the initial campaign doesn't need to be edited). I'll give this a shot on Tuesday night or Wednesday.

Also it seems that most of the triggers in the game only come up at specific times. Upon a marrage and such. Another load limiting factor.

Finally consider that an if statement fix would circumvent needing the AntiTrait conditions, and the AntiTrait loop wouldn't run in place of an if we control running. Replacing one loop with another is probably going to be a lot faster then running twice as many trigger checks.

Not that any of this matters since we don't know if we can use control loops in the traits file anyhow.

Regarding foz's method of doubling up the triggers:
The script I've been writing for statistical analysis of the traits I can modify to auto-generate a new file with fixed triggers. I just dont want to do this until I've given up on being able to use the other potential solutions I mentioned in my previous post.


One last thing @Kobal:
Do you have a more indepth changelog for your traits fixes? I havn't diffed it to the vanilla yet, but since you're deleting blocks I'm not sure how useful it would be. Maybe you could release version updates as diff files (patch.diff) as well so modded files can stay somewhat compatible?

Foz
12-23-2006, 20:13
Regarding pellik's #3: Yes it's probably very safe to say that Conditions only affect the lines following the Condition statement. However, I would guess code like you've suggested isn't going to happen. The structure of the txt file seems very rigid, and we already know (from the fact that it accepts modification) that the game must parse it for use. Anyone that's used a parser before knows how unforgiving they typically are, so as far as code like this is concerned...

Trigger MyTrigger
WhenToTest CharacterTurnEnd

Affects BattleChivalry 1 Chance 100

Condition Trait BattleDread >=1

Affects BattleChivalry -1 Chance 100
Affects BattleDread 1 Chance 100

...I would surmise that since it never shows up in an Affects-Condition-MoreAffects format in the traits file, the parser probably doesn't handle that case. Nevertheless I'll see about setting one up like that to find out what happens. Something like a huge diplo skill boost for a new diplomat upon creation should work well, as it's easy to churn out a new diplo and see if he has 9 or 10 skill instead of his normal amount. Of course I might not get that far, as an unparseable traits file could make me CTD.

As an additional note, I think it's very unlikely we can use logic like IF, loops, etc in this file. Again I would cite the fact that the game code has to parse the txt file into some useable format, and allowing loops in the file would have made that parser ridiculously more complicated than it has to be. It's probably the exact reason that antitraits are handled entirely outside of the traits file: it's far more easy to associate traits with a word and define that association in actual code somewhere else, than it is to associate them using logic in the traits file and then have to parse that logic into code. It's just unfortunate for us that we can't actually mod the antitraits code, as I'm sure it would be a matter of only a few lines to make it do exactly what we think it should.

A few other ideas to toss out:

1. @Kobal: I have been thinking, and possibly have something on that 2) problem you mentioned. Without the Antitrait tags in the file, the game should allow opposite traits to exist with points in each... so you won't even need to mess with an unused trait to keep track. You do this:

Trigger trig1
Condition Drink = 3
Affects Sober 12 60%

Trigger trig2
Condition Drink = 3
and Sober = 12
Affects Trait Drink -3 100%
Affects Sober -3 100%

The important thing is that the trigger right before trig2 is the only way they'd get to be at 3 and 12 respectively (because the rest of my code inherently makes sure they can't be positive at the same time), so trig 2 can only run if trig1 hit success.

2. Another concept would be to use trig1 as is and ignore trig2 altogether, instead opting to simulate anti-trait code with additional triggers. This makes even MORE triggers though... but I'm not convinced it would cause any real slowdown (the computer can pretty much FLY through a few extra conditionals, especially since they'd be false most of the time), and would be easy to crank out in the file via automation. It also has the huge benefit of requiring no changes to any triggers already in the file, and only the removal of the Antitrait tag from all trait definitions. To explain better, if we're talking about marriage code here, you'd append to the file some triggers that check:

when marriage
if trait1 > 0
and antitrait1 > 0
then trait1 -1 100%
antitrait1 -1 100%

You'd copy that like 25 times for each trait/antitrait pair that could come into conflict during marriage. This is essentially a far less eloquent implementation of a while loop. I don't think anything actually gives a trait 25 points ever... so you could just cap the copies at whatever the biggest trait jump is that's in the file, and the code would balance it until at least one of the traits is zero again. This can be done for each WhenToTest time, over all traits.

The real beauty of it is in our ability to generate the code through a simple routine, though. We can parse the Vanilla traits file to find trait definitions and their associated antitraits, as well as all WhenToTest condition names (unless there's an All feature I don't remember seeing). This should be easy due to how rigid and formulaic the traits file is. Then you generate like 25 triggers for each antitrait family, for each checktime. Append them all to the file, and you should have achieved intuitive anti-trait functionality, without the broken anti-trait code.

The only thing left to consider would be how to implement situations where multiple traits are listed as antitraits for another.

Sarastro
12-24-2006, 19:32
In Vices & Virtues FIXES v1.0 -

See:

https://forums.totalwar.org/vb/showthread.php?t=75661

and:

https://forums.totalwar.org/vb/local_links.php?catid=135


The author stats:

"Assasssins / Princesses / Diplomats losing all Good- traits instead of one point on unsuccessful mission: Now working as intended, failed missions now only reduce trait by one point."

Could this be related?

Hey folks, found this problem when I first started modding M2 traits (I authored the Vices & Virtues FIXES mod, different username on this forum :) ), and managed to hotfix it, but there does seem to be a hardcode problem.

Just like to say hi to Kobal quickly, and thank you for your mod, you found a lot of stuff that I missed out first time round, was most helpful being able to see someone else's mod along the same lines, so thanks!

I think, but haven't tested thoroughly, that a part of the anti-trait hardcode is broken. In RTW, anti-traits had two functions. One, having X trait would disallow any of its anti-traits. Two, 1 point in that trait would = -1 point in the anti-traits. This meant that the RTW triggers operated a scale between trait & anti-trait like thus:

EXAMPLE

BadCommander 4 3 2 1 NEUTRAL 0 NEUTRAL 1 2 3 4 5 6 GoodCommander

So the triggers which give 1 point in BadCommander for losing a battle would simply take 1 point off GoodCommander if that character had points in GoodCommander. NoGoingBackLevels would simply mean that once the character was advanced enough in a trait, he wouldn't lose it past that level.

In Medieval 2, it seems that code is broken. So if you gain 1 point in BadCommander, that trait will appear, and since GoodCommander is the anti-trait, it will dissapear. The new trait overrides the old anti-trait. The result was that if there isn't a NoGoingBackLevel, then as soon as you gain 1 point in the Bad- trait, you will lose all points in any GoodTrait. If there is a NoGoingBackLevel, as soon as you gain 1 point in the Bad- trait, you will go straight to the NoGoingBackLevel of the Good- trait.

This is a little annoying. However, -1 Trait as a trigger value still works, so my fix (example for diplomats) is this:

;------------------------------------------
Trigger agents27
WhenToTest DiplomacyMission

Condition MissionSucceeded

Affects GoodDiplomat 1 Chance 100

;------------------------------------------
Trigger agents28
WhenToTest DiplomacyMission

Condition not MissionSucceeded

Affects GoodDiplomat -1 Chance 50

;------------------------------------------
Trigger agents28_baddiplomat
WhenToTest DiplomacyMission

Condition not MissionSucceeded
and AgentType = diplomat
and Trait GoodDiplomat < 1

Affects BadDiplomat 1 Chance 50

Tested that thoroughly with various agents, and it works going up and down the scale, so effectively it should work like RTW again. However, it does required a lot more triggers and thinking when writing new traits.

As for broken NoGoingBackLevels, I haven't noticed that myself, but it could well be related to the above.

I don't know exactly what is going on in the code, but at a guess I would say it is either: the latest gained trait over-rides existing traits more than it should, or the code for anti-traits has been changed so that they no longer = -1 point in corresponding traits.

Hope that is some use.

PS The longer I work on the traits, the more it looks to me like whoever did them for M2 was a) not the same person who developed it for RTW, b) doesn't quite understand how they work, c) had to rush the job. The good news is that there are now many more conditions which seem to work within the traits & strat functions, so there seems to be a lot of opportunity for modding.

Foz
12-25-2006, 02:59
I agree with everything you've said, Sarastro. I had surmised the exact same thing about the antitrait hardcode, since nothing in the trait file could be causing the issue. As for your solution, it works for agents, but can't be applied directly to other situations. The primary reason is that the agent-affecting traits never gain more than 1 point at once for their success or failures. This allows the simple +1/-1 trigger pairs that you implemented, which admittedly IS the easiest way to fix the agents. However, as Kobal pointed out in the coming-of-age triggers, the marriage triggers, and others, sometimes traits like sobriety have a chance of gaining huge amounts of points, like 8 or more. There's no easy way to setup a similar trigger pair to fix that, as the points are typically split across removing antitrait and adding trait. So 8 points of sobriety at 60% chance doesn't equal -3 pts drink at 60% and 5 pts of sobriety at 60%, because there's no way to make sure the 2nd triggers if and only if the first does, short of actually testing to see, which makes yet another trigger and is messy to boot. See #1 from my last post for how this would work, though I don't recommend trying to do this to the file.

I would also point out that the code you displayed is not quite right yet: you've allowed an agent with 0 GoodDiplomat pts to still have 1 removed half the time, and then have a chance to gain a BadDiplomat point as well. This means a failed mission could cause a 2-point swing in any diplo with 1 or less GoodDiplomat points, since both triggers will go off - and he could also get a negative GoodDiplomat stat, which is something undefined in game terms as far as I know. The fix is to make the triggers mutually exclusive by testing the first trigger as well. You check for GoodDiplomat > 0 (or >= 1 if you prefer), which then prevents GoodDiplomat from becoming negative ever, and keeps the Affects line from firing if there aren't points to lose in GoodDiplomat.


Update: As per my #2 from last post, I'm in the middle of working out a program to sift through the file, pull out all the traits and their corresponding list of antitraits, find all the WhenToTest conditions, and generate comprehensive antitrait-like triggers for all WhenToTest times. It shouldn't be too difficult to get it wrapped up - hopefully inside of a few days. It will probably be several thousand more triggers though. I anticipate it will make the traits txt file very much bigger than it currently is, but don't anticipate a lot of extra overhead in-game, though it's hard to tell exactly how much time is currently spent trigger-checking. I know this is a source of much concern, so I'll keep everyone posted on the results, whenever I get to that point.

Sarastro
12-25-2006, 17:26
I would also point out that the code you displayed is not quite right yet: you've allowed an agent with 0 GoodDiplomat pts to still have 1 removed half the time, and then have a chance to gain a BadDiplomat point as well. This means a failed mission could cause a 2-point swing in any diplo with 1 or less GoodDiplomat points, since both triggers will go off - and he could also get a negative GoodDiplomat stat, which is something undefined in game terms as far as I know. The fix is to make the triggers mutually exclusive by testing the first trigger as well. You check for GoodDiplomat > 0 (or >= 1 if you prefer), which then prevents GoodDiplomat from becoming negative ever, and keeps the Affects line from firing if there aren't points to lose in GoodDiplomat.

Yep, the failed / successful mission which should switch the trait from Good- 1 or Bad- 1 to neutral will instead immediately go to the opposite trait. I actually tried the way you suggested above, and several similar triggers which were meant to be safeguards to ensure that the standard mission failed / suceeded script didn't fall foul of the anti-trait bug, and the character correctly returned to neutral. For some reason, however, it didn't work, and the agent didn't start picking up points again on the next successful / failed mission. Since I was a little pressed for time, I simply went for the hotfix of skipping the neutral level, which doesn't make a huge difference to the game imo. Also, it is stable and works, which is a big plus :2thumbsup:

You are right about the -1 thing though, I'll stick in

Condition not Trait BadDiplomat >= 1

to be safe, but I think that is in effect what it assumes anyway, as I haven't seen anything that would indicate a buildup of negative GoodDiplomat trait points which would have to be worked off to gain GoodDiplomat 1 from the next successful mission. In fact, I'm not sure the game even recognises a trait with negative points, they only seem to work when the trait has points above zero.

Always looking for improvements though, so if you have a working code to get the neutral level working, I'd like to know the solution!

Kobal2fr
12-25-2006, 23:54
I just thought of something, and I really, really need to find my old Rome CD's so I can check how things were when they worked : couldn't traits and antitraits coexist in a character ?
I know only the superior one was displayed, minus any levels in the antitrait but -

Say you had a Stoic 4 general (can't remember wether this has a NoGoingBackLevel, and I'm stranded with a 52k connection so let's assume not for the sake of the example). He stops in town, picks up the dreaded Drink. Then moves out. Now, does the general has Stoic 3 or (like I'm fearing right now) Stoic 4 Drink 1 ? Because if it's the latter, then Drink's of course self-updating, so overtime the general would become Stoic 4 Drink 5 = Drink 1.
With the duplicate triggers, that won't be possible because both traits will never appear together, and the self-updating bad traits will never make a good one slowly drop down... Not that it's a huge problem of course, but it would be one more thing lost in an easy-for-CA-to-fix hardcode issue...

@pellik : forgot you last time, I'm sorry.
No, I don't have diff files, I'm afraid I'm not what you'd call a disciplined coder. The readme file is pretty much all I've got to remind myself of what I changed as I plowed through the file without a plan. When I saw a bug, I cross checked then made a change if necessary, then wrote it in the readme - no method, no order, no hierarchy, no nothing. I tried to be as verbose as possible, and to always give the trigger names so that the changes can be found and reverted easily, but... well, you've seen the result :}
I'll try to make .diff files from now on though.

Foz
12-26-2006, 17:25
Yep, the failed / successful mission which should switch the trait from Good- 1 or Bad- 1 to neutral will instead immediately go to the opposite trait. I actually tried the way you suggested above, and several similar triggers which were meant to be safeguards to ensure that the standard mission failed / suceeded script didn't fall foul of the anti-trait bug, and the character correctly returned to neutral. For some reason, however, it didn't work, and the agent didn't start picking up points again on the next successful / failed mission. Since I was a little pressed for time, I simply went for the hotfix of skipping the neutral level, which doesn't make a huge difference to the game imo. Also, it is stable and works, which is a big plus :2thumbsup:
You know it's funny you mention that. I fixed the agent success/failure triggers in the manner I described, and it seemed a little quirky, but I couldn't place exactly how. I haven't even been playing with the new code long enough to say if I have the problem you described for sure... but I aim to find out. If so, then maybe it's an odd quirk of the antitrait code that doesn't allow things to get back to neutral again correctly. Since the agent fix should already bypass it, I recommend removing the Antitrait lines from the Trait defs for all the Good/Bad agent traits, and seeing if it solves the problem.

You are right about the -1 thing though, I'll stick in

Condition not Trait BadDiplomat >= 1

to be safe, but I think that is in effect what it assumes anyway, as I haven't seen anything that would indicate a buildup of negative GoodDiplomat trait points which would have to be worked off to gain GoodDiplomat 1 from the next successful mission. In fact, I'm not sure the game even recognises a trait with negative points, they only seem to work when the trait has points above zero.
Can anyone verify/deny this for me? If the game zeros negative traits or otherwise ignores a -1 to an already 0 trait, it would save me a TON of triggers for all the cases where a trait has multiple antitraits. I could just -1 all the antitraits without worrying about making any negative...

@Kobal: I hope you're wrong about the traits actually coexisting, because there's absolutely no way we can accomplish that from modding the trait file. Well we could make them coexist by ONLY removing the antitrait lines from the file... but it'll make your character actually get both traits, lol. They typically have opposite effects so this might actually make the characters get reasonably correct stats since the good and bad would cancel... but it would make reading a character sheet nearly impossible, and certainly it would be way too hard to figure out what net effects your governor is actually going to have on a settlement. Not to mention just how weird it would be to see people around with completely opposite traits at the same time...

Sarastro
12-26-2006, 23:32
Can anyone verify/deny this for me? If the game zeros negative traits or otherwise ignores a -1 to an already 0 trait, it would save me a TON of triggers for all the cases where a trait has multiple antitraits. I could just -1 all the antitraits without worrying about making any negative...

You should be able to test that from MedShell with give_trait?

Just select a diplomat, give_trait this GoodDiplomat 0, give_trait this BadDiplomat 0. Then give_trait this GoodDiplomat -3, then give_trait this GoodDiplomat 1, and see what happens. If he gets GoodDiplomat level 1, then it doesn't seem to take negative levels into account, if it takes GoodDiplomat 4 to get him to positive levels, then it does.

Would do it myself, but don't have an installed copy here atm.

Kobal2fr
12-27-2006, 02:27
Won't quite work that way - give_trait gives the absolute value input for the trait. You can type "give_trait this GoodDiplomat 1" for a week, your diplo will still have GoodDiplo 1 :)

What he can do is make up a test trigger along the lines of "WhenToTest EndOfTurn Condition AgentType = Diplomat Affects GoodDiplomat 1 100". Then fire the game, make a brand new diplo, give_trait him GoodDiplo -3 and NaturalDiplomat 0, and then hit end turn four times. If he's got Influence 1, then negative values are accounted for. If he's got 2+, then negatives equal zero.

Foz
12-27-2006, 04:44
Thanks for the help Sarastro and Kobal. I have ended up doing something very similar to what Kobal said: I setup one of the spyinit triggers to give -32 to GoodSpy with 100% chance, then on the next line gave 32 to GoodSpy with 100% chance. Fired up the game, loaded a save, queued a ton of spies, and they all came out Master Spy (that's the +5 tier of GoodSpy) instead of the neutral you'd expect if negatives counted. So yeah, the negatives don't do a thing past 0, which is really handy for me.

Update: I got my code for generating the extra triggers up and running tonight. It churned out some 17,000 new triggers, and that was just with 1 copy of each trait/antitrait pairing. I think that may be enough, as there are way more WhenToTest conditions than I originally thought, meaning the trigger for any given trait/antitrait pair should trigger multiple times per turn on each character anyway. You still might see a son turn of age and have oodles of drink and sobriety at the same time, but it should be balanced in a few turns as his triggers go off. Most everything else is completely seamless.

As expected, it didn't affect the game speed noticeably, even between turns, but of course your mileage may vary. I have to tweak it a little still, as I neglected to trip ALL antitraits -1 anytime that the trait and one of them are both positive. This results in trait points cancelling with only one of the antitraits... whichever happened to be listed first in the file. Obviously we can't have that! I also have yet to thoroughly test it to make sure it's really doing what I think it is. If that goes well, then I'll see about releasing it here.

@Kobal2fr: Are you okay with me using your modded file as a basis for further changes? I did so because it has already incorporated the easy bug fixes, but I can go back and make the fixes myself if it will bother you. Also, supposing that you like what I come up with, what would you think of incorporating the fix into your mod? I don't feel the need to have my own mod on account of one fix, and seeing that you already have a bug-blasting mod going, it seems like a good place for my work to be.

pellik
12-27-2006, 04:58
@foz: I already have a script that can do what you are trying to do. Its not well written but its more or less human understandable. If you want it let me know.

Speaking of which, I turned my script to generate the traits file already. Sorry Foz that I didn't get on here sooner to save you some work.


I will be able to test my script tomorrow evening. But until then I have an modified character traits file for anyone who wants to give it a try.

export_descr_character_traits.txt (http://nbtsc.org/~pellik/export_descr_character_traits.txt)

My solution was to generate a series of eight triggers for each trait/antitrait pair. Each trigger checks to see if both the trait and the antitrait are > 0, and then adds -1 to each. So if you have Trait 4 and gain AntiTrait 1, the first trigger will set Trait 3 AntiTrait 0. There are eight of them incase you gain many points of an antitrait. They fire on turn end right now, so weird things may happen in character generation that wont get fixed until the next turn. I'll play with it more later to fix that, however.

Please let me know where the bugs are. I havn't test this at all yet and am unsure if it will even load.

Enjoy.

pellik
12-27-2006, 05:13
T
Update: I got my code for generating the extra triggers up and running tonight. It churned out some 17,000 new triggers, and that was just with 1 copy of each trait/antitrait pairing. I think that may be enough, as there are way more WhenToTest conditions than I originally thought, meaning the trigger for any given trait/antitrait pair should trigger multiple times per turn on each character anyway. You still might see a son turn of age and have oodles of drink and sobriety at the same time, but it should be balanced in a few turns as his triggers go off. Most everything else is completely seamless.


You posted this while I was in the process of posting mine. Crazy.
I should have held mine back for testing, but that will take a few days and I wanted feedback now!~. I added a lot fewer triggers for the same effect :laugh4:.

Foz
12-27-2006, 08:26
Not a problem Pellik, I've enjoyed doing it. Plus, you've brought out my competitive nature and gotten me to release mine too! But first...
I added a lot fewer triggers for the same effect :laugh4:....The same not-quite-right effect, lol! The way I understand it, a trait point should cancel 1 from all of its antitraits, where we implemented it such that each time any antitrait gets cancelled, it eats a point of trait.

Luckily, the fix is easy (at least was for me, how I was mining the file). You just have to trip a -1 for all antitraits any time you find that the trait and any of its antitraits is > 0. As mentioned previously the -1 can't take it below 0, so this ensures that if there are pts to be lost, they all are losing them. So a trait with 4 antitraits still gets its 4 different triggers, it's just that each one will slap a -1 on the trait and all its antitraits. If you wanna see it in action, I think the last one in my modded file had 4 or 5 antitraits.

Speaking of which, I got all my tweaking done on mine, and ran it (yes, it runs for me). It seems to do exactly what I thought it would. It's also generated with CA-copied formatting, so it's readable (though the 17k triggers kinda aren't). I did notice that sometimes erroneus Trait Increased messages trip for agents now, presumably when you gain 1 antitrait point temporarily (which pulls the stat -1), just before the new trigger fixes it back to 0, bumping the stat up again (by removing the minus to it).

More good news: I can mold my generated triggers to a great degree, so let's get some discussion going! Do people prefer Pellik's implementation where massive balancing is done at the end of the turn while using less added triggers, or is it preferable to do it all through the turn which would keep the character sheet more up-to-date typically? What's important, what isn't, and how should it be? If we get some sort of concensus, I'll just generate it to specifications :beam:

And oh yeah, can't forget the best part:

export_descr_character_traits.txt (http://www.goldeneaglecomics.com/Files/export_descr_character_traits.txt)

Sarastro
12-28-2006, 01:30
Just before we get too carried away here. There is a litmus test trait about the -1 thing: Fertility

Fertility only works in + and - numbers

WifeIsFertile / WifeIsBarren (when working) each test Fertility of a Princess. If she has + Fertility, then she gets the fertile trait, if she has - Fertility she gets Barren.

I've seen WifeIsBarren appearing in my fixed traits file...that suggests that at least some - traits exist. It might be a good idea to work out a) if this is true, b) which traits it applies to, before starting a system which relies on negative numbers not existing.

Traits file is below, it's between 1.0 and 1.1 on my VnV Fixes mod, but it's pretty much all updated to 1.1 apart from some checking. Has all of Kobals fixes as well as many more (unless you've updated yours sir!).

http://www.savefile.com/files/370033

Foz
12-28-2006, 03:34
Apples and oranges, Sarastro. Fertility is not a Trait at all, but rather an Attribute. The following code illustrates this:

;------------------------------------------
Trigger family_generalmarries_barren_1
WhenToTest CharacterMarriesPrincess

Condition SpouseAttribute Fertility < 0

Affects WifeIsBarren 1 Chance 100

Attributes appear with the word "Attribute" preceding them in the Condition line, where a trait appears with "Trait" in front of it always. Similarly, Traits are changed with Affects, while Attributes get Effects used on them. I assume this is a tag for the parser, to indicate what kind of variable it is that we're talking about... which coincidentally would only be needed if the different types actually behaved differently.

To elaborate: When you notice your characters having WifeIsBarren, it's not that it's a - trait. It's a bad trait and impacts the character negatively, but it will have positive trait points: it's just that the trigger which generates it checks an Attribute that had a negative value. Similarly, Fertile/Infertile would never be negative since they are always given positive points (note the trigger above) no matter whether the woman's Fertility was positive, negative, or zero.

So I'm gonna keep rolling along with the "Traits can't be negative" thing since I've seen evidence of it from several traits, and none to the contrary. If anyone finds any that don't behave like that though, let me know of course. Until then, use my file! :yes:

Also since I just noticed it... no wonder I've never seen a man with WifeIsFertile: it's set only to apply to "admirals," where WifeIsBarren correctly affects "family." I guess only sailors could procreate like rabits back in those days. :wall:

Sarastro
12-28-2006, 12:09
...and that's why I don't have good ideas at 1:30 in the morning.:laugh4:

Any chance you could release the anti-trait generating program?

Foz
12-29-2006, 06:20
Hmm... I will consider doing so. It's a real mess right now though from a usability standpoint for anyone that didn't write it. All C++ code, no UI... so everything is in the hardcode, which you'd have to modify, compile and run, since I'm not dressing up a script intended for a single purpose with a happy interface and lots of fun features and settings. If you're into that, you're welcome to have the cpp file.

If you're not into that, which I'm guessing is most people, then there are other possibilities. I can refine it a little and post the resulting exe, which would then do the following:

1. Read in a traits file.
2. Find all the traits in the file, with their associated antitraits.
3. Generate a new traits file, with antitrait lines stripped out and new antitrait-simulating triggers appended.

This would allow you to generate triggers for any modded traits file, which I'm sure is neat for you modders out there, since removing or adding a single trait or antitrait would otherwise mean you'd have to hunt down all the associated triggers that had been generated and modify them appropriately by hand. Since I wrote a program to do it rather than attempt it by hand, you should be able to guess about how much fun that would be.

The other possibility is similar, but with some inputs. Like, I could have it give simple options like generating for all test times, only for start and end turn, only end turn... and then allow you to choose the number of copies per trigger.

So what it boils down to is, what do you (and anyone else that will use it) want it to do, and how?

Sarastro
12-29-2006, 11:26
My main feature would simply be a working generator which created all the extra triggers neccessary to fake the trait/anti-trait scale working correctly.

When the adjustments are done doesn't concern me too much, I'm quite happy with start turn, end turn, and on battle or mission resolution.

Inputs are always good though, my top options would be:

Ability to generate for a single set of trait/anti-trait triggers (ie GoodPrincess/BadPrincess), specified by trait name.

Automatic .bak creation on an operation (probably easiest and most secure way to work with a lot of operations & numerous triggers).

HOWEVER, it is probably worth waiting until the 1.2 patch until taking your time to make such a thing, as there's always a (slim) chance that if the mod community make enough noise, CA might fix what should be a pretty basic and important hardcode error.

Kobal2fr
12-29-2006, 20:07
Hey lads, sorry for the lack of reply, my comp did its meltdown trick... again, and I had to go out and buy stuff... Still need some more till it works perfectly again I'm afraid, in the meantime it's unstable as a schyzophrenic, and I'm a liiittle bit afraid of what the MB might do to my filesystems until I'm confident it's patched up, so no medieval for me for at least another few more days... Merry christmas ! :)

the_foz : sure sure, use'em all you want. Saves me the hassle of doing this for myself :)

alpaca
12-29-2006, 20:42
Hmm... I will consider doing so. It's a real mess right now though from a usability standpoint for anyone that didn't write it. All C++ code, no UI... so everything is in the hardcode, which you'd have to modify, compile and run, since I'm not dressing up a script intended for a single purpose with a happy interface and lots of fun features and settings. If you're into that, you're welcome to have the cpp file.

If you're not into that, which I'm guessing is most people, then there are other possibilities. I can refine it a little and post the resulting exe, which would then do the following:

1. Read in a traits file.
2. Find all the traits in the file, with their associated antitraits.
3. Generate a new traits file, with antitrait lines stripped out and new antitrait-simulating triggers appended.

This would allow you to generate triggers for any modded traits file, which I'm sure is neat for you modders out there, since removing or adding a single trait or antitrait would otherwise mean you'd have to hunt down all the associated triggers that had been generated and modify them appropriately by hand. Since I wrote a program to do it rather than attempt it by hand, you should be able to guess about how much fun that would be.

The other possibility is similar, but with some inputs. Like, I could have it give simple options like generating for all test times, only for start and end turn, only end turn... and then allow you to choose the number of copies per trigger.

So what it boils down to is, what do you (and anyone else that will use it) want it to do, and how?

Well that's a fairly good idea if it works properly ;)
How does it work actually, do you read in the triggers for the respective traits as objects and edit them?

By the way, I'*d propose using python for small scripts, it's very useful and you don't have to re-compile it (since it's run through an interpreter) every time :)
It's also easily usable in C programs so can be actually given a UI to go with it later if you feel like it (which you probably won't but who knows)

Foz
12-31-2006, 02:15
Actually, I don't do a thing with the existing triggers except copy them verbatim to the output file, and copy all the WhenToTest conditions from them to a list to reference later. The real work all comes from the Trait definitions in the top part of the file.

Basically, I pull out the name of the trait and each of its antitraits from each trait definition in the file. I know how to find them because they're preceded by "Trait" and "Antitrait." While doing that, I echo the trait defs to the output file, but without any antitraits. Then after that's done, I pull all the WhenToTest stuff from the triggers while copying them to the file.

The new triggers are generated in the following manner:

-for each WhenToTest condition
--for each trait
---for each antitrait of that trait
----output the trigger for this trait/antitrait pair

The triggers are basically identical, so all the code has to do is stick in the correct trait and antitrait names in the correct places, and the trigger pops out. Oh yeah, I also run a counter to name each trigger incrementally.

So overall, it wasn't bad to get done... and I might be able to fit in a no going back level fix sometime too. I'll have to think on it and see if I can work it out somehow. It's not as simple as it initially seems.

Afro Thunder
01-02-2007, 18:23
What I find interesting is that this bug was also present in BI. It was fixed in the Bug Fixer Mod, made by Player1 I believe. I'm not meaning to bash CA or anything, but I just find it curious how this same bug is still present in Medieval II, long after a third-party mod fixed it in BI.

Foz
01-03-2007, 01:58
What I find interesting is that this bug was also present in BI. It was fixed in the Bug Fixer Mod, made by Player1 I believe. I'm not meaning to bash CA or anything, but I just find it curious how this same bug is still present in Medieval II, long after a third-party mod fixed it in BI.
Wow that's LAME. Maybe I can get them to send me 20 bucks and give me access to whatever file has the antitrait hardcode in it so I can actually fix it for them. I'm certain if I could do that, it would be no more than a few lines of code...

Afro Thunder
01-03-2007, 05:38
Actually, I remember the details of the work-around that Player1 used in his BugFixer mod. It all has to do with NoGoingBackLevel. Let's take the GoodCommander line of traits, for example. This group has 5 different levels, going from Promising Commander to Legendary Commander. What Player1 did was simply add an artificial "NoGoingBackLevel 6". This solved the disappearing traits problem in BI, though I'm not sure if it will still hold true for M2.

Kobal2fr
01-05-2007, 21:01
I'll try that, see how it works out (though Sinan said the NoGoingBack were borked). Thanks for the explanation ! If that doesn't work, that'll lead us to...

the_foz : so, does your modified file work properly ? :sweatdrop: :laugh4:

Foz
01-06-2007, 02:10
I've been using it for a while now, and yes it seems to work exactly as it is intended to. The traits shift up and down as appropriate, instead of the horrid destruction of traits that occurred before. This is easy to notice when a smacked-down diplomat or princess loses only 1 point of skill, and it warms my heart each time it happens :beam:

As previously noted, it also doesn't slow my system down noticeably, so I'm calling it a big ole success. I gather from the lack of feedback, though, that no one else has tried it at all, lol. If anyone decides to, it'd be nice to have some confirmation that it is working correctly, and maybe some feedback on how it affects performance, as other people may be affected differently than I've been.

alpaca
01-06-2007, 17:08
Well, rest assured most larger conversion mods will use a similar system for their traits ;)

BozosLiveHere
01-06-2007, 21:14
There's no way I'll even consider start converting EB to M2TW if they don't fix this.

We already use the 'NoGoingBackLevel being higher than the last trait level' trick, but there are lots of traits where we can't have it. Gah!:wall:

seneschal.the
01-07-2007, 19:28
I'm convinced that the only way to fix the entire mess of the VnV system is for CA to have a few guys go through the actual code itself, fixing all the quirks and bugs and errors. After that, they should re-write everything. I'm serious, looking through the vanilla VnV files reminds me of typical internal company code for ancient programs where hotfix after hotfix is applied to something broken to make it seem like it is working properly. Then the hotfixes get bugged and need more fixes...

Seeing that CA decided that there is no need to fix the VnV system (no change between 1.0 and 1.1, DESPITE many people commenting and mailing to CA pointing out e.g the ReligionStarter bug...) I wouldn't get my hopes up for any future fixes.

alpaca
01-07-2007, 23:18
Bozos: You can just add negative trait points (i.e. subtract them) if you redo the whole traits system anyways.

On topic: It actually appears that the NoGoingBackLevel is bugged. If you subtract points, the trait stays there, but the actual internal trait points are lowered. That means you have to artificially take care with triggers for this, too.
The trick of setting the NoGoingBackLevel higher than the actual maximum trait level still seems to fix the AntiTraits code somehow... meh, I'd rather do it all with triggers than relying on CA's bugged code.

Edit: Just noticed that if you are at the NoGoingBackLevel and add exactly 1 point to the AntiTrait it doesn't do anything. So maybe the problem lies in the interaction between NoGoingBackLevel and AntiTraits or something like that. So if instead of using Affects bla 3 you use Affects bla 1 three times, it works fine.

BozosLiveHere
01-08-2007, 16:48
Bozos: You can just add negative trait points (i.e. subtract them) if you redo the whole traits system anyways.


Yeah, but if I understood the findings of this thread correctly (I just did a superficial reading) this would force me to have lots of new triggers to compensate for the faulty antitrait mechanics. This is just not feasible for EB. My latest version of edct is 7,399,591 bytes long already.

Foz
01-09-2007, 04:37
If you're concerned with the size, then yes this could be problematic. My currently implemented trait file with the triggers to fix anti-trait functionality is 5.24 MB, compared with the ~400k original IIRC. If you're concerned with actually having the triggers, though, I can probably work out some way to automate their generation (as I have for the vanilla traits file). In fact, it's likely if you've followed CA's format for the file even loosely that I might be able to just run it through what I already have and have it churn out correct triggers. LMK what you're thinking.

BozosLiveHere
01-09-2007, 16:34
I'm definitely concerned about size. Keep in mind that unlike vanilla, we have lots of traits that have the maximum (for RTW) of 10 antitraits: this would mean an even bigger bloat.

alpaca
01-09-2007, 16:48
Well maybe we'll get it fixed in the next patch. Although I don't have too much hope in that unless we can niggle the guys at CA to have a look at it lol

Sarastro
01-11-2007, 22:09
Seems fairly obvious to me that after vanilla RTW, they just stopped caring and about the rp / traits side. Clearly the guy who did traits for M2 didn't have the faintest idea what he was doing, there are some basic and endemic mistakes that I worked out after looking at the file for just an hour or so, but he managed to miss.

Foz, I intend to try out your app as soon as I have my fix mod finished (over the weekend). Two questions though:

How does it handle trait/anti traits which are affected by many triggers? From what I gather, it shouldn't be a problem as it fixes the problem at the trait level, rather than hotfixing triggers?

Two, any idea what the effect would be on triggers which already compensate for anti-traits not working? ie the code that is currently in my mod for agents? This is the main reason I haven't tried it out yet, I'm fairly sure it will bork that, and I'll have to spend a while going back through the files and replacing the original.

Considering the massive complexity of fixing chivalry / dread traits by hotfixing triggers by hand, however, your app looks like the best bet.

Foz
01-12-2007, 23:30
1. Well, it uses triggers to accomplish the fix, but not by modifying any of the existing ones in the file: they are generated based solely on the trait defs in the upper portion of the file. Existing triggers are copied to the new file verbatim, and existing trait defs copied only with their antitrait lines removed.

2. Triggers that already hotfix anti-trait functionality should in no way be borked by this fix. My new triggers only fire if a trait and anti-trait both have positive points at the same time (which is now allowed due to the removal of antitrait tags in the file). As the hotfixed triggers I've been seeing usually utilize the ability to give a trait negative points, they should not ever be able to cause a situation that would even make my fix triggers fire off... and if they did, you'd want the fix triggers to go off to correctly balance the traits that are tugging at each other.

As an additional note, I didn't post the file patcher yet (unless I was drunk and just can't remember doing it). Truth be told, I cobbled it together rather hastily, and have been chopping the input file apart by hand into neat input files with only particular pieces of the original in them, as I was too lazy at the time to write code to figure out where trait defs ended and triggers began, while also ignoring the random stuff in between.

If you like, you can link to your finished file when it's ready, and I'll see if I can get it processed for you and sent back so you can check it out. Outside of that, I'll have to work those things I mentioned into the code, which I'm neither really motivated to do at the moment nor having the time to accomplish due to 1. the shield bug, as well as 2. my desire to actually play the game I spend so much time troubleshooting.

Sarastro
01-13-2007, 15:08
My new triggers only fire if a trait and anti-trait both have positive points at the same time (which is now allowed due to the removal of antitrait tags in the file).

Aaaahhhh, I suddenly understand how it works now. Excellent :beam:


If you like, you can link to your finished file when it's ready, and I'll see if I can get it processed for you and sent back so you can check it out.

That would be wonderful. If it works, would you mind me including it in the final version of the VnV Fixes mod? Only thing I haven't managed to fix is the anti-trait code for dread & chivalry, and some of the more obscure anti-traits, as it would take so long to do the triggers by hand. Fixing those would, I think, produce a 99.9% clean traits file without other alterations which everyone could start using as a base for their mods. Huge recognition to you for the solution would, of course, be given.


my desire to actually play the game I spend so much time troubleshooting.

I know the feeling :whip:

alpaca
01-13-2007, 16:27
To be honest, the traits system is screwed even if you fix it. It has no themes, no charm, no nothing. It feels like a glue-on and doesn't add much to immersion.
I think a new system built up from scratch is needed, but that will probably be left to total conversion mods.

Nonetheless, you've made some quite nice work on this ;)

Sarastro
01-13-2007, 23:19
To be honest, the traits system is screwed even if you fix it. It has no themes, no charm, no nothing. It feels like a glue-on and doesn't add much to immersion.
I think a new system built up from scratch is needed, but that will probably be left to total conversion mods.

I know - the VnV's fix is only intended to be a base. After I finish that (ie now), I'm planning a longer-term total rework mod, revamping the traits system, combining it with a popular titles mod, and adding some new features which should really make traits both powerful and immersive - give characters a real sense of, well, character.

We will be announcing it on TWCenter sometime next week.

That reminds me Alpaca - since the above obviously requires messing with some files other than the traits / ancillary files (ie for rebellion), files which may be used by other mods, I know one of your mods had an .exe program to add lines to an existing file instead of re-writing it. How difficult is that to do? Assume I have 0 actual programming knowledge and just reverse-engineer things that are already there when modding.

alpaca
01-14-2007, 15:34
I know - the VnV's fix is only intended to be a base. After I finish that (ie now), I'm planning a longer-term total rework mod, revamping the traits system, combining it with a popular titles mod, and adding some new features which should really make traits both powerful and immersive - give characters a real sense of, well, character.

We will be announcing it on TWCenter sometime next week.

That reminds me Alpaca - since the above obviously requires messing with some files other than the traits / ancillary files (ie for rebellion), files which may be used by other mods, I know one of your mods had an .exe program to add lines to an existing file instead of re-writing it. How difficult is that to do? Assume I have 0 actual programming knowledge and just reverse-engineer things that are already there when modding.
It's not too difficult really. Spurius used a batch file to copy two files into one. Check out the file that the mod folder installer leaves in your MTW2 dir to see how it's done.
You could also use other methods, but this one is probably the easiest.

Foz
01-14-2007, 19:05
Aaaahhhh, I suddenly understand how it works now. Excellent :beam:

That would be wonderful. If it works, would you mind me including it in the final version of the VnV Fixes mod? Only thing I haven't managed to fix is the anti-trait code for dread & chivalry, and some of the more obscure anti-traits, as it would take so long to do the triggers by hand. Fixing those would, I think, produce a 99.9% clean traits file without other alterations which everyone could start using as a base for their mods. Huge recognition to you for the solution would, of course, be given.

I know the feeling :whip:

Glad it makes sense :smile:

Provided it works, which I expect it will (it has been for me for weeks now), you are certainly welcome to use it in your mod. Truth be told I actually sorta prefer this particular fix to be packed along with others, as it's not the sort of thing there's a huge public outcry for (probably because it's not as readily noticed as some other bugs), but still one that makes the VnV system work very differently in practice. I am of course never one to balk at credit, either! :smile:

Fair warning though, expect it to bloat the file size by a large amount. My fixed version of Kobal2fr's Cherry Vanilla traits file went from ~500k to ~5MB.

JeromeGrasdyke
01-15-2007, 14:16
I've passed this one on for investigation to the Oz guys since - if proven true - it would be a serious issue which breaks quite a few progression mechanisms on the campaign map. Good spot...

alpaca
01-15-2007, 19:08
I've passed this one on for investigation to the Oz guys since - if proven true - it would be a serious issue which breaks quite a few progression mechanisms on the campaign map. Good spot...
Hey Jerome, nice to see you.
If they're at it, tell them to fix the NoGoingBackLevel, too. I think it only works if the trait goes exactly one point below the NoGoingBackLevel. Otherwise, it will keep the trait but the points go down nonetheless (i.e. if you increase it again, it'll take longer).

Sarastro
01-15-2007, 19:29
I've passed this one on for investigation to the Oz guys since - if proven true - it would be a serious issue which breaks quite a few progression mechanisms on the campaign map. Good spot...

Huzzah...the official caveat does make me laugh though, give your QA testers a smack for not noticing it on turn one.

Thank you sir!

pellik
02-02-2007, 20:24
Heh, I was quite drunk all through the holiday and, upon sobering up, completely forgot I had been messing with antitraits. Sorry for the prolonged absence.

I'm not much of a programmer, but I threw togeather a script for this that inports the traits file, breaks it down, and sews it back togeather again. What I didn't do was adequately comment my code, or do things in the most logical or effecient mannor. If you want to make use of this you'll just have to figure out things like $BoB[$i][$j][3] always refers to a GainMessage line. Its not too complicated asside from that kind of weirdness.


#!/usr/bin/perl

open (INFILE, "export_descr_character_traits.txt") || die "Cannot open traits fie.\n"; # Using fixed filenames.
open (OUTFILE, "> export_descr_character_traits.txt.new") || die "Cannot open output file.\n"; #
@INFILE = <INFILE>; #
#
foreach $line (@INFILE) { # Read infile to an AoA. 1/
if ( $line =~ /-{5,}/) { #
$i++; #
$j = 0; #
} else { #
$line =~ s/^\s+//; # Removes leading whitespace.
chomp $line; # Removes newline symbols.
$line =~ s/\r$//; # Removes carriage returns.
$AoA[$i][$j] = $line; #
$j++ #
} #
} # /1

$a = -1; # Bad fix for a hard counter.
for $i ( 0 .. $#AoA ) { # Sorts AoA into BoB by label. 2/
$k = 0; #
for $j ( 0 .. $#{$AoA[$i]} ) {
$l = 1; # Counter for line in level.
$line = $AoA[$i][$j];
if ($line =~ m/^Trait/) {
$line =~ s/Trait\ //;
$BoB[$i][0] = $line;
}
if ($line =~ m/Characters /i) {
$line =~ s/Characters\ //;
$BoB[$i][1] = $line;
}
if ($line =~ m/^ExcludeCultures/) {
$line =~ s/ExcludeCultures\ //;
$BoB[$i][2] = $line;
}
if ($line =~ m/^NoGoingBackLevel/) {
$line =~ s/NoGoingBackLevel\ //;
$BoB[$i][3] = $line;
}
if ($line =~ m/^AntiTraits/) {
$line =~ s/AntiTraits\ //;
$BoB[$i][4] = $line;
}
if ($line =~ m/^Level/) {
$line =~ s/Level\ //;
$k++;
$BoB[$i][$k + 5][0] = $line; # Begin additional loop for
$line = $AoA[$i][$j+$l]; # repeating Level tags within
while ($line !~ m/^Level/ && ($j + $l) <= $#{$AoA[$i]}) { # each Trait block.
if ($line =~ m/^Description/) {
$line =~ s/^Description\ //;
$BoB[$i][$k + 5][1] = $line;
}
if ($line =~ m/^EffectsDescription/) {
$line =~ s/^EffectsDescription\ //;
$BoB[$i][$k + 5][2] = $line;
}
if ($line =~ m/^GainMessage/) {
$line =~ s/^GainMessage\ //;
$BoB[$i][$k + 5][3] = $line;
}
if ($line =~ m/^LoseMessage/) {
$line =~ s/^LoseMessage\ //;
$BoB[$i][$k + 5][4] = $line;
}
if ($line =~ m/^Epithet/) {
$line =~ s/^Epithet\ //;
$BoB[$i][$k + 5][5] = $line;
}
if ($line =~ m/^Threshold/) {
$line =~ s/^Threshold\ //;
$BoB[$i][$k + 5][6] = $line;
}
if ($line =~ m/^Effect/) {
$line =~ s/^Effect\ //;
$line =~ s/\ \ /\ /;
@TMP = split(/\ /, $line);
$BoB[$i][$k + 5][7]{@TMP[0]} = @TMP[1]; # Multiple effects split and
} # Sorted in array @TMP.
$l++;
$line = $AoA[$i][$j + $l];
}
}
print $BoB[0][0]; # /2
if ($line =~ m/^Trigger/) { # Sorts Triggers into CoC 3/
$a++;
$line =~ s/^Trigger\ //;
$CoC[$a][0] = $line;
}
if ($line =~ m/^WhenToTest/) {
$line =~ s/^WhenToTest\ //;
$CoC[$a][1] = $line;
}
if ($line =~ m/^Condition/) {
$line =~ s/^Condition\ //;
$m = 0;
$CoC[$a][2][0] = $line;
$m++;
}
if ($line =~ m/^and/i) {
$line =~ s/^and\ //;
$CoC[$a][2][$m] = $line;
$m++;
}
if ($line =~ m/^Affects/i) {
$line =~ s/^Affects\ //;
@TMP = split (/\ \ Chance\ \ /, $line); # Multiple Affects split.
$CoC[$a][3]{@TMP[0]} = @TMP[1]; # /3
}
}
}
print $BoB[0][0]; # Output each line more or
for $i ( 0 .. $#BoB ) { # less as it came in.
print OUTFILE ';------------------------------------------' . "\n";
if ( defined ($BoB[$i][0])) {
print OUTFILE "Trait $BoB[$i][0]\n";
}
if ( defined ($BoB[$i][1])) {
print OUTFILE "\tCharacters $BoB[$i][1]\n";
}
if ( defined ($BoB[$i][2])) {
print OUTFILE "\tExcludesCultures $BoB[$i][2]\n";
}
if ( defined ($BoB[$i][3])) {
print OUTFILE "\tNoGoingBackLevel $BoB[$i][3]\n";
}
# if ( defined ($BoB[$i][4])) {
# print OUTFILE "\t;AntiTraits $BoB[$i][4]\n";
# }
for $j ( 5 .. $#{$BoB[$i]} ) {
if ( defined ($BoB[$i][$j][0])) {
print OUTFILE "\tLevel $BoB[$i][$j][0]\n";
}
if ( defined ($BoB[$i][$j][1])) {
print OUTFILE "\t\tDescription $BoB[$i][$j][1]\n";
}
if ( defined ($BoB[$i][$j][2])) {
print OUTFILE "\t\tEffectsDescription $BoB[$i][$j][2]\n";
}
if ( defined ($BoB[$i][$j][3])) {
print OUTFILE "\t\tGainMessage $BoB[$i][$j][3]\n";
}
if ( defined ($BoB[$i][$j][4])) {
print OUTFILE "\t\tLoseMessage $BoB[$i][$j][4]\n";
}
if ( defined ($BoB[$i][$j][5])) {
print OUTFILE "\t\tEpithet $BoB[$i][$j][5]\n";
}
if ( defined ($BoB[$i][$j][6])) {
print OUTFILE "\t\tThreshold $BoB[$i][$j][6]\n";
}
print OUTFILE "\n"; # Use hash for easier sorting of
while (($key,$value) = each %{$BoB[$i][$j][7]}) { # Effects in the future.
if ($value =~ /-/) {
print OUTFILE "\t\tEffect $key $value\n";
} else {
print OUTFILE "\t\tEffect $key $value\n";
}
}
print OUTFILE "\n";
# }
}
}
for $i ( 0 .. $#CoC ) {
print OUTFILE ';------------------------------------------' . "\n";
print OUTFILE "Trigger $CoC[$i][0]\n";
print OUTFILE "\tWhenToTest $CoC[$i][1]\n\n";
print OUTFILE "\tCondition $CoC[$i][2][0]\n";
$m = 1;
while ( defined ($CoC[$i][2][$m]) ) {
print OUTFILE "\t\tand $CoC[$i][2][$m]\n";
$m++;
}
print OUTFILE "\n";
while (($key,$value) = each %{$CoC[$i][3]}) {
print OUTFILE "\tAffects $key Chance $value\n";
}
print OUTFILE "\n";
}

for $u ( 0 .. $#BoB ) {
@array = split(/, /, $BoB[$u][4]);
for $a ( 0 .. $#array ) {
$BoB[$u][0] =~ s/\s//;
$array[$a] =~ s/\s//;
$line = "$BoB[$u][0]" . " " . "$array[$a]";
foreach $element (@lines) {
if ("$element" =~ "$line") {
$line = '';
}
}
$lineb = "$array[$a]" . " " . "$BoB[$u][0]";
if ("$line" =~ m/\S/) {
push (@AntiTraits, $line);
}
push (@lines, $line);
push (@lines, $lineb);
}
}

foreach (@AntiTraits) {
@TMP = split;
for ($i = 0; $i < 9; $i++) {
print OUTFILE ';------------------------------------------' . "\n";
print OUTFILE "Trigger ANTITRAIT_$TMP[0]_Trigger$i\n";
print OUTFILE "\tWhenToTest CharacterTurnEnd\n\n";
print OUTFILE "\tCondition Trait @TMP[0] > 0\n";
print OUTFILE "\t\tand Trait @TMP[1] > 0\n\n";
print OUTFILE "\tAffects @TMP[0] -1 Chance 100\n";
print OUTFILE "\tAffects @TMP[1] -1 Chance 100\n\n";
}
}

KnightErrant
02-02-2007, 21:47
Whew, I'm afraid my Perl is really rusty so I'll be lazy and
just ask. Is this code saving up all the AntiTraits and then
hot fixing the Triggers to test if a character possesses a non-zero
"Good Trait" then don't give him the AntiTrait but rather just
subtract 1 from his good trait? Also, does the commented out
code for $BoB$[$i][4] in the output section mean that Traits
no longer have an AntiTrait line in them?

pellik
02-03-2007, 06:21
Whew, I'm afraid my Perl is really rusty so I'll be lazy and
just ask. Is this code saving up all the AntiTraits and then
hot fixing the Triggers to test if a character possesses a non-zero
"Good Trait" then don't give him the AntiTrait but rather just
subtract 1 from his good trait? Also, does the commented out
code for $BoB$[$i][4] in the output section mean that Traits
no longer have an AntiTrait line in them?

Yeah. You read it right. It breaks everything apart and stores it in specific places before piecing back 90% of it all untouched because it is cannabalized from another script I was playing with for some analysis ideas I have that are yet unfinished for motivation reasons. The chunk to print the AntiTraits is commented out to omit AntiTraits from the output. The fix is such that every turn end the game checks to see if a both the trait and the antitrait exist, then gives each a -1 until one of them no longer exists. So if you gain one point in AntiTrait the net result is -1 to Trait.

There are two bugs I havn't gotten around to fixing yet. One is that the windows newline tag I stripped isn't put back in with this code. Its an easy enough fix, I just havn't bothered. The newlines are put in, but not the windows one. The other bug is that if you gain a point in Trait not all of the AntiTraits are deincremented, only the first. I think this makes sense as gaining one point of Trait shouldn't remove 5 points of AntiTraits.

Foz
02-03-2007, 17:13
The other bug is that if you gain a point in Trait not all of the AntiTraits are deincremented, only the first. I think this makes sense as gaining one point of Trait shouldn't remove 5 points of AntiTraits.
Actually that doesn't make a lot of sense. If being morally upright makes you less likely to drink, womanize, curse, etc, then it should in fact have a negative impact on any and all of those antitraits that have points in them. At least that's how it is IRL - if I suddenly develop a sense of ethics and morality, it impacts everything in my life that doesn't agree with my new methodology, not just one select aspect of it.

Also I wanted to point out that the file I linked to on page 1 I think does almost this exact same thing - I stored up all the info, stripped the antitrait stuff out, and then generated a bunch of new triggers that do the antitrait functionality. I have it working so it checks every time an event happens though, and so it cancels 1 point from all the antitraits for each trait point. Never packed it up for people on here to use though (the file I linked is Kobal2fr's CherryVanilla VnV fixer w/ my antitrait fix added) which I guess I ought to get around to doing, lol.

Foz
02-03-2007, 19:07
After my momentary lapse of inspiration, I'm back to being myself. Not without something to show for it though: that file patcher I promised everybody last month sometime. It strips the antitrait lines from the file, and instead uses triggers that fire on any game event to remove points from a trait and all its antitraits (like the antitrait was supposed to function). Here's the patcher:

Foz's AntiTrait Fix v1.0 (http://www.goldeneaglecomics.com/Files/AntiTrait.exe)

You can also use Kobal2fr's CherryVanilla VnV file, that I already patched (with his permission) here (http://www.goldeneaglecomics.com/Files/export_descr_character_traits.txt)

For the exe that processes any given traits file, you'll need to put it in the folder that has your export_descr_character_traits.txt file, and run it. It creates newEDCT.txt that you can rename to export_descr_character_traits.txt after backing up your old one (I typically just change the old extension to .bak).

Notes:

If using the exe file, the EDCT file you intend to apply it to must be correctly formatted. The important bits are:

- The traits must come before the triggers (not sure it works any other way anyway).
- Antitraits lines must be indented the same amount CA uses (4 spaces). This is because I was lazy and checked the line for the word "Antitraits" only in the 5th through 14th character spots on each line. Most people have never touched these at all (triggers get modded usually, not traits). If any are not right, though, they get copied to the new file instead of omitted, which I imagine will prevent my fix from working for that trait. If you're worried about this, you can search the finished file for "antitraits" - you should come up with nothing at all.

Outside of those few things, it should process anything that will parse correctly on game startup. I'll probably change the bit about the indentation to be more robust soon... but for now that's how it is.

pellik
02-03-2007, 20:31
If I spent a lot of time drinking, gambling, womanizing, &c., I'm not sure a small amount of religious/ethical motivation would change all of my behavior. Most people who enguage in a variety of negative trait behavior focus on reforming one thing at a time such as a new years resolution. I don't think the road from sinner to saint is so easily walked.

Anyway, I'm not posting this program as a way to fix the trait file. Thats already done. But a program to parse and reassemble the entire trait file may prove useful to someone. Hence why I'm posting the source and not an executable.

Foz
02-04-2007, 02:31
Anyway, I'm not posting this program as a way to fix the trait file. Thats already done. But a program to parse and reassemble the entire trait file may prove useful to someone. Hence why I'm posting the source and not an executable.
Agreed, it probably will be useful to someone, good idea :smile:

dzzirt
02-06-2007, 12:27
You can also use Kobal2fr's CherryVanilla VnV file, that I already patched (with his permission) here (http://www.goldeneaglecomics.com/Files/export_descr_character_traits.txt)


Umm. can i know a bit more about installation. Im a bit newbie in m2tw editing. So iva installed m2tw and want to get bot vanilla's and yours fixes - what should i do?

A link to the guide (if it is alrdy present) will be appreciated.

Foz
02-06-2007, 19:19
Umm. can i know a bit more about installation. Im a bit newbie in m2tw editing. So iva installed m2tw and want to get bot vanilla's and yours fixes - what should i do?

A link to the guide (if it is alrdy present) will be appreciated.
https://forums.totalwar.org/vb/showthread.php?t=76289&highlight=unpacker

That'll get you setup with unpacked files and able to run a modified version of the game.

Once you have that all done, all that remains is to take the export_descr_character_traits.txt file that I linked to, and put it in the data directory (overwrite the one that is there - it will be from what you unpacked). You put it in the data directory of your M2TW folder if you went with io.file_first, or in the data folder of your mod folder if you set it up like that. Then you run the shortcut the guide had you create, and the game will use the modified file.

Afro Thunder
04-03-2007, 23:50
Hope I'm not resurrecting an ancient topic, but does anyone know if the 1.2 update will fix the anti-trait problem?

alpaca
04-03-2007, 23:55
Well there's nothing specific there yet. Maybe, maybe not.
Although, since it's probably classified as low priority, rather not than maybe :P

FactionHeir
04-04-2007, 01:29
pfft low priority?! Someone needs to get their priorities straight! :p

alpaca
04-04-2007, 13:06
pfft low priority?! Someone needs to get their priorities straight! :p
Believe me, there's quite a lot of far more significant bugs in this game ;)
This one is only mildly annoying...

isellj0epnuts
04-04-2007, 21:47
...and from a twisted designer's standpoint, the current 'anti-trait' could be in place for balancing issues (though the argument is defeated when we observe a Merciless general losing all of his dread trait when he releases prisoners once...)

FactionHeir
04-04-2007, 21:51
Believe me, there's quite a lot of far more significant bugs in this game ;)
This one is only mildly annoying...

Hmm more than mildly but yes there are more important things. On a sidenote though, it was working perfectly fine in RTW and since M2TW is built on RTW, it could simply utilize the old code for antitraits.

Foz
04-13-2007, 03:42
I've been playing leaked 1.2, and antitraits seem to be working correctly now. Even passed a few tests specifically targeting it, so I'm confident it is completely fixed. One major result is that AI generals seem to end up with higher command stars a lot more of the time, which makes me happy. Several times I've been surprised to see 6+ star generals roaming about: in 1.1 I was never seeing any, save possibly my own.

Afro Thunder
04-13-2007, 03:53
Awesome, guess I won't have to tinker with the EDCT file any more, whenever we get the official 1.2, that is.

alpaca
04-13-2007, 19:29
Yep, I can confirm anti traits work fine now.

FactionHeir
04-13-2007, 21:12
Who was saying its too low on their priority they won't bother, eh? :p

Its great to hear its working though, no more tough decisions whether to build a church with the general in or not :D

Shigawire
04-15-2007, 13:06
Thanks for fixing this CA! :2thumbsup:

The Anti-Trait bug was not just a minor bug, but THE biggest deal-breaker for us for making EB2 - due to our massive trait system. The other deal-breakers were the inability to mod the meshes and animations, but that's in the process of being fixed now.