[Vanilla] Custom requirements not working?

ChrisWJN

Chieftain
Joined
Mar 12, 2019
Messages
43
Location
Canada
I'm trying to make a civ where their ability is to be able to make equipment for their unique unit, giving them abilities over the course of the game. Currently, I've created a unique district, with district-unique buildings which grant modifiers to units.

The way I have it set up makes it so that each building has a modifier that attaches a modifier to all player units. The modifiers it attaches each have a SubjectRequirementSetId that should make it so only one type of unit benefits from the modifier, but it's not the case. All units get the modifier if I build the building.

An example of how this works:

Each building has a modifier like this:

<ModifierId>BUILDING_ATTACH_MOD</ModifierId>
<ModifierType>MODIFIER_PLAYER_UNITS_ATTACH_MODIFIER</ModifierType>

The modifier I've attached to BUILDING_ATTACH_MOD is this:

<ModifierId>MOD_NO_TERRAIN_PENALTY</ModifierId>
<ModifierType>MODIFIER_PLAYER_UNIT_ADJUST_IGNORE_TERRAIN_COST</ModifierType>
<SubjectRequirementSetId>UNIT_IS_HOLLOW</SubjectRequirementSetId>
(with proper modifer arguments)

This is my requirement to check if the unit is the right type:

<RequirementSets>
<Row>
<RequirementSetId>UNIT_IS_HOLLOW</RequirementSetId>
<RequirementSetType>REQUIREMENTSET_TEST_ALL</RequirementSetType>
</Row>
</RequirementSets>
<RequirementSetRequirement>
<Row>
<RequirementSetId>UNIT_IS_HOLLOW</RequirementSetId>
<RequirementId>UNIT_IS_HOLLOW_REQUIREMENT</RequirementId>
</Row>
</RequirementSetRequirement>
<Requirements>
<Row>
<RequirementId>UNIT_IS_HOLLOW_REQUIREMENT</RequirementId>
<RequirementType>REQUIREMENT_UNIT_TYPE_MATCHES</RequirementType>
</Row>
</Requirements>
<RequirementArguments>
<Row>
<RequirementId>UNIT_IS_HOLLOW_REQUIREMENT</RequirementId>
<Name>UnitType</Name>
<Value>UNIT_DSMOD_HOLLOW</Value>
</Row>
</RequirementArguments>

So in theory, at least in my mind, is that this should grant the ignore terrain cost modifier to all units, but then check if the unit is a UNIT_DSMOD_HOLLOW or not. If it is, it will be able to ignore terrain costs, but if it isn't, it can't.
However, when I test it, what ends up happening is that ALL units are able to ignore terrain costs. I can't figure out what the problem with my requirement is.
 
Last edited:
I think the problem is here
Code:
<ModifierId>MOD_NO_TERRAIN_PENALTY</ModifierId>
 <ModifierType>MODIFIER_PLAYER_UNIT_ADJUST_IGNORE_TERRAIN_COST</ModifierType>
 <SubjectRequirementSetId>UNIT_IS_HOLLOW</SubjectRequirementSetId>
Since in DynamicModifiers we have
Code:
		<Row>
			<ModifierType>MODIFIER_PLAYER_UNIT_ADJUST_IGNORE_TERRAIN_COST</ModifierType>
			<CollectionType>COLLECTION_OWNER</CollectionType>
			<EffectType>EFFECT_ADJUST_UNIT_IGNORE_TERRAIN_COST</EffectType>
		</Row>
I think in this case the owner of the modifier will be the unit to which the modifier is attached. The unit to which the modifier is attached I don't think will be the 'subject' of the modifier. So I would try
Code:
<ModifierId>MOD_NO_TERRAIN_PENALTY</ModifierId>
 <ModifierType>MODIFIER_PLAYER_UNIT_ADJUST_IGNORE_TERRAIN_COST</ModifierType>
 <OwnerRequirementSetId>UNIT_IS_HOLLOW</OwnerRequirementSetId>
I know that the effect can be created by using a UnitAbility and only allowing the UnitAbility to be applied to an Ability-Class that is only attached to UNIT_DSMOD_HOLLOW if using an OwnerRequirementSetId is still not applied correctly by the game.
 
I find XML extremely hard to read so forgive me for stumbling through this. :)

First thing I would do before banging my head against the keyboard any longer is getting SQLite Studio and writing some SQL queries to see what is going on at the database level. You'll want something like this:

SELECT * FROM Modifiers
LEFT JOIN ModifierArguments USING (ModifierId)
left join requirementsets on requirementsets.RequirementSetId= modifiers.SubjectRequirementSetId
left join requirementsetrequirements using (requirementsetid)
left join requirements using (requirementid)
left join requirementarguments using (requirementid)
where modifiers.ModifierType like '%MODIFIER_NO_TERRAIN_PENALTY%';


This should give you a view into whether the code is even making it into the database at all.

By the way, as a convenience I recommend a standard naming convention for when you are naming modifiers. I would start any object that you insert into the database with some kind of 'calling card,' an unusual string of letters other modders are unlikely to duplicate.

Then, for me, when I have Broadcast/attaching modifier: end with the word _PLAYER (if broadcast to all entities owned by a player) or else _ALL (if broadcast to all players).

For you this would be:

  • CWJN_MODIFIER_NO_TERRAIN_PENALTY
  • CWJN_MODIFIER_NO_TERRAIN_PENALTY_PLAYER

The advantage of this is when you get to SQLite Studio you can do a statement like WHERE ModifierType like '%CWJN%' and have a view of every custom Modifier you've created in your mod.
 
Thanks so much for the help guys! I'll try it later today when I get back to my computer. As for SQL stuff, I really I have no idea how to do anything in SQL besides the basics. I do know that SQL is a better language to use, but since I'm a beginner to modding, I'm just going to stick with the language I already know for now.
 
Thanks so much for the help guys! I'll try it later today when I get back to my computer. As for SQL stuff, I really I have no idea how to do anything in SQL besides the basics. I do know that SQL is a better language to use, but since I'm a beginner to modding, I'm just going to stick with the language I already know for now.


IMO if you're going to be doing any sort of modding you need to be working with SQL. It's not just a question of whether XML or SQL is better. You need SQL in order to make your QA process efficient, even if your actual mod code is not written in SQL. Otherwise you will spend hours trying to figure out why code is not working. You want to be able to peek into the database to see if your updates are applying. Trying to do it just from in-game feedback is very difficult. The hours of frustration you will save just by learning how to connect t the database and write simple SELECT statements is worth it.
 
Top Bottom