This program is intended to facilitate the modification of large contents of text with nothing but a few key strokes. With it, tasks that could take hours or days of painstaking manual work can be accomplished in mere moments. It was born out of my disappointment with regular expressions and their inability to modify matches in the manner I wanted. Though I made it with Total War games in mind, it can be used for any text editing purposes in which attention to detail and repetitive work are required. The program is written in ISO C99 and the GUI in C++ with Qt 5.15. It was cross-compiled for Windows with Mingw in Linux.
Here’s some examples of what it can do:
* Split lines in the document in tokens based on a delimiter character, and access each resulting field based on its position, for advanced modifications.
* Treat records in a line as numbers, not text, and perform arithmetic operations on them, optionally establishing conditions for when this happens. In example, is the value greater or equal to a specific number?
* Use different records with numerical values in a line as the base to modify another numerical record.
* Establish a filter for what you want to modify in the file. Areas that don't match this filter will not be modified.
* Create conditions to determine whether or not to carry out your changes.
* Change any record in a file according test parameters you establish. e.g in a units definition file, you could change attributes like type, class, category, formations, stats, or any other, and have those changes carried out for all other units in the file that share the same identifying characteristic you specified
* Export files into a table-like, comma separated value format, useful for viewing in spreadsheet software. With the added possibility of customizing what records are exported, the order, etc.
* Import files previously exported back into standard format.
Preliminaries:
Details:
The editing section has two main modes of operation, regular and line mode. Regular mode behaves like a normal find and replace function, wherein each pattern matched is replaced with the specified expression. In line mode the program will search for a specific pattern, and will treat the rest of the line as a list, using the pattern as a header and the rest of the line as fields of the list. Modifications can be made to these fields according to various criteria you specify. Fields are identified by their separating character, be it a comma, a space, or any character you specify.
Different flags can further alter how the program behaves. For instance, the insert flag makes the program insert an expression after the pattern rather than replace it. The discard flag, deletes everything else in the line after inserting an expression, and with reversal, an expression is inserted before the pattern instead of the other way around.
The true strength of the program, where it really shines, is in its ability to define conditions for when to perform modifications. It is possible to define an unlimited number of such conditions, stating for instance: I want to change this record if this other record has this value, and this other record exists, and this and that or this or that, etc. If all the conditions are met, the program proceeds to perform the requested changes, according to your specifications.
Unlike other programs with which you might be familiar, you can establish a specific search area within the text to scan for patterns. i.e the pattern need not be matched and replaced throughout the whole document, but in the areas you establish. To establish a processing area, we make use of section markers. By design, section markers are not bound by formatting. i.e markers are matched word for word, regardless of spaces, tabs, newlines or non printable characters in between.
For instance, imagine we have a book and want to modify an expression in a specific chapter only; we can establish an area encompassing this chapter by setting the starting section marker to "Chapter 5" assuming 5 is the chapter we want to modify, and the section marker end to "Chapter 6". The text will then be scanned between the words "Chapter 5" and "Chapter 6". If no markers are specified, the whole book will be scanned, instead of just Chapter 5.
The program's built-in help and the included documentation offer ample explanation of each feature and what they do. Instead of going over that here, I will present real cases in which I've used the program. This will hopefully give you some idea of what the tool is about and what it can do for you.
Real Use Examples:
In Stainless Steel, cavalry units are way too powerful for my taste. Not only during charges which are devastating even to powerful spear units, but in regular melee as well. To address this, I decided to nerf the base attack damage of all cavalry units by 30%, if their attack damage was greater than 6 points. It was precisely this task that prompted me to create the initial version of this program in the first place. Now, my knowledge of the EDU is very limited, so my changes might not have been the most accurate, or balanced, but they worked stupendously for my taste.
The task itself I achieved easily with these program options:
Code:
Start Marker: "category cavalry" End Marker: "ownership" Ignore: ";" Search Pattern: "stat_pri" Exact: On Line Mode: On Delimiter: "," Field: "1" Numeric: On Replacement: 0.7 Arithmetic: "*" Qualifier: ">7" Condition:"[stat_pri]spear"
That reduced the base damage of all cavalry with an attack damage greater than 6 (technically >= 7) by 30%. I used a condition to modify the text only if the stat_pri line contained the word spear; the reason for that is that I didn't want to change cavalry archers. I could have used a longer marker like "category cavalry class heavy" but then I'd have to do another pass to cover light cavalry.
With that done, I decided to "overhaul" the cavalry charge bonus by basing it on the value of the primary weapon. I thought an amount of twice the primary attack value, would be a good number:
Code:
Start Marker: "category cavalry" End Marker: "ownership" Ignore: ";" Search Pattern: "stat_pri" Exact: On Line Mode: On Delimiter: "," Field: 2 Numeric: On Replacement: "L1 0.7" Arithmetic: "*" Condition:"[stat_pri]spear"
After that, I wasn't happy with some new charge values, as they were a bit low, so I increased the charge damage by 2 points if they were below 10 points:
Code:
Start Marker: "category cavalry" End Marker: "ownership" Ignore: ";" Search Pattern: "stat_pri" Exact: On Line Mode: On Delimiter: "," Field: 2 Numeric: On Replacement: 2 Arithmetic: "+" Field: 10 Condition:"[stat_pri]spear
With that done, I nerfed the damage done with their secondary weapon by 40% if it was greater than 8. Some of these knights have insanely high damage in regular melee with their sword or mace, which is why they can obliterate units so quickly:
Code:
Start Marker: "category cavalry" End Marker: "ownership" Ignore: ";" Search Pattern: "stat_sec" Exact: On Line Mode: On Delimiter: "," Field: 1 Numeric: On Replacement: 0.6 Arithmetic: "*" Condition:"[stat_pri]spear
The results: overpowered cavalry units were a bit weaker, but in most cases stronger during a charge and much more manageable in regular melee combat.
In the same vein with the cavalry changes, I wanted to rebalance spear units and their strength vs cavalry. I thought it best to start from a blank slate and so used the program to delete all the attributes in the stat_pri_attr line. It didn't matter whether my EDU file contained a single spear unit or one thousand. All it took was to write one line:
Code:
Start Marker: "class spearmen" End Marker: "era" Search Pattern: "stat_pri_attr" Replacement: "" Discard: On
Then I did a second pass inserting basic common attributes, spear and spear_bonus_2.
Code:
Start Marker: "class spearmen" End Marker: "era" Search Pattern: "stat_pri_attr" Replacement: " spear, spear_bonus_2" Insert: On
Technically, this could be done in a single pass(and that's how I originally did it), but I wanted to compartmentalize it here for illustrative purposes.
This served as a solid foundation on which to base further customization. From here, we can establish further attributes based on whether the unit is a pike unit, the the quality of the unit, the experience, etc. To do that I made use of conditions. Conditions help to establish a set of qualifications that must be met before the program executes our orders. In this case, I wanted 2 things in addition to have the spearmen class: that the unit used a pike and that it was well trained. With those two conditions met, I deemed the unit worthy of having the pike attribute, and gave it a spear bonus of 4.
This is how I accomplished the task:
Code:
Start Marker: "class spearmen" End Marker: "\n\n" Special: On Search Pattern: "stat_pri_attr" Exact: On Line Mode: On Ignore: ";" Delimiter: "," Field: 2 Replacement: "long_pike, spear_bonus_4" Insert: On Condition: "[stat_pri]pike" Condition: "[stat_mental]trained"
This removed the old bonus, which was the second attribute in stat_pri_attr, leaving now: spear, long_pike and spear_bonus_4. All the units that met the criteria now had the correct attributes. I continued to customize things further by creating a new set of conditions each tailored to fit the change I had in mind.
Recently, I finished what in most certainty will be my absolute last playIgnore:hrough of the Witcher 3. After a good 120 hours I bid farewell to my friend Geralt of Rivia leaving him to enjoy the rest he well deserves. I've finished the game maybe 3-4 times since its release. but always return for one reason or another. This time, it was a mod that prompted me to return, the W3EE. In retrospect, I regret having played because I had to spend so much time fixing and changing the mod, that it took from my enjoyment of the game. This program helped me more than a couple of times to do tedious edits to xml item definition files. I present one of those below:
Code:
<!-- ARMOR LIGHT -->
<ability name="Light armor 01_crafted 1 _Stats">
<weight type="base" min="4.0" />
<quality type="add" min="1" max="1" />
<armor type="base" min="42" max="42" />
<slashing_resistance_perc type="base" min="0.10" />
<piercing_resistance_perc type="base" min="0.09" />
<bludgeoning_resistance_perc type="base" min="0.09" />
<elemental_resistance_perc type="base" min="0.10" />
<armor_regen_penalty type="mult" min="-0.01" />
<armor_stamina_efficiency type="mult" min="-0.01" />
<armor_speed type="mult" min="-0.030" />
</ability>
This is one of several entries that fill the armor definition files. Basically these dictate the properties of armor in the game. I wanted to make light armor have a lesser effect on the speed of the player and, since modifying these by hand would be immensely tedious, I used the to accomplish my task:
Code:
Start Marker: "<!-- ARMOR LIGHT -->" End Marker: "<!-- ARMOR MEDIUM -->" Search Pattern: "armor_speed" Replacement: 0.01 Arithmetic: 3 Line Mode: On Delimiter: " Field: 4 Numeric: On Arithmetic: "+"
In the above command, I make use of section markers to establish a "working area" that encompasses only light armor, the rest of the armor entries are not modified. I also increase the arithmetic precision to 3 decimal places to match the precision of the numbers in the file and use a quote " character as the CSV delimiter since spaces, and the equal sign were not close enough to the number. As for the operation itself, it's a simple subtraction, I subtract 0.01 from whatever value armor_speed has, so all the light armors in the game ended up 0.01 lighter.
For the particular example shown above the result is:
Code:
<armor_speed type="mult" min="-0.020" />
While we are talking about The Witcher 3, here's another task in which I had to use the program:
Code:
[Exploration]
IK_F=(Action=TakePaintGreen)
IK_F=(Action=Look)
IK_F=(Action=Stash)
IK_F=(Action=PlaceBeans)
IK_F=(Action=PlaceLure)
IK_F=(Action=GiveAlms)
IK_F=(Action=PlaceSword)
IK_F=(Action=PlaceArmor)
IK_F=(Action=HangPainting)
This is a snippet of the input.settings file. Basically, this file controls what each key press does in the game. Normally, this can be configured in game, but certain modDiscard: Ondded keys and other select functionality can only be changed manually by changing this file. Besides the length of the file, there's another hurdle to overcome: each key behaves differently depending on the context used so if for instance you want the the space key to open the stash while in exploration mode, but to do something else while swimming, you have to configure those separately. Luckily, with the program I can limit the area of my changes to a specific context by using section markers. Additionally I don't need to look up what key is bound to the action I want to change in what context, I can just say I want to change this action, in this and this context to use this specific key.
So, going back to the example above and say we wish to change the key used to open the stash in the exploration context to the space key, we can do so like:
Code:
Start Marker: "[Exploration]" End Marker: "\n\n" Special: On Search Pattern: "(Action=Stash)" Replacement: "IK_SPACE=" Discard: On Special: On
The program searches for the action I specify, then inserts the key before the action, removes everything else on the line and finally writes the result to the same file. The result for the example above:
Code:
IK_SPACE=(Action=Stash)
I would have spent a lot of time on this, had I done it manually.
Download Link
changelog available in download thread.