Modding tool

Note! The latest Democracy 3 update has broken the policies.csv file in two places:
ChildBenefit has an effect with the number “0.0.5”
DeathPenalty has an effect which is not correctly formatted according to the modding guide: “Religious-0.06-(0.06x)", it’s probably supposed to say "Religious,0.06-(0.06x)”
This means I have broken the error handling of the tool somewhat so that it still works, and I’m probably gonna stop working on it soon. As soon as I decide to stop, I will release the source files.

In order to encourage modding I’ve begun developing a modding tool for Democracy 3, which will provide a user interface for creating mods, hopefully making it more intuitive for modders. It allows you to create policies, simulations, situations and events, and observe their effects on the game. To use the mod in the game, simply export it to the mod folder of Democracy 3.

The application can be downloaded at http://coredumping.com/random/Democracy3Modder.zip.
I’ts a ~650KB zip file containing some binaries, of which Democracy3Modder.exe is the one to open. Chrome will probably block it, so you’ll have to manually approve the download. If it is of any comfort, I can promise you that it does not contain any malware.
The application requires .NET 4, and therefore Windows XP or later. You can download this here: http://www.microsoft.com/en-us/download/details.aspx?id=24872.
The application also requires you have Democracy 3 installed and will ask for the installation folder on startup.

Here’s a list of things I want to do before I call it quits, There might be far between updates and some might not happen at all, but I will strive to at least get the first six done.

  • Make effect operator font size bigger in dropdownmenus - Done
  • Merge input/output lists using a treeview - Done
  • Add hidden tab control, to show situation/simulation/policy specific controls when selected, instead of all over the place - Done
  • Add income/cost equations to effects tree when policy selected - Done
  • Add flags to policy editor tab: None, UNCANCELLABLE, MULTIPLYINCOME - Done
  • Add emotions to simulation editor tab: HIGHBAD, HIGHGOOD, UNKNOWN - Done
  • Add label on effect lines with the effect’s numerical value to SimulationView - Done
  • Downgrade to .NET 4 to add Windows XP support - Done
  • Add grudge editor with graph
  • Globalize possible target names across entire tool - Done
  • Refactor effect editing by creating effect control - Done
  • Add events - Done
  • Add .ogg playback - Done
  • Add dilemmas - Partially done
  • Add slider editor
  • Add effect direct input
  • Add country editor

And here’s a picture of the currently horrible looking interface:



Nice job thanks

Wow, well this influence feature on the screenshot looks nice.
Will try your editor a bit later.

Hell, I’ve done something similiar, I also created a editor currently for Country-Files and Policies, I’m currently starting the final tests and think will release it tomorrow.
Hope that’s not going to be a modding tool war, perhaps our both editors can eventually value up each other, I don’t know.
I did mine with C#.

Ah, crap. well, if it’s any consolation, I’m not sure I’ll be able to continue with mine between work and school.
I also made mine in C#, the biggest hassle I’ve had so far was interpreting effects, so here’s the source if you’re interested:
It also allows you to calculate the effect with some input x value. The object Values can be string if it’s an external effector, double if it’s a number and null if it’s the magic value x. The constructor takes a string like the ones in Democracy 3, the ToString() converts it back to Democracy 3 format.

[code]public class Effect
{
public string Target;
public object FirstValue, SecondValue, ThirdValue, FourthValue;
public EffectOp FirstOP, SecondOP, ThirdOP;
public bool ThirdTerm;
public int Inertia;

    public enum EffectOp
    {
        Add,
        Subtract,
        Multiply,
        Divide,
        Power
    }

    public Effect(string input)
    {
        var data = input.Split(',');
        Target = data[0];
		InterpretFormula(data[1]);
        Inertia = data.Length > 2 ? Convert.ToInt32(data[2]) : 0;
    }

    private static object ExtractValue(string formula, ref int i)
    {
        var j = i;
        if (formula[i] != 'x')
        {
            if (char.IsLetter(formula[i]) || formula[i] == '_')
            {
                while (i < formula.Length && (char.IsLetter(formula[i]) || formula[i] == '_'))
                {
                    i++;
                }
                return formula.Substring(j, i - j);
            }
            else
            {
                if (formula[i] == '-')
                {
                    i++;
                }
                while (i < formula.Length && (char.IsDigit(formula[i]) || formula[i] == '.'))
                {
                    i++;
                }
                return Convert.ToDouble(formula.Substring(j, i - j), System.Globalization.CultureInfo.InvariantCulture);
            }
        }
        else
        {
            i++;
            return null;
        }
    }

    private void InterpretFormula(string formula)
    {
        int i = 0;
        formula = formula.Replace("(", "").Replace(")", "").Replace(" ","");
        FirstValue = ExtractValue(formula, ref i);
        FirstOP = CharToOP(formula[i]);
        i++;
        SecondValue = ExtractValue(formula, ref i);
        SecondOP = CharToOP(formula[i]);
        i++;
        ThirdValue = ExtractValue(formula, ref i);
        if (i < formula.Length)
        {
            ThirdTerm = true;
            ThirdOP = CharToOP(formula[i]);
            i++;
            FourthValue = ExtractValue(formula, ref i);
        }
    }

    public static EffectOp CharToOP(char op)
    {
        switch (op)
        {
            case '*':
                return EffectOp.Multiply;
            case '-':
                return EffectOp.Subtract;
            case '/':
                return EffectOp.Divide;
            case '^':
                return EffectOp.Power;
        }
        return EffectOp.Add;
    }

    public static char OpToChar(EffectOp op)
    {
        switch (op)
        {
            case EffectOp.Multiply:
                return '*';
            case EffectOp.Divide:
                return '/';
            case EffectOp.Subtract:
                return '-';
            case EffectOp.Power:
                return '^';
        }
        return '+';
    }

    public static Func<double, double, double> OpToFunc(EffectOp op)
    {
        switch (op)
        {
            case EffectOp.Multiply:
                return (x, y) => x * y;
            case EffectOp.Divide:
                return (x, y) => y == 0 ? 0 : x / y;
            case EffectOp.Subtract:
                return (x, y) => x - y;
            case EffectOp.Power:
                return (x, y) => Math.Pow(x, y);
        }
        return (x, y) => x + y;
    }

    public static double ValueOrX(object value, double x)
    {
        return value == null ? x : (value.GetType() == typeof(double) ? (double)value : 0.5);
    }

    public static string ValueToString(object value)
    {
        return value == null ? "x" : (value.GetType() == typeof(double) ? ((double)value).ToString(System.Globalization.CultureInfo.InvariantCulture) : value.ToString());
    }

    public double GetValue(double x)
    {
        var val = OpToFunc(FirstOP)(ValueOrX(FirstValue, x), OpToFunc(SecondOP)(ValueOrX(SecondValue, x), ValueOrX(ThirdValue, x)));
        if (ThirdTerm)
        {
            val = OpToFunc(ThirdOP)(val, ValueOrX(FourthValue, x));
        }
        return val;
    }

    public override string ToString()
    {
        var sb = new StringBuilder();
        sb.AppendFormat("{0},{1}{2}({3}{4}{5})", Target, ValueToString(FirstValue),
            OpToChar(FirstOP), ValueToString(SecondValue),
            OpToChar(SecondOP), ValueToString(ThirdValue));
        if (ThirdTerm)
        {
            sb.AppendFormat("{0}{1}", OpToChar(ThirdOP), ValueToString(FourthValue));
        }
        if (Inertia > 0)
        {
            sb.AppendFormat(",{0}", Inertia);
        }

        return sb.ToString();
    }

    public static object EffectValueFromString(string value)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return 0;
        }
        double d = 0;
        try
        {
            d = Convert.ToDouble(value,System.Globalization.CultureInfo.InvariantCulture);
            return d;
        }
        catch (Exception ex)
        {
            if (value.ToLower().Equals("x"))
            {
                return null;
            }
            else
            {
                return value;
            }
        }
    }
}[/code]

Hehe, no need for consolation, sure I’m not the first to publish, but we both have the same goal to encourage modding in Democracy 3,
so who cares, not everything needs to be a competition.
And it’s fine, you did situations and mod data, while I was doing countries and policies.

Thx for the code snippet, I will evaluate this when doing the great code redesign which is necessary (did it quick & dirty somehow).
Currently recognizing Effects and Saving them is working on my editor, I just have to still evaluate if it saves everything correct
and works fine with the game and it should be also possible to load most mods with mine when I’m done.

Can’t argue with that. My mod currently does simulations and policies though, not situations, though it should be easy to add, so we have a bit of an overlap.
My goal was to make a modding tool that would make it possible to create big mod packages with several countries, policies, simulations, sliders, events and dilemmas, might have been a little ambitious considering how much time I have to spare.

Do you have this windows for virtualbox? (PM if you have)

I updated the application to include situations.

I do not

Great tool thanks.

If you are still working on it I would like to request the ability to edit the cost/income equations as well as the ability to directly edit the input/effect equations. Also, being able to see effects as numerical outputs in addition the graphical representation would be great.

Thanks again for the great tool.

Np, I hope you found it useful.
I’ll look into cost/income equations, but I don’t effects are gonna change, programmatically the current way works best, and you can write in anything you would otherwise be able to.
I might put in a slider or min/max indicators for the effects, I plan pn putting in graphs for the grudges at least.

Great tool,

I downloaded and Now I will use…

thanks

A collaborative project to create a single “community favored” modding tool would be awesome.

I promise to release the source at some point.

Cost and income equations, and numerical outputs in the graphical representation are added.

Source Code is available from me too, as soon I finished the redesign.
Simply PM me if you want the source code.

Yea, a collaborative project could drive forward faster, but needs some system like SourceSafe or CVS and a good team communication.

Great Work!
Edit: Would this work for 1.09 GoG version?
Tried multiple times but mod can not seem to find the Democracy 3.exe @ GoG version. Please help?

Based on the Steam version, the tool requires the following folders relative to Democracy3.exe:
data/bitmaps/policies
data/bitmaps/situations
data/simulation

So if your data folder is located somewhere else, try specifying that folder. Or you can write here how your folders are structured and I’ll update the tool.

I tried to put it but couldnt find any configs but here is my destination. The rest folders are in order. Thank you for your help :slight_smile:
D:\GOG Games\Democracy 3

If the folders are there, then it should work.
I’ve updated the tool so it displays a more descriptive error message when failing to load Democracy 3. Try downloading the new version and tell me what error you get.

Tried. This time It give different error. Here is the picture.