Hegemony III: Clash of the Ancients

Hegemony III: Clash of the Ancients

Hegemony III Workshop
Post your maps and mods here ...
Learn More
 This topic has been pinned, so it's probably important
Ijtzoi  [developer] 15 Jan 7, 2016 @ 8:30pm
Weekly Modding Tutorial Index
We at Longbow have been posting tutorials explaining how one mods our game; links to all our tutorials can be found in this thread.

1: Basics and the Blue Histri
2: Stances
3: New Factions in a New Sandbox
4: Upgrades
5: Skills and Skill Trees
6: Brigades
7: A First Look At Events
8: Quests (continues from Events)

In addition, video tutorials on the map editor can be found found on our YouTube channel (link).

If there's any topic you would like to see covered or you have any other modding questions, please do post and we'll do our best to help you out!
Last edited by Ijtzoi; Jan 7, 2016 @ 8:34pm
< >
Showing 1-13 of 13 comments
Grunge Mirkwood Jan 8, 2016 @ 9:49pm 
Can we see AI modding? Right now, it is really easy to: starve your foes into leaving their fort or wait for them to attack a 3rd party so they are weak. Additionally, is there a way to mod such that travel in winter hurts your units morale and potentially kills some of them?
Ijtzoi  [developer] 15 Jan 11, 2016 @ 7:55pm 
Many of the values the AI uses when deciding what to do are available in globals.xnt; look below <!-- AI constants -->. To edit a value in globals.xnt, create a mod and place a new globals.xnt in it, all of its information in one globals tag. You don't need to copy every value in globals, only the ones you want to change. For example, a mod that just had
<globals> <constaithresholdexpert>5</constaithresholdexpert> </globals>
in its globals.xnt would do nothing but change constaithresholdexpert down to 5, which would make the ai launch attacks more frequently on expert difficulty. Some of the ai globals are inside aiconst goal types and will only apply to plans of a certain type so if you do
<globals> <aiconst goaltype="raid"> <constfarmvalue>8</constfarmvalue> </aiconst> </globals>
It'll increase how likely the AI is to target farms instead of other targets during raids but not affect how it behaves when trying to capture a new building or city.

Modding winter travel is more difficult, there aren't any default mechanics or numbers you can use. You can however create events that would only fire in winter; it requires some knowledge of our event system and lua scripting, but it IS possible. The lua function getseason() will return a number between 0 and 4. Numbers between 0 and 1 are winter; this means than an event that checks if getseason() < 1 would only fire in winter. From there, you can have the event add an effect to factions:
for faction in listfactions do faction:setattribute("speed", - 0.25, "mult"); end
Would give all factions a speed penalty of 25%. You could also tweak maxmorale to edit morale, but at the moment that would change morale for all things, including cities thus making them more likely to rebel, which doesn't seem to be what you want. We are working on seperate morale attributes in future patches, though.
Of course, this will only add the attribute; you'll want to add a different event that checks if it's not winter and if we're still getting penalized for its being winter. Have the first event assign something to a variable (preferably in the _G table we set aside that gets saved and loaded, so this event works with save games); something like
_G.AreWeHitByWinter = true;
Then in your new event, check if that event happened by seeing if that variable's set. If so, and it's not winter, we'll need to clear away the attribute changes.
if _G.AreWeHitByWinter == true and getseason() >= 1 then for faction in listfactions do faction:setattribute("speed", 0, "mult"); --resets their speed end end

In addition to this, you can have a different winter-only event take a brigade, check if it's inside a city with the isincontainer() command, and if it's not, kill off a unit by calling the brigade:addunits(-1). It would be impossible to make the AI aware of this event and avoid moving around in winter, so it might be preferable to also check that the brigade's player-controlled. Doing this by event is a bit clumsy, but should be functional.

Hope this helps!
Last edited by Ijtzoi; Jan 11, 2016 @ 8:08pm
Grunge Mirkwood Jan 15, 2016 @ 4:05pm 
Thanks for the detailed post, I need to try some of this out. I would like to empower the AI to understand that winter is a problem for their units also if I made the "don't campaign in winter" change. Obv, the AI can be made to know about it, similar to AI not running ships in Heg 1 Gold during winter. I am really interested more in giving overall strategy and personality to the AI. How does the AI decide where to attack? Highest percieved value based on locations of enemy defenses versus target values? It seems a bit crazy for them to know everything about everywhere. I'd more like to see a diplomacy driven approach, where the AI waits for you to get tangled up and then invades at your rear. Or if you suffer a large defeat they might know about that and decide to challenge you. If they think they are outright stronger they might just go for the nearest useful target. etc. Additionally perhaps there are "plots" that can be undertaken, such as bribing a local noble to open city gates for them at night, but that ofc sounds like more of a crazy sidegame.
rob  [developer] 4 Jan 15, 2016 @ 10:38pm 
Unfortunately a lot of the basic AI routines aren't very moddable right now. This includes decisions on managing its own empire (capturing resources, building upgrades, constructing camps/bridges, etc) as well as deciding what player targets to attack. This is partly because there's a ton of calculations going on that would be too slow if we ran them as scripts and also because we're continually adjusting the AI and we don't have the resources to be updating a modding interface at the same time.

As you described, when picking targets to attack the AI does do a value vs threat comparison but it also factors in a lot of other things like game difficulty, time since last attacks, faction hostility, resources of potential launching points for the attack, etc. While the AI technically knows the size and position of all of the players units, we specifically avoid factoring these into the scale of AI attacks so players aren't indirectly penalized for better defense.

All of that said, we have been expanding the scripted portions of the AI significantly in Hegemony III. In 3.1 all diplomacy, AI vs AI conquests, and all city rebellions are now determined by scripting that can be modded and many attacks such as those that occur after breaking/rejecting truces are triggered by scripts.

I definitely love the idea of having more personality to the AIs and more plot to the objectives and it is something we're actively trying to work on as we go forward.

If you have any savedgames where you think the AI could be making a better decision, please send them along to rob@longbowgames.com While improving some AI behaviours can be weeks of work, many times I can make significant improvements just by adjusting some of the decisions weights or introducing a new piece of info the AI was considering before.

Also, if you're interested in scripting any plot events we'd be more than happy to provide any support you'd need to get it working.
Grunge Mirkwood Jan 26, 2016 @ 10:14pm 
I tried getting into this, I don't think I can do what I wanted for food. I want units to die off if they are out of food too long:

starvation.xml here:
<eventgroup>

<event name="General.Starvation" event="timed">
<pollingfrequency>1</pollingfrequency>
<scriptfile>resources/objectives/general/starvation.lua</scriptfile>
</event>

</eventgroup>

starvation.lua is here:
--how do I get a list of brigades? how are they uniquely IDe'd?
for brigade in listbrigades do
if (brigade:getfood()<1) then --how can I check food?
brigade:starvation=brigade:starvation+1;
else
brigade:starvation=0;--end starvation when food returns
if(brigade:starvation>0) then --avoid wasting cpu cycles if not starving
if(brigade:starvation>0) or if(brigade:starvation<3) then --start dying after 1 week of no food
brigade:setmorale(maxmorale*(starvation/2)); --after 2 days of no food, no combat ability left.
end
if(brigade:starvation>6) then --start dying after 1 week of no food
brigade:addunits(-(brigade:getsize()/10)); --all men dead at day 17. where are brigades destroyed?
end
end

end

-------------------------
I didn't even try to run this as I'm sure syntax is wrong and some functions I need don't exist. How do I turn on debug mode??
Ijtzoi  [developer] 15 Jan 26, 2016 @ 11:03pm 
Yeah, I can see how it'd be hard to find the functions you need with just the console, and we don't really have a good list available yet. One thing you can do is take a look at some of the scripts and events we have defined in the basic game (they're located in the game's Resources/Objectives/ClassOfObjectives folder) and compare to that for reference.

Originally posted by Grunge Mirkwood:
--how do I get a list of brigades? how are they uniquely IDe'd?
for brigade in listbrigades do
You actually came pretty close, here. What you would want is
for brigade in listbrigades() do
. listbrigades() is a function that creates the type of iterator we want. You could also do getplayerfaction():getbrigades() or getfactionbyname("Veii"):getbrigades() if you wanted to limit the brigades checked to a specific faction's. As for how they're uniquely ID'd, you can use the brigade:getid() to receive a number for the brigade that was randomly created for them when they're created that never changes*.

*If you retrain the brigade, the old one is deleted and relevant stats like xp and custom names are ported to the new one. Technically, the old brigade's ID never changed, but the retrained brigade will have a different one. If you assigned the brigade a script tag through the brigade:settag() function that would persist though.

Originally posted by Grunge Mirkwood:
if (brigade:getfood()<1) then --how can I check food?
brigade:getresource("supplies") returns how much food a brigade has, but this would still return 0 even if they were standing in the supply range of a city. Luckily there's the brigade:isinsupply() function, which returns either true or false.

Originally posted by Grunge Mirkwood:
brigade:starvation=brigade:starvation+1;
else
brigade:starvation=0;--end starvation when food returns
Hm, looks like you're trying to define your own variable in the brigade, I'm afraid you can't really do that; you CAN however create a table of brigade IDs to your new variable and look up the current one. What I'd suggest might look like this:
global.starvingbrigades[brigade:getid()]=global.starvingbrigades[brigade:getid()]+1; else global.starvingbrigades[brigade:getid()]=0; end;
Small note, you'll need to close this if/else block with an end and change all future brigade:starvation checks to refer to this variable instead.

Originally posted by Grunge Mirkwood:
if(brigade:starvation>0) then --avoid wasting cpu cycles if not starving
if(brigade:starvation>0) or if(brigade:starvation<3) then --start dying after 1 week of no food
brigade:setmorale(maxmorale*(starvation/2)); --after 2 days of no food, no combat ability left.
end
As you probably noticed, there is no setmorale or maxmorale function. The current morale of a brigade can't be set through script unfortunately (I'll see about adding that in a future patch), but the maximum can. The maximum morale of a brigade is controlled through the "maxmorale" attribute. If you call brigade:setattribute("maxmorale", -50, "add"), that'd add a 50 morale penalty to the maximum morale of the brigade and it would start fading towards that. Note that in the current system, this penalty will be applied twice for a total of -100, and unless you put a brigade:setattribute("maxmorale", +50, "add") somewhere, this will never be undone!

Originally posted by Grunge Mirkwood:
if(brigade:starvation>6) then --start dying after 1 week of no food
brigade:addunits(-(brigade:getsize()/10)); --all men dead at day 17. where are brigades destroyed?
end
end

end
You'll want to call either brigade:getmaxunits() or brigade:getnumunits() here. I honestly have no idea how the game will react if you put a brigade at zero or fewer units via script, but I doubt it'd be anything good, so you should add checks that the number you're about to remove is less than brigade:getnumunits(), and if it's not, call the function that destroys brigades, which is brigade:disband().

Originally posted by Grunge Mirkwood:
I didn't even try to run this as I'm sure syntax is wrong and some functions I need don't exist. How do I turn on debug mode??
No worries, we really ought to put together a list of useful functions sometime. Debug mode can be activated with debugmode(true)
Last edited by Ijtzoi; Jan 26, 2016 @ 11:04pm
Stabby  [developer] 1 Jan 27, 2016 @ 8:37am 
Once debugmode is on there are a bunch of things that you should be aware of.
All brigades that are attacked will be attributed to you. So if An AI brigade attacks another AI brigade you will get get the credit for attacking it (this will make diplomacy behave a little strangely)

The console will pop up a lot once you unpause the game telling you all sorts of things (there's a lot debug code).

to avoid seeing all our debug code you can use this:
pprint("what ever you want to print");

pprint() can do some useful things like:
pprint(getday())
the output of that will be ###.###. Basically you can print strings, print the result of a function, print the result of some math and so on.

our print and pprint code is inside the code:
if debugmode() then pprint("debug code"); end
and there is a lot of it. I would suggest not using the debug method as it's not neccessary print and pprint will print to and open the console.
Last edited by Stabby; Jan 27, 2016 @ 8:37am
Grunge Mirkwood Jan 27, 2016 @ 11:33pm 
ljtzoi: can I set the morale to a fixed amount rather than only adding to it? I'll change the starvation codes as you suggested and get that working first. I am now considering a mod we'd call "chance" which would add randomness to faction actions and perhaps historical tracking and adjustment of ai target values and posturing. I think it would be super cool for some enemies to be opportunistic and wait for you to suffer defeat, then suddenly try to nab some territory from you.
Robcore-Inside 4 Aug 20, 2016 @ 10:46am 
So when will there be a models editing tutorial? It cant be too hard. I mean I dont want you to explain how to retexture or 3d model! I just want to know how I can open those files properly to edit (retexture/recolour) them and then rename the file. An example:
Taras hoplites. I want them to have a black armour. So normaly I have to open a .dds file and recolour the armour parts, then save it as ??? dxt5? dxt3??? after that I will save it to taras_hoplite_black.dds. Now I still need to bring the texture i made into the game, normaly by making a complete new unit i think?. Then I can follow the instructions of the other tutorials I suppose. But WE NEED TO KNOW how to edit and then take those textures in the game?!?!? Please make a tut for it :) thank you. Also would be cool to know if we can adjust the variants of a unit, I mean a hoplite unit got different crests, so basically i want to have a more organized look, which means the crests for a unit should be all the same. How can I do this?
Robcore-Inside 4 Aug 20, 2016 @ 1:41pm 
Nevermind I found out that Photoshop is needed to see the textures. After exporting with my Version of PS I can see them also now in GIMP (though this doesnt work for all textures...) now I still need to know how to implement those retextured ones into the game. Anyone?
Tallestdavid Feb 6, 2017 @ 2:47am 
need to send you a debug bug i got.
Ijtzoi  [developer] 15 Feb 6, 2017 @ 2:38pm 
You can post any bugs in the forums or email them to rob@longbowgames.com or chris@longbowgames.com and we'll look at it.
Tallestdavid Feb 7, 2017 @ 10:29am 
Originally posted by Ijtzoi:
You can post any bugs in the forums or email them to rob@longbowgames.com or chris@longbowgames.com and we'll look at it.
ah dang i lost the debugged when i turn the pc off :/ ill keep taht email for next time.
< >
Showing 1-13 of 13 comments
Per page: 15 30 50