-- set base values for variables
local BaseAttritionMin,BaseAttritionMax = 1,6
local TerrainAttritionMul,CataChance,TerrainCataMul = 1,10,2
local TerrainAttritionMulLow,TerrainAttritionMulBelowAverage,TerrainAttritionMulAverage,TerrainAttritionMulStrong,TerrainAttritionMulHuge = 10,15,20,35,60
local CataChanceLow,CataChanceAverage,CataChanceAboveAverage,CataChanceStrong,CataChanceHuge = 150,250,350,500,800
local TerrainCataMulLow,TerrainCataMulBelowAverage,TerrainCataMulAverage,TerrainCataMulStrong,TerrainCataMulHuge = 2,3,5,8,15
function damageAndDestroyUnit(pPlayer,iUnit,minDam,maxDam)
local tKillUnits = {}
local pPlayerToCheck = Players[pPlayer]
local pUnits = pPlayerToCheck:GetUnits()
local pUnit = pUnits:FindID(iUnit)
local pPlayerEra = pPlayerToCheck:GetEra()+1
if (pUnit ~= nil) and (pUnit:IsDead() == false) and (pUnit:IsDelayedDeath() == false) then
local UnitPlot = Map.GetPlot(pUnit:GetX(), pUnit:GetY())
local UnitPlotOwner = UnitPlot:GetOwner()
if (UnitPlot ~= nil) and (UnitPlotOwner ~= pPlayer) then
local unitDamage = math.random(minDam,maxDam)
if (pUnit:GetDamage() + unitDamage) >= 200 then
table.insert(tKillUnits, pUnit)
else
pUnit:ChangeDamage(unitDamage)
print("inflicted "..unitDamage.." to unit")
print("Player is "..UnitPlotOwner.." ID")
print("player era is "..pPlayerEra.." era")
end
end
end
--now we've completed the iteration through table pUnits:Members() and can safely delete units listed as members
for k,pUnit in ipairs(tKillUnits) do
pUnits:Destroy(pUnit)
print("a unit was destroyed because of attrition")
end
end
function eraModifier(era, TerrainAttritionMul,CataChance,TerrainCataMul)
if era == "1" then
TerrainAttritionMul = TerrainAttritionMul+30
CataChance = CataChance+150
TerrainCataMul = TerrainCataMul+10
elseif era == "2" then
TerrainAttritionMul = TerrainAttritionMul+25
CataChance = CataChance*150
TerrainCataMul = TerrainCataMul+10
elseif era == "3" then
TerrainAttritionMul = TerrainAttritionMul+10
CataChance = CataChance*100
TerrainCataMul = TerrainCataMul+5
elseif era == "4" then
TerrainAttritionMul = TerrainAttritionMul+10
CataChance = CataChance*75
TerrainCataMul = TerrainCataMul+3
elseif era == "5" then
TerrainAttritionMul = TerrainAttritionMul
CataChance = CataChance
TerrainCataMul = TerrainCataMul
elseif era == "6" then
TerrainAttritionMul = TerrainAttritionMul
CataChance = CataChance*0.5
TerrainCataMul = TerrainCataMul
elseif era == "7" then
TerrainAttritionMul = TerrainAttritionMul*0.5
CataChance = CataChance*0.25
TerrainCataMul = TerrainCataMul*0.5
elseif era == "8" then
TerrainAttritionMul = TerrainAttritionMul*0.25
CataChance = CataChance*0.1
TerrainCataMul = TerrainCataMul*0.05
elseif era == "9" then
TerrainAttritionMul = TerrainAttritionMul*0
CataChance = CataChance*0
TerrainCataMul = TerrainCataMul*0
end
return TerrainAttritionMul,CataChance,TerrainCataMul
end
function getDamageFromTerrains(tTerrain)
if string.find(tTerrain, "MOUNTAIN") then
TerrainAttritionMul = TerrainAttritionMulHuge
CataChance = CataChanceHuge
TerrainCataMul = TerrainCataMulHuge
elseif tTerrain == "TERRAIN_OCEAN" then
TerrainAttritionMul = TerrainAttritionMulAverage
CataChance = CataChanceHuge
TerrainCataMul = TerrainCataMulHuge
elseif (string.find(tTerrain, "DESERT") or string.find(tTerrain, "TUNDRA") or string.find(tTerrain, "SNOW")) then
TerrainAttritionMul = TerrainAttritionMulStrong
CataChance = CataChanceAverage
TerrainCataMul = TerrainCataMulHuge
elseif tTerrain == "TERRAIN_COAST" then
TerrainAttritionMul = TerrainAttritionMulBelowAverage
CataChance = CataChanceAverage
TerrainCataMul = TerrainCataMulAverage
else
TerrainAttritionMul = TerrainAttritionMulLow
CataChance = CataChanceLow
TerrainCataMul = TerrainCataMulLow
end
return TerrainAttritionMul,CataChance,TerrainCataMul
end
function getDamageFromFeatures(plotFeature)
if plotFeature == "FEATURE_ICE" then
TerrainAttritionMul = TerrainAttritionMulStrong
CataChance = CataChanceHuge
TerrainCataMul = TerrainCataMulHuge
elseif plotFeature == "FEATURE_MARSH" then
TerrainAttritionMul = TerrainAttritionMulStrong
CataChance = CataChanceHuge
TerrainCataMul = TerrainCataMulAverage
elseif plotFeature == "FEATURE_BARRIER_REEF" then
TerrainAttritionMul = TerrainAttritionMullow
CataChance = CataChanceStrong
TerrainCataMul = TerrainCataMulHuge
elseif plotFeature == "FEATURE_JUNGLE" then
TerrainAttritionMul = TerrainAttritionMulAverage
CataChance = CataChanceAverage
TerrainCataMul = TerrainCataMulStrong
elseif plotFeature == "FEATURE_FOREST" then
TerrainAttritionMul = TerrainAttritionMulBelowAverage
CataChance = CataChanceAverage
TerrainCataMul = TerrainCataMulStrong
elseif plotFeature == "FEATURE_OASIS" then
TerrainAttritionMul = 0
CataChance = CataChanceAverage
TerrainCataMul = TerrainCataMulAverage
end
return TerrainAttritionMul,CataChance,TerrainCataMul
end
function Attrition(PlayerID,UnitID,UnitX,UnitY)
local experienceFromCata = false
local feedBack = false
local pPlayerToCheck = Players[PlayerID]
local PlayerEra = pPlayerToCheck:GetEra()+1
-- give feedback only to player
if PlayerID == 0 then feedBack = true end
-- set values for terrains
local plotToCheck = Map.GetPlot(UnitX,UnitY)
local tTerrain = GameInfo.Terrains[plotToCheck:GetTerrainType()].TerrainType
TerrainAttritionMul,CataChance,TerrainCataMul = getDamageFromTerrains(tTerrain)
-- check features. Takes precedence on terrain.
if plotToCheck:GetFeatureType() > -1 then
local plotFeature = GameInfo.Features[plotToCheck:GetFeatureType()].FeatureType
TerrainAttritionMul,CataChance,TerrainCataMul = getDamageFromFeatures(plotFeature)
end
--Era check
TerrainAttritionMul,CataChance,TerrainCataMul = eraModifier(playerEra, TerrainAttritionMul,CataChance,TerrainCataMul)
-- check cata chance
if math.random(1,1000) <= CataChance then
experienceFromCata = true
TerrainAttritionMul = TerrainCataMul
if feedBack then
Game.AddWorldViewText(0, "A catastrophe happened to this unit while moving", UnitX, UnitY, 0)
end
end
-- reduce attrition and cata chance if road on plot.
if plotToCheck:GetRouteType() > -1 then
print("There is a route here, so much less attrition.")
CataChance = CataChance/5
TerrainCataMul = 1
TerrainAttritionMul = TerrainAttritionMul*0.2
end
-- check chance to create a road when a unit moves
local roadCheckAllowed = true
if tTerrain == "TERRAIN_COAST" or "TERRAIN_OCEAN" then
roadCheckAllowed = false
end
if roadCheckAllowed then
local chanceToCreateRoad = math.random(1,1000)
if chanceToCreateRoad <= 75 then
if feedBack then
Game.AddWorldViewText(0, "Your unit found and marked some easy path while moving here.", UnitX, UnitY, 0)
end
WorldBuilder.MapManager():SetRouteType( plotToCheck,GameInfo.Routes["ROUTE_ANCIENT_ROAD"].Index, false )
end
end
-- deal damages
local FinalAttritionMin = BaseAttritionMin*TerrainAttritionMul
local FinalAttritionMax = BaseAttritionMax*TerrainAttritionMul
damageAndDestroyUnit(PlayerID,UnitID,FinalAttritionMin,FinalAttritionMax)
-- give XP if a cata happens.
if experienceFromCata then
local pPlayerToCheck = Players[PlayerID]
local pUnits = pPlayerToCheck:GetUnits()
for i, pUnit in pUnits:Members() do
if(tostring(pUnit:GetID()) == tostring(UnitID)) then
local currentXP = pUnit:GetExperience()
local currentXPPoints = currentXP:GetExperiencePoints()+5
--currentXPPoints = currentXPPoints+5
local experienceChangeAmount = math.random((FinalAttritionMin/10)+1,(FinalAttritionMax/10)+1)
currentXP:ChangeExperience(experienceChangeAmount)
end
end
end
end
function CheckIdleDamage()
local players = Game.GetPlayers()
for k, pPlayer in ipairs (players) do
local pUnits = pPlayer:GetUnits()
for i, pUnit in pUnits:Members() do
local iUnitX, iUnitY = pUnit:GetX(), pUnit:GetY()
local pPlot = Map.GetPlot(iUnitX, iUnitY)
local tTerrain = GameInfo.Terrains[pPlot:GetTerrainType()].TerrainType
TerrainAttritionMul,CataChance,TerrainCataMul = getDamageFromTerrains(tTerrain)
if pPlot:GetFeatureType() >-1 then
local fFeature = GameInfo.Features[pPlot:GetFeatureType()].FeatureType
TerrainAttritionMul,CataChance,TerrainCataMul = getDamageFromFeatures(fFeature)
end
local PlayerID = pPlayer:GetID()
local UnitID = pUnit:GetID()
local FinalAttritionMin = (BaseAttritionMin*TerrainAttritionMul)/2
local FinalAttritionMax = (BaseAttritionMax*TerrainAttritionMul)/2
damageAndDestroyUnit(PlayerID,UnitID,FinalAttritionMin,FinalAttritionMax)
end
end
end
Events.TurnEnd.Add(CheckIdleDamage)
Events.UnitMoved.Add(Attrition)