DLL - Lua API requests

I'd like to request a few things in order to improve the stability of my ExCE mod (which I'll be working on for CBP compatibility as a bribe :p) - hopefully they're feasible.

Would it be possible to add an "AdjacentSpawnLocationUnitFreePromotion" to the Terrains and Features table. This would allow a promotion to be added to units that spawn adjacent to a specific terrain or feature, and to add "SpawnLocationUnitFreePromotion" to the Features table (good for Marsh or Flood Plains, for me).

And would it be possible to add a way to negate the "LocationUnitFreePromotion", such as with another promotion? To put it anecdotally, in ExCE, ocean terrain affords the Scurvy Promotion (I want information displayed as to the risks, hence I don't just use TerrainTurnDamage). However, there is a corresponding Scurvy Immunity promotion that is intended to remove the Scurvy Promotion. So could you add a "LocationUniFreePromotionNegatingPromotion" column or something along those lines? So that if the unit has that promotion and enters a terrain/feature with an applicable LocationUniFreePromotion, the free promotion from that column is not applied (or removed if it is on the unit; though this is less needed for me, as that can be handled with less strenuous Lua). Incidentally, does "LocationUnitFreePromotion" obey Promotion_UnitCombat rules?

Finally, would it be possible to make it so that embarked units are affected by LocationUnitFreePromotion? Though it'd only be needed for me if the above can be done somehow.

Thanks for anything you can help with.

EDIT: One more: is there any way to allow Game.GetGreatWorkTooltip(greatWorkIndex, playerID) to be intercepted? To support Whowards GreatWorkYieldTypes component.

Better yet:

pPlayer:GetCityOfClosestGreatWorkSlot(iX, iY, iGreatWorkSlotType)

iGreatWorkSlotType being something like GameInfoTypes.GREAT_WORK_SLOT_ART_ARTIFACT. Note that if there are no open slots of the specified iGreatWorkSlotType available, the function returns nil.

In case it's worth something to you, player:GetBuildingOfClosestGreatWorkSlot(iX, iY, iGreatWorkSlotType) seems to exist :p
 
Would it be possible to update Gedemon's RED combat functions to allow the damage dealt by a specific unit to be directly altered via Lua, before combat starts?

Okay, looking at these requests. Can you clarify this one a bit more?

I have another request. Could we have a tag in the UnitPromotions table which prevents a unit from being captured from things such as Suleiman's vanilla trait?

Yep, I'll add this. Should it destroy the unit?

Would it be possible to add an "AdjacentSpawnLocationUnitFreePromotion" to the Terrains and Features table. This would allow a promotion to be added to units that spawn adjacent to a specific terrain or feature, and to add "SpawnLocationUnitFreePromotion" to the Features table (good for Marsh or Flood Plains, for me).

I have these already (they've been there for some time) - will they suffice?

Code:
- Grants a free valid promotion to a unit when it enters a type of feature (forest, marsh, etc.).

ALTER TABLE Features ADD COLUMN 'LocationUnitFreePromotion' text default NULL;

-- Grants a free valid promotion to a unit when it spawns on type of feature (forest, marsh, etc.). Generally used for barbarians.

ALTER TABLE Features ADD COLUMN 'SpawnLocationUnitFreePromotion' text default NULL;

-- Feature-promotion bonuses restricted to Barbarians. Can be used with CityStateOnly if desired.

ALTER TABLE Features ADD COLUMN 'IsBarbarianOnly' boolean default false;

-- Feature-promotion bonuses restricted to City States. Can be used with IsBarbarianOnly if desired.

ALTER TABLE Features ADD COLUMN 'IsCityStateOnly' boolean default false;

-- Grants a free valid promotion to a unit when it enters a type of terrain (grassland, plains, coast, etc.).

ALTER TABLE Terrains ADD COLUMN 'LocationUnitFreePromotion' text default NULL;

-- Grants a free valid promotion to a unit when it spawns on type of terrain (grassland, plains, coast, etc.). Generally used for barbarians.

ALTER TABLE Terrains ADD COLUMN 'SpawnLocationUnitFreePromotion' text default NULL;

-- Grants a free valid promotion to a unit when it is adjacent to a type of terrain (grassland, plains, coast, etc.). Generally used for barbarians.

ALTER TABLE Terrains ADD COLUMN 'AdjacentUnitFreePromotion' text default NULL;

-- Terrain-promotion bonuses restricted to Barbarians. Can be used with CityStateOnly if desired.

ALTER TABLE Terrains ADD COLUMN 'IsBarbarianOnly' boolean default false;

-- Terrain-promotion bonuses restricted to City States. Can be used with IsBarbarianOnly if desired.

ALTER TABLE Terrains ADD COLUMN 'IsCityStateOnly' boolean default false;

So could you add a "LocationUniFreePromotionNegatingPromotion" column or something along those lines? So that if the unit has that promotion and enters a terrain/feature with an applicable LocationUniFreePromotion, the free promotion from that column is not applied (or removed if it is on the unit; though this is less needed for me, as that can be handled with less strenuous Lua). Incidentally, does "LocationUnitFreePromotion" obey Promotion_UnitCombat rules?

Finally, would it be possible to make it so that embarked units are affected by LocationUnitFreePromotion? Though it'd only be needed for me if the above can be done somehow.

The first request, are you asking for a new promotion line? Also, yes, they do follow unitcombat rules.

G
 
Whoops, for some reason I thought "LocationUnitFreePromotion" wasn't in the Features table (only in Terrains). Nevermind about that part then.

But I still would like something like "AdjacentSpawnLocationUnitFreePromotion."

"AdjacentUnitFreePromotion" (which is only in Terrains btw) applies the promotion as a unit enters the tile adjacent to the specified terrain/feature. I only want the promotion to be applied when the unit is first created in the tile adjacent to the specified terrain/feature (so if I train a unit in a city adjacent to a desert, that unit will get the promotion specified in te Deserts>AdjacentSpawnLocationUnitFreePromotion column). It's not a primary need, as the Lua to simulate the effect is fairly simple, and only fires on the UnitCreated event, but if it's possible, it would probably make things more efficient.

The other request is that which I have need of most. As it stands, if I have a promotion in LocationUnitFreePromotion applied to, say, the Ocean terrain, units will get this promotion as they move about the ocean. However, I need to add a condition that, if the unit has X promotion (specified in another column, such as "LocationUniFreePromotionNegatingPromotion", though that's not a terribly articulate name), it won't get the promotion registered to LocationUnitFreePromotion, e.g. if a unit has my Scurvy Immunity promotion (added in ExCE), then I don't want it getting the Scurvy promotion as it moves along ocean. Atm, I'm checking, with Lua, every time a unit moves along to ocean to give the Scurvy promotion, but only if it doesn't already have the Scurvy Immunity promotion, which is quite a taxing method - and half of it is already supported by the DLL.
 
In case it's worth something to you, player:GetBuildingOfClosestGreatWorkSlot(iX, iY, iGreatWorkSlotType) seems to exist :p

They both pretty much accomplish the same thing if your only goal is to find out if a player can hold a new Great Work of a specific type. Of course, if you are trying to put it in a specific building, then GetBuildingOfClosestGreatWorkSlot would work better.



Okay, looking at these requests. Can you clarify this one a bit more?


Let's say two melee units have combat and do damage to each other. What I'd like is the ability to edit the damage dealt within the CombatResult (or CombatEnded, I don't know which one fires first) function, and have the function return whichever values the user wants for both attacker's and defender's damage. For example...

Code:
function OnCombatEndedRecoverQBDamage(iAttackingPlayer, iAttackingUnit, attackerDamage, attackerFinalDamage, attackerMaxHP, iDefendingPlayer, iDefendingUnit, defenderDamage, defenderFinalDamage, defenderMaxHP, iInterceptingPlayer, iInterceptingUnit, interceptorDamage, plotX, plotY)
	local pAttackingPlayer = Players[iAttackingPlayer]
	local pDefendingPlayer = Players[iDefendingPlayer]
	local iReturnedAttackerDamage = attackerDamage
	local iReturnedDefenderDamage = defenderDamage
	
	if pAttackingPlayer and pDefendingPlayer then
		local pAttackingUnit = pAttackingPlayer:GetUnitByID(iAttackingUnit)
		local pDefendingUnit = pDefendingPlayer:GetUnitByID(iDefendingUnit)
		if pAttackingUnit and pDefendingUnit then
			local sAttackingType = GameInfo.Units[pAttackingUnit:GetUnitType()].Type
			local sDefendingType = GameInfo.Units[pDefendingUnit:GetUnitType()].Type
			
			--Incubators should never deal melee damage, so set damage of other unit to 0 if one enters melee combat.
			if (string.find(sAttackingType, "_PMMM_") and string.find(sAttackingType, "INCUBATOR")) or HasAnyTimeStopPromo(pAttackingUnit) then
				iReturnedDefenderDamage = 0
			elseif (string.find(sDefendingType, "_PMMM_") and string.find(sDefendingType, "INCUBATOR")) or HasAnyTimeStopPromo(pDefendingUnit) then
				iReturnedAttackerDamage = 0
			end
			
		end
	end
	
	return iReturnedAttackerDamage, iReturnedDefenderDamage
end

GameEvents.CombatEnded.Add(OnCombatEndedRecoverQBDamage)

What I would want the above code to do is completely negate damage (i.e. return 0 for the damage dealt) to any unit which attacks the unit UNIT_PMMM_INCUBATOR or UNIT_PMMM_ARTIFICIAL_INCUBATOR. Right now, I have it done by healing the damage dealt in Lua in a CombatEnded function, but it's ugly and clunky. In later stages of the mod, I'll be introducing some promotions which reduce all damage taken by flat amounts as well.

Yep, I'll add this. Should it destroy the unit?

Yes.
 
On reflection, I suppose it's intended for LocationUnitFreePromotion to not remove the specified promotion once the unit leaves the terrain/feature, but it's something I hadn't realised until now. So could you add - whenever your next update is - an IsTerrainOnly and IsFeatureOnly column to the Terrains and Features tables, so that the FreePromotion is removed if a unit leaves the terrain/feature. Thanks.
 
On reflection, I suppose it's intended for LocationUnitFreePromotion to not remove the specified promotion once the unit leaves the terrain/feature, but it's something I hadn't realised until now. So could you add - whenever your next update is - an IsTerrainOnly and IsFeatureOnly column to the Terrains and Features tables, so that the FreePromotion is removed if a unit leaves the terrain/feature. Thanks.

Makes sense. I'll just do it as an 'else' for the current tests with a false modifier, so as to remove the promotion.
G
 
On reflection, I suppose it's intended for LocationUnitFreePromotion to not remove the specified promotion once the unit leaves the terrain/feature, but it's something I hadn't realised until now. So could you add - whenever your next update is - an IsTerrainOnly and IsFeatureOnly column to the Terrains and Features tables, so that the FreePromotion is removed if a unit leaves the terrain/feature. Thanks.

I checked the code for the ice crossing, etc., and it is all fine - I haven't touched any of it.

To be sure, you are updating the custommodoptions.xml to enable the functionality of the promotions, yes?
G
 
Unless it was something other than "PROMOTIONS_CROSS_MOUNTAINS" and "PROMOTIONS_CROSS_ICE," I'm absolutely sure - I always check SQLite Manager to check that it's updating the database correctly. Even if I hadn't, I tested with whoward's Pick n Mix mod in which promotions with these functions are introduced, but they worked neither in my mod nor his. I'm really at a loss.
 
I would like to request a table that allows a building to add local happiness to another building, like Neuschwanstein, but only to the building in that city, instead of to all of that building in the empire. I'd also like to request the equivalent YieldChanges table. So the table could be named something like Building_BuildingClassLocalHappiness and Building_BuildingClassLocalYieldChanges.
 
Would it be possible to move SAPPED_CITY_ATTACK_MODIFIER and SAPPER_BONUS_RANGE from Defines to UnitPromotions? It will allow to create units with different sapper promotions.
 
Would it be possible to move SAPPED_CITY_ATTACK_MODIFIER and SAPPER_BONUS_RANGE from Defines to UnitPromotions? It will allow to create units with different sapper promotions.

Because of the way the code is written, these defines are not easily changed (the unit in question isn't part of the function, so a costly call would have to be made to retrieve and integer the value). I'm not sure this is feasible without significant reworking of the function, so I'm going to put this on hold.


G
 
I know I haven't tested the Damage altering promotions that you added for me yet (been quite busy hunting bugs down first), so sorry to ask for another thing before I've even gotten to use the first thing I requested.

Can we add a "Duration" field to UnitPromotions? The idea is that Duration represents a number of turns a Unit has a Promotion before it is automatically removed. For example, Duration 3 will cause the promotion to be automatically removed upon the beginning of the fourth turn of the unit's owner. Ideally, this would apply to promotions granted via pUnit:SetHasPromotion() as well as by other, "normal" means.

Also, I have these tables in my mod already. The effects are currently done via Lua, but if these were implemented in the DLL, I'm sure they'd be significantly faster. I believe the effects are self-explanatory, but if you need more details on what I want each one to accomplish, let me know.

Thanks for all the work you've put into CP!

Code:
	<!--Grant a promotion to a unit if it is on a specific Improvement-->
	<Table name="Promotion_PMMM_GrantNewPromotionOnImprovement">
		<Column name="PromotionType" type="text" reference="UnitPromotions(Type)"/>
		<Column name="ImprovementType" type="text" reference="Improvements(Type)"/>
		<Column name="NewPromotionType" type="text" reference="UnitPromotions(Type)"/>
	</Table>

	<!--Grant a promotion to nearby enemy units (typically a bad one)-->
	<Table name="Promotion_PMMM_GrantAdjacentEnemyPromotion">
		<Column name="PromotionType" type="text" reference="UnitPromotions(Type)"/>
		<Column name="Radius" type="integer" default="1"/>
		<Column name="EnemyPromotionType" type="text" reference="UnitPromotions(Type)"/>
	</Table>

	<!--Grant a promotion to nearby allied units (not this unit itself)-->
	<Table name="Promotion_PMMM_GrantAdjacentAllyPromotion">
		<Column name="PromotionType" type="text" reference="UnitPromotions(Type)"/>
		<Column name="Radius" type="integer" default="0"/> <!-- 0 makes it only work on units stacked on the same tile -->
		<Column name="AllyPromotionType" type="text" reference="UnitPromotions(Type)"/>
	</Table>

	<!--Get another promotion when an enemy is near-->
	<Table name="Promotion_PMMM_GrantNewPromotionNearEnemy">
		<Column name="PromotionType" type="text" reference="UnitPromotions(Type)"/>
		<Column name="Radius" type="integer" default="1"/>
		<Column name="NewPromotionType" type="text" reference="UnitPromotions(Type)"/>
	</Table>
 
Excellent. Thanks again for looking into it.

Also, it'd be ideal if there was an added API method to retrieve either the current duration of a Promotion, or the turn number on which a Unit received that promotion. This way, I could add in some logic to UnitPanel to tell users how long particular Promotions will last.
 
Excellent. Thanks again for looking into it.

Also, it'd be ideal if there was an added API method to retrieve either the current duration of a Promotion, or the turn number on which a Unit received that promotion. This way, I could add in some logic to UnitPanel to tell users how long particular Promotions will last.

I'd have to do that anyways (save that data), as that's how the DLL would track expiration. I'll make some lua hooks for it once I get around to it (I've been out of town, and there's a lot of things to look at, bug-wise).

Test the damage-altering promotions for me when you get a chance.

G
 
Okay, I went ahead and tested them.

It would appear that ChangeDamageValue isn't working, and ForcedDamageValue is returning 2 damage regardless of which value is put in.

Here are a few of the combat tests I ran, showing the damage inflicted prediction from UnitPanel, what type of promotion the unit had, and the actual damage dealt to the unit:

Approx. Dmg Inflicted: 36
Promotion: 5 ForcedDamageValue
Result: 2 Damage

Approx. Dmg Inflicted: 33
Promotion: 50 ChangeDamageValue
Result: 29 Damage

Approx. Dmg Inflicted: 30
Promotion: -50 ForcedDamageValue
Result: 2 Damage

Approx. Dmg Inflicted: 38
Promotion: -100 ChangeDamageValue
Result: 44 Damage

Approx. Dmg Inflicted: 13
Promotion: 50 ChangeDamageValue
Result: 10 Damage

Approx. Dmg Inflicted: 10
Promotion: 50 ChangeDamageValue
Result: 9 Damage


Alas, it also seems to not be effective if the promotions are added to the unit during the RED Combat hooks (tried both CombatResult and CombatEnded), which is what I was really hoping for...

This testing was relatively quick and dirty, but I can test some more if you need me to.
 
I see my requests made it into the latest version - thanks, very much appreciated :D

For the next version, would it be possible to expose Team:SetForcePeace() to Lua. The difference between this and Team:MakePeace() being that it instigates a peace treaty (AFAIK), which I'd otherwise need to simulate messily.
 
I have several requests.
1. New column for improvements table: "ExtraSightRange" . Gives units extra sight range. Value is integer.
2. New column for improvements table: "RequiresConnectionToCapital" . Improvement can be built only if tile is connected to capital. If connection is lost the resource provided by improvement is lost too. Value is boolean.
3. New column for improvements table: "ConnectsResourceOusideBorders" . Connects resource to your trade network even if it's ouside your borders. Value is boolean.
4. Move GREAT_GENERAL_RANGE and GREAT_GENERAL_STRENGTH_MOD from defines to UnitPromotions.
5. New column for UnitPromotions that makes great general affect not only your units but every one within its range.
 
Lots of requests, I'll look at them soon enough. I didn't test those additions, JFD, so test them and let me know if they work (they may also need some LUA to show the yield changes &#8211; if so, I can expose them to lua).

Vicevirtuoso,
I'll see what the problem is &#8211; the functions are pretty simple, but you never know. Thanks for testing.

Also, regarding the RED hooks, the problem is that said hooks occur 'tangentially' within the combat functions (i.e. the RED hook happens within the existing function), thus there is no 'clean' way to easily hook that hook, if that makes sense. I'll look at it, but no guarantees, unfortunately.

Edit: in the future, can we have all DLL API requests pinned to the 'Issues' tab of github? Helps me keep tabs on them.
G
 
Top Bottom