Shades of Gray
Consul
- Joined
- Apr 12, 2011
- Messages
- 64
Hey everyone,
I am working on a mod that changes the ability of the Kremlin to a "General Winter" of sorts where enemy units lose 10 health per turn while in the owner of the Kremlin's land. Requires to be built in or next to Tundra to give a little bonus to those stuck up in the icy wastes.
I'm pretty decent at XML, but am still sort of fumbling around with Lua, without much luck.
What I have currently is:
I have been experimenting with it a bit more and here is what I have now, but I still am having trouble getting it to work.
Looking at the logs, the error is at line 37:
lua:37: attempt to call field 'getOwner' (a nil value)
Removing that troublesome line just to see what would happen (and changing the way the damage is dealt since I was having trouble with it working) I come up with
Now the issue with the changes is that it harms units (friendly and not) in the borders and, for some reason, only hits a single unit with the damage. I had 4 units inside the borders, yet only the "first" was harmed.
So I guess the primary issues I am having is how to limit the damage to only those at war with and expand it to all enemy units, instead of just the first.
And for my third attempt, because three times is apparently not the charm, I decided to try and separate each variable in its own function... With little success:
Firetuner returns a runtime error at line 34: attempt to index 'playerKremlinOwner' (a nil value)
I'm not sure where it isn't defined :/
Any help with this would be greatly appreciated. As would any that point out issues with the current code that I have started.
I am working on a mod that changes the ability of the Kremlin to a "General Winter" of sorts where enemy units lose 10 health per turn while in the owner of the Kremlin's land. Requires to be built in or next to Tundra to give a little bonus to those stuck up in the icy wastes.
I'm pretty decent at XML, but am still sort of fumbling around with Lua, without much luck.
What I have currently is:
Spoiler :
Code:
--Figure out who has the Kremlin
function GetPlayerWithKremlin()
local playerWithKremlin = nil;
local buildingClassId = GameInfo.BuildingClasses["BUILDINGCLASS_KREMLIN"].ID;
for playerNum = 0, GameDefines.MAX_CIV_PLAYERS - 1 do
local player = Players[playerNum];
local buildingCount = player:GetBuildingClassCount(buildingClassId);
if buildingCount > 0 then
playerWithKremlin = player;
break;
end
end
return playerWithKremlin
end
--General Winter Strikes
function KremlinGeneralWinter(iPlayer, iUnitID, iX, iY)
if iPlayer ~= nil then
local playerWithKremlin = GetPlayerWithKremlin();
--If the Kremlin has not yet been built
if playerWithKremlin == nil then
return;
end
local unit = Players[ iPlayer ]:GetUnitByID( iUnitID );
--To check if the player is at war with Kremlin Owner
if unit ~= nil and playerWithKremlin.isAtWar(unit.getOwner()) then
local plot = unit:GetPlot();
if plot:GetOwner() == playerWithKremlin:GetID() then
--Time for General Winter Damage
local GeneralWinterDamage = unit:GetCurrHitPoints() -10
local damage = unit:GetDamage();
if GeneralWinterDamage > 0 then
Unit:SetDamage(10)
else
Unit:Kill(true, -1)
end
--Alert Human player of the General Winter's effect
local activePlayer = Players[Game.GetActivePlayer()];
if activePlayer:IsHuman() then
local header = Locale.ConvertTextKey("TXT_KEY_GENERAL_WINTER_NOTIFICATION_HEADER", playerWithKremlin:GetName());
local message = Locale.ConvertTextKey("TXT_KEY_GENERAL_WINTER_NOTIFICATION_BODY", playerWithKremlin:GetName());
print(message);
activePlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, message, header, iX, iY);
end
end
end
end
end
GameEvents.PlayerDoTurn.Add(KremlinGeneralWinter)
I have been experimenting with it a bit more and here is what I have now, but I still am having trouble getting it to work.
Looking at the logs, the error is at line 37:
Code:
if unit ~= nil and playerWithKremlin.isAtWar(unit.getOwner()) then
Removing that troublesome line just to see what would happen (and changing the way the damage is dealt since I was having trouble with it working) I come up with
Code:
--Figure out who has the Kremlin
function GetPlayerWithKremlin()
local playerWithKremlin = nil;
local buildingClassId = GameInfo.BuildingClasses["BUILDINGCLASS_KREMLIN"].ID;
for playerNum = 0, GameDefines.MAX_CIV_PLAYERS - 1 do
local player = Players[playerNum];
local buildingCount = player:GetBuildingClassCount(buildingClassId);
if buildingCount > 0 then
playerWithKremlin = player;
break;
end
end
return playerWithKremlin
end
gGeneralWinterDamage = 10;
--General Winter Strikes
function KremlinGeneralWinter(iPlayer, iUnitID, iX, iY)
if iPlayer ~= nil then
local playerWithKremlin = GetPlayerWithKremlin();
--If the Kremlin has not yet been built
if playerWithKremlin == nil then
--print("The Kremlin does not exist yet");
return;
end
local unit = Players[ iPlayer ]:GetUnitByID( iUnitID );
--To check if the player is at war with Kremlin Owner
if unit ~= nil then
local plot = unit:GetPlot();
if plot:GetOwner() == playerWithKremlin:GetID() then
--Time for General Winter Damage
local hitPoints = unit:GetCurrHitPoints();
local damage = unit:GetDamage();
unit:SetDamage(damage + gGeneralWinterDamage);
--Alert Human player of the General Winter's effect
local activePlayer = Players[Game.GetActivePlayer()];
if activePlayer:IsHuman() then
local header = Locale.ConvertTextKey("TXT_KEY_GENERAL_WINTER_NOTIFICATION_HEADER", playerWithKremlin:GetName());
local message = Locale.ConvertTextKey("TXT_KEY_GENERAL_WINTER_NOTIFICATION_BODY", playerWithKremlin:GetName());
print(message);
activePlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, message, header, iX, iY);
end
end
end
end
end
GameEvents.PlayerDoTurn.Add(KremlinGeneralWinter)
Now the issue with the changes is that it harms units (friendly and not) in the borders and, for some reason, only hits a single unit with the damage. I had 4 units inside the borders, yet only the "first" was harmed.
So I guess the primary issues I am having is how to limit the damage to only those at war with and expand it to all enemy units, instead of just the first.
And for my third attempt, because three times is apparently not the charm, I decided to try and separate each variable in its own function... With little success:
Spoiler :
Code:
--Figure out who has the Kremlin
function GetPlayerWithKremlin()
local playerWithKremlin = nil;
local buildingClassId = GameInfo.BuildingClasses["BUILDINGCLASS_KREMLIN"].ID;
if playerWithKremlin == nil then
for playerID = 0, GameDefines.MAX_CIV_PLAYERS - 1 do
local player = Players[playerID];
if (player:IsAlive() and player:GetCivilizationType() == civilisationID) then
local buildingCount = player:GetBuildingClassCount(buildingClassId);
if buildingCount > 0 then
playerWithKremlin = playerID;
break;
end
end
end
end
return playerWithKremlin
end
--Time to check for war
local playerWithKremlin = GetPlayerWithKremlin();
function GeneralWinter_IsPlayerAtWarWithKremlin(playerID)
local isAtWarwithKremlin = false
if playerID ~= playerWithKremlin then
local player = Players[playerID]
local playerKremlinOwner = Players[playerWithKremlin]
if Teams[player:GetTeam()]:IsAtWar(playerKremlinOwner:GetTeam()) then
isAtWarWithKremlin = true
end
return isAtWarWithKremlin
end
end
--Are you in Kremlin lands?
function GeneralWinter_IsthePlotKremlinOwned(Plot)
local isPlotKremlinOwned = false
if plot:GetOwner() > -1 then
local player = Players[plot:GetOwner()]
if player == playerWithKremlin then
isPlotKremlinOwned = true
end
end
return isPlotKremlinOwned
end
gGeneralWinterDamage = 10;
--General Winter
function KremlinGeneralWinter(playerID, unitID, unitX, unitY)
local player = Players[playerID]
if (player:IsAlive() and GeneralWinter_IsPlayerAtWarWithKremlin(playerID)) then
local isPlotKremlinOwned = false
local unit = player:GetUnitByID(unitID)
local plot = unit:GetPlot()
if (plot and (plot:GetOwner() == playerWithKremlin)) then
isPlotKremlinOwned = true
end
if isPlotKremlinOwned then
--Time for General Winter Damage
local hitPoints = unit:GetCurrHitPoints();
local damage = unit:GetDamage();
unit:SetDamage(damage + gGeneralWinterDamage);
--Alert Human player of the General Winter's effect
local activePlayer = Players[Game.GetActivePlayer()];
if activePlayer:IsHuman() then
local header = Locale.ConvertTextKey("TXT_KEY_GENERAL_WINTER_NOTIFICATION_HEADER", playerWithKremlin:GetName());
local message = Locale.ConvertTextKey("TXT_KEY_GENERAL_WINTER_NOTIFICATION_BODY", playerWithKremlin:GetName());
print(message);
activePlayer:AddNotification(NotificationTypes.NOTIFICATION_GENERIC, message, header, iX, iY);
end
end
end
end
GameEvents.PlayerDoTurn.Add(KremlinGeneralWinter)
I'm not sure where it isn't defined :/
Any help with this would be greatly appreciated. As would any that point out issues with the current code that I have started.