-- ===============================================================================================
-- STATE / CACHE from BlackDeathScenario
-- Custom data are kept in cache and set into game as a property on the Game object from script thread
-- Set your custom data = pObject:SetProperty(sPropertyName, value)
-- Get your custom data = pObject:GetProperty(sPropertyName)
-- Object can be Game, pCity, pPlayer, pUnit, pPlot
-- Value are variable, field, structure
-- Name of Value (sPropertyName) are stored in g_PropertyKeys
-- Handle among script thread and UI thread guarantee function in this file
-- This file must be insert on start every file using "include" command (from UI and script)
-- When save, load game system do it with yours custom data
-- ===============================================================================================
g_PropertyKeys = {
MilitarizationPerTurn = "MilitarizationPerTurn", -- your custom data
};
-- Every time SetObjectState is called, the script-side cache is updated to prevent unnecessary
-- calls down to gamecore.
local USE_CACHE : boolean = true;
local g_ObjectStateCache = {};
-- ===========================================================================
function SetObjectState(pObject : object, sPropertyName : string, value)
if (sPropertyName == nil) then
return nil;
end
if (pObject == nil) then
print("StateUtils SetObjectState: ERROR: object is nil!");
return nil;
end
if (USE_CACHE == true) then
if (g_ObjectStateCache[pObject] == nil) then
g_ObjectStateCache[pObject] = {};
end
-- update cache
g_ObjectStateCache[pObject][sPropertyName] = value;
end
-- when you call this function from UI thread you must update data on script thread
if UI ~= nil then
-- We are on the UI side of things. We must sent a command to change the game state
local kParameters:table = {};
kParameters.propertyName = sPropertyName;
kParameters.value = value;
kParameters.objectID = pObject:GetComponentID();
-- Send this GameEvent when processing the operation
kParameters.OnStart = "OnPlayerCommandSetObjectState";
UI.RequestPlayerOperation(Game.GetLocalPlayer(), PlayerOperations.EXECUTE_SCRIPT, kParameters);
else
-- when you call this function from script thread you send data into gamecore
if (pObject.SetProperty ~= nil) then
pObject:SetProperty(sPropertyName, value);
end
end
end
-- ====================================================================================
-- This function is called from UI thread using function "UI.RequestPlayerOperation" as event
function OnPlayerCommandSetObjectStateHandler(ePlayer : number, params : table)
local pObject = Game.GetObjectFromComponentID(params.objectID);
if pObject ~= nil then
SetObjectState(pObject, params.propertyName, params.value);
end
end
-- This file gets includes on both the UI and GameCore side, we only want to handle the event on the Game Core side.
if UI == nil then
GameEvents.OnPlayerCommandSetObjectState.Add( OnPlayerCommandSetObjectStateHandler );
end
-- ===================================================================================
function GetObjectState(pObject : object, sPropertyName : string, bCacheCheckOnly : boolean)
if (sPropertyName == nil) then
return nil;
end
if (pObject == nil) then
print("StateUtils GetObjectState: ERROR: object is nil!");
return nil;
end
bCacheCheckOnly = bCacheCheckOnly or false;
if (USE_CACHE == true) then
if (g_ObjectStateCache[pObject] == nil) then
g_ObjectStateCache[pObject] = {};
end
if (g_ObjectStateCache[pObject][sPropertyName] ~= nil) then
return g_ObjectStateCache[pObject][sPropertyName];
else
if (bCacheCheckOnly) then
return nil;
else
return RefreshObjectState(pObject, sPropertyName);
end
end
else
return pObject:GetProperty(sPropertyName);
end
end
-- ===========================================================================
-- Forces a call to gamecore and cache update.
function RefreshObjectState(pObject : object, sPropertyName : string)
if (sPropertyName == nil) then
return nil;
end
if (pObject.GetProperty == nil) then
return nil;
end
local propResult = pObject:GetProperty(sPropertyName);
if (g_ObjectStateCache[pObject] == nil) then
g_ObjectStateCache[pObject] = {};
end
g_ObjectStateCache[pObject][sPropertyName] = propResult;
return propResult;
end
-- ===================================================================================
local MilitarizationPerTurn = 0;
local ProjectEncampmentTrainingID = GameInfo.Projects["PROJECT_ENHANCE_DISTRICT_ENCAMPMENT"].Index;
function pPlayerUnitsGetOrLoseMilitarizationYield(iKilledPlayerID, iKilledUnitID, iPlayerID, iUnitID)
local pKilledPlayer = Players[iKilledPlayerID];
local pKilledPlayerConfig = PlayerConfigurations[iKilledPlayerID];
local pKilledUnit = pPlayer:GetUnits():FindID(iKilledUnitID);
local pPlayer = Players[iPlayerID];
local pPlayerConfig = PlayerConfigurations[iPlayerID];
local pUnit = pPlayer:GetUnits():FindID(iUnitID);
if pPlayer:IsAlive() and pPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" and pKilledPlayer:IsAlive() and pKilledPlayerConfig:GetCivilizationTypeName() ~= "CIVILIZATION_GERMANY" then
if pUnit ~= pKilledUnit and UnitManager.Kill(pKilledUnit) then
MilitarizationPerTurn = MilitarizationPerTurn + 1
SetObjectState(pPlayer, g_PropertyKeys.MilitarizationPerTurn, 1)
end
elseif pPlayer:IsAlive() and pPlayerConfig:GetCivilizationTypeName() ~= "CIVILIZATION_GERMANY" and pKilledPlayer:IsAlive() and pKilledPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" then
if pUnit ~= pKilledUnit and UnitManager.Kill(pKilledUnit) then
MilitarizationPerTurn = MilitarizationPerTurn - 1
SetObjectState(pPlayer, g_PropertyKeys.MilitarizationPerTurn, -1)
end
end
end
Events.UnitKilledInCombat.Add(pPlayerUnitsGetOrLoseMilitarizationYield);
function pPlayerLoyaltyLoseMilitarizationYield(iPlayerID, iCityID)
local pPlayer = Players[iPlayerID];
local pPlayerConfig = PlayerConfigurations[iPlayerID];
local pCity = pPlayer:GetCities():FindID(iCityID);
if pPlayer:IsAlive() and pPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" then
if pCity:ChangeLoyalty(-1) then
MilitarizationPerTurn = MilitarizationPerTurn - 1
SetObjectState(pPlayer, g_PropertyKeys.MilitarizationPerTurn, -1)
end
end
end
Events.CityLoyaltyChanged.Add(pPlayerLoyaltyLoseMilitarizationYield);
function pPlayerEncampmentTrainingCompleteGetMilitarizationYield(iPlayerID, iCityID, iProjectID, iBuildingIndex, iX, iY, bCancelled)
local pPlayer = Players[iPlayerID];
local pPlayerConfig = PlayerConfigurations[iPlayerID];
local pCity = pPlayer:GetCities():FindID(iCityID);
if pPlayer:IsAlive() and pPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" then
if iProjectID == ProjectEncampmentTrainingID and bCancelled == false and pCity == pPlayer:GetCities():Members() then
MilitarizationPerTurn = MilitarizationPerTurn + 5
SetObjectState(pPlayer, g_PropertyKeys.MilitarizationPerTurn, 5)
end
end
end
Events.CityProjectCompleted.Add(pPlayerEncampmentTrainingCompleteGetMilitarizationYield);
function pPlayerDeficitLoseMilitarizationYield(iPlayerID, iGoldPerTurn, iCurrentTreasury)
local pPlayer = Players[iPlayerID];
local pPlayerConfig = PlayerConfigurations[iPlayerID];
if pPlayer:IsAlive() and pPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" and iGoldPerTurn < 0 then
MilitarizationPerTurn = MilitarizationPerTurn - 1
SetObjectState(pPlayer, g_PropertyKeys.MilitarizationPerTurn, -1)
end
end
Events.TreasuryChanged.Add(pPlayerDeficitLoseMilitarizationYield);
function pPlayerOnCombat(m_CombatResults)
local attacker = m_CombatResults[CombatResultParameters.ATTACKER]
local defender = m_CombatResults[CombatResultParameters.DEFENDER]
pPlayerMilitarizationBonus(attacker, defender)
pPlayerKillBonus(attacker, defender)
end
Events.Combat.Add(pPlayerOnCombat);
function pPlayerMilitarizationBonus(attacker, defender)
local attackerID = attacker[CombatResultParameters.ID];
local pAttackingPlayer = Players[attackerID.player];
local pAttackingPlayerConfig = PlayerConfigurations[attackerID.player];
local pAttackingPlayerUnits = pAttackingPlayer:GetUnits();
local defenderID = defender[CombatResultParameters.ID];
local pDefendingPlayer = Players[defenderID.player];
local pDefendingPlayerConfig = PlayerConfigurations[defenderID.player];
local pDefendingPlayerUnits = pDefendingPlayer:GetUnits();
local iAttackerCombatStrength = attacker[CombatResultParameters.COMBAT_STRENGTH];
local iDefenderCombatStrength = defender[CombatResultParameters.COMBAT_STRENGTH];
local iAttackerBonus = attacker[CombatResultParameters.STRENGTH_MODIFIER];
local iDefenderBonus = defender[CombatResultParameters.STRENGTH_MODIFIER];
local iPlayerUnitExperienceBonus = 1;
if pAttackingPlayer:IsAlive() and pAttackingPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" then
for i, pAttackingPlayerUnit in pAttackingPlayerUnits:Members() do
for j = 0, MilitarizationPerTurn do
iAttackerBonus = iAttackerBonus + iAttackerCombatStrength * 0.01
pAttackingPlayerUnit:GetExperience():ChangeExperience(iPlayerUnitExperienceBonus)
end
end
elseif pDefendingPlayer:IsAlive() and pDefendingPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" then
for i, pDefendingPlayerUnit in pDefendingPlayerUnits:Members() do
for j = 0, MilitarizationPerTurn do
iDefenderBonus = iDefenderBonus + iDefenderCombatStrength * 0.01
pDefendingPlayerUnit:GetExperience():ChangeExperience(iPlayerUnitExperienceBonus)
end
end
end
end
function pPlayerKillBonus(attacker, defender)
local attackerID = attacker[CombatResultParameters.ID];
local pAttackingPlayer = Players[attackerID.player];
local pAttackingPlayerConfig = PlayerConfigurations[attackerID.player];
local pAttackingPlayerUnits = pAttackingPlayer:GetUnits();
local defenderID = defender[CombatResultParameters.ID];
local pDefendingPlayer = Players[defenderID.player];
local pDefendingPlayerConfig = PlayerConfigurations[defenderID.player];
local pDefendingPlayerUnits = pDefendingPlayer:GetUnits();
local pPlayerEnemyUnitsKillRate = 0;
for i = 0, MilitarizationPerTurn do
pPlayerEnemyUnitsKillRate = pPlayerEnemyUnitsKillRate + 0.1
end
if pAttackingPlayer:IsAlive() and pAttackingPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" then
local pkAttacker = UnitManager.GetUnit(attackerID.player, attackerID.id);
if Automation.GetRandomNumber(100) <= pPlayerEnemyUnitsKillRate then
for i, pDefendingPlayerUnit in pDefendingPlayerUnits:Members() do
pkAttacker.Kill(pDefendingPlayerUnit)
end
end
elseif pDefendingPlayer:IsAlive() and pDefendingPlayerConfig:GetCivilizationTypeName() == "CIVILIZATION_GERMANY" then
local pkDefender = UnitManager.GetUnit(defenderID.player, defenderID.id);
if Automation.GetRandomNumber(100) <= pPlayerEnemyUnitsKillRate then
for i, pAttackingPlayerUnit in pAttackingPlayerUnits:Members() do
pkDefender.Kill(pAttackingPlayerUnit)
end
end
end
end