AW Arcaeca
Deus Vult
Can't find it on the UI reference. :/ What parameters does it pass?
Also, do you know if it's G&K-compatible?
Also, do you know if it's G&K-compatible?
GameEvents.UnitPrekill.Add(
function(iOwner, iUnit, iUnitType, iX, iY, bDelay, iKiller)
print("")
print("GameEvents.UnitPrekill("..tostring(iOwner)..", "..tostring(iUnit)..", "..tostring(iUnitType)..", "..tostring(iX)..", "..tostring(iY)..", "..tostring(bDelay)..", "..tostring(iKiller)..")")
if (iKiller < 0) then return end -- this is so that it's not impossible to manually delete your unit - I learned the hard way that this needs to be here :P
if (iUnitType == GameInfoTypes.UNIT_AW_UNIT) then return end
local pPlayer = Players[iOwner]
local pUnit = pPlayer:GetUnitByID(iUnit)
if not bDelay then
print("Trying to resurrect the unit")
print("Identifying resurrectable properties;")
-- INDENTIFY PROMOTIONS --
local tPromotions = {}
for row in GameInfo.UnitPromotions() do if (pUnit:IsHasPromotion(row.ID)) then table.insert(tPromotions, row.ID) end end -- Have fun reading that :p
-- FIND EXPERIENCE
local iExperience = pUnit:GetExperience() + GameInfo.Units[GameInfoTypes.UNIT_AW_UNIT].XPValueDefense
-- RESURRECT UNIT --
print("Resurrecting unit;")
local pNewUnit = pPlayer:InitUnit(GameInfoTypes.UNIT_AW_UNIT, iX, iY)
pNewUnit:SetExperience(iExperience)
for k,v in pairs(tPromotions) do pMetsikhovne:SetHasPromotion(v, true) end
print("unit brought back from the brink of death!")
Events.GameplayAlertMessage("Invincible HAXX0R unit saved by the power of illuminarty")
else -- find the killer and whisk them off the plot (heaven forbid that we should move)
print("Firing to move the heathen enemy unit;")
for mUnit in Players[iKiller]:Units() do
if (mUnit:GetPlot() == Map.GetPlot(iX, iY)) then
MoveUnitBackwards(mUnit)
print("Heathen enemy unit moved back!")
end
end
end
end)
function MoveUnitBackwards(pUnit, numTiles)
if (numTiles == nil) then numTiles = 1 end
local iFacingDirection = pUnit:GetFacingDirection()
-- so we need to find the opposite direction of that; that's the direction we want to move the unit
local iDirectionChange = math.ceil(DirectionTypes.NUM_DIRECTION_TYPES / 2)
local iDirectionToMove = iFacingDirection - iDirectionChange
if (iDirectionToMove < 0) then -- whoops! We screwed this up and subtracted when we should've added
iDirectionToMove = iDirectionToMove + (2 * iDirectionChange)
end
-- so now we have the opposite direction, now we need to figure out the target tile
-- so I guess I'll find the adjacent tile, and then if numTiles > 1, find that adjacent tile, and if numTiles > 2, find the next adjacent tile...
local pPlot = pUnit:GetPlot()
local iX = pPlot:GetX()
local iY = pPlot:GetY()
local toPlot
for i = 0, numTiles, 1 do
toPlot = Map.PlotDirection(iX, iY, iDirectionToMove)
iX = toPlot:GetX()
iY = toPlot:GetY()
end
pUnit:SetXY(iX, iY)
end
local tPromotions = {}
for row in GameInfo.UnitPromotions() do if (pUnit:IsHasPromotion(row.ID)) then table.insert(tPromotions, row.ID) end end -- Have fun reading that :p
local iLevel = pUnit:GetLevel()
local iExperience = pUnit:GetExperience() + GameInfo.Units[GameInfoTypes.UNIT_AW_UNIT].XPValueDefense
local pNewUnit = pPlayer:InitUnit(GameInfoTypes.UNIT_AW_UNIT, iX, iY)
[COLOR="Blue"]pNewUnit:JumpToNearestValidPlot()[/COLOR]
pNewUnit:SetExperience(iExperience)
pNewUnit:SetLevel(iLevel)
for k,v in pairs(tPromotions) do pNewUnit:SetHasPromotion(v, true) end
print("unit brought back from the brink of death!")
"pMetsikhovne" is just the name of the variable that I renamed to pNewUnit for the purpose of posting this code here. Redaction, you know. Secrecy. Looks I missed one though. :/without looking into anything else, there's a problem right here: "pMetsikhovne:SetHasPromotion(v, true)". This is undefined so far as I can see: pMetsikhovne.
I'm wary of Unit.JumpToNearestValidPlot(). During an earlier test, I believe that line was somewhere in the code, and my unit got teleported some ridiculous number of tiles away and, surprise! I suddenly meet Shaka because my unit died. Plot jumping makes weird things happen.Don't try to recreate the 'killed' unit on the same plot as this is bound to have troubles, just shift the resurrected unit to the nearest valid plot.
If you want to you can then reposition the enemy unit that occupied the original tile, and re-position pNewUnit to the original tile where it was positioned, and then re-re-position the enemy unit.Code:local tPromotions = {} for row in GameInfo.UnitPromotions() do if (pUnit:IsHasPromotion(row.ID)) then table.insert(tPromotions, row.ID) end end -- Have fun reading that :p local iLevel = pUnit:GetLevel() local iExperience = pUnit:GetExperience() + GameInfo.Units[GameInfoTypes.UNIT_AW_UNIT].XPValueDefense local pNewUnit = pPlayer:InitUnit(GameInfoTypes.UNIT_AW_UNIT, iX, iY) [COLOR="Blue"]pNewUnit:JumpToNearestValidPlot()[/COLOR] pNewUnit:SetExperience(iExperience) pNewUnit:SetLevel(iLevel) for k,v in pairs(tPromotions) do pNewUnit:SetHasPromotion(v, true) end print("unit brought back from the brink of death!")
IntendedThe other thing you are not doing is setting any damage to pNewUnit, so not only does it get resurrected, it gets returned to 100% health.
So then... this line should've spit out an error:
- iKiller will be the ID # of the victorious player only when bDelay is true (edit: and there was actual combat)
[*]iKiller will be '-1' when bDelay is false- the only way that iKiller can be '-1' and bDelay can be true is if you kill off your own unit, for example, use a settler to create a city.
- the only way that bDelay can be false and iKiller can be anything except '-1' is if a Barb (for example) kills off a civilian unit. It is the civilian unit that is the key to the behavior in this case.
for mUnit in Players[iKiller]:Units() do
I guess then I would have to have a variable outside of the function that stores the value of iKiller when bDelay = true...You actually need to run your code when bDelay is 'false' and when 'iKiller' is '-1', because then all units seen under the event as being 'on the plot' will still give valid data, including the unit that is 'dead', as well as any civilian units that were on the plot and under the protection of the defeated unit. Plus, the game is not still in the process of killing off the defeated unit, which it still is in the method you are employing.
"pMetsikhovne" is just the name of the variable that I renamed to pNewUnit for the purpose of posting this code here. Redaction, you know. Secrecy. Looks I missed one though. :/
I'm wary of Unit.JumpToNearestValidPlot(). During an earlier test, I believe that line was somewhere in the code, and my unit got teleported some ridiculous number of tiles away and, surprise! I suddenly meet Shaka because my unit died. Plot jumping makes weird things happen.
Intended
So then... this line should've spit out an error:
Because there is no player #-1. But if it never spit out an error, then it must be because it never reached that line... because why?Code:for mUnit in Players[iKiller]:Units() do
I guess then I would have to have a variable outside of the function that stores the value of iKiller when bDelay = true...
So:
When bDelay = true and 0 <= iKiller <= GameDefines.MAX_MAJOR_CIVS, retrieve iKiller and store outside the function[/INDENT]
Else: move the killer unit THEN proceed to resurrect the dead unit
Should that work, or have I still misunderstood something?
if (iKiller < 0) then return end
So you'll need a variable outside of the UnitPreKill event that stores this info, which you then stick the 'iKiller' data info when bDelay it true, read back out of when bDelay is false, and then set back to some form of 'nil' value as soon as your code has completed running when bDelay is false.
GameEvents.UnitPrekill.Add(
function(iOwner, iUnit, iUnitType, iX, iY, bDelay, iKiller)
print("")
print("GameEvents.UnitPrekill("..tostring(iOwner)..", "..tostring(iUnit)..", "..tostring(iUnitType)..", "..tostring(iX)..", "..tostring(iY)..", "..tostring(bDelay)..", "..tostring(iKiller)..")")
if (iKiller < 0) then return end -- this is so that it's not impossible to manually delete your unit - I learned the hard way that this needs to be here :P
if (iUnitType [B][COLOR="Red"]==[/COLOR][/B] GameInfoTypes.UNIT_AW_UNIT) then return end
local pPlayer = Players[iOwner]
local pUnit = pPlayer:GetUnitByID(iUnit)
if not bDelay then
print("Trying to resurrect the unit")
print("Identifying resurrectable properties;")
-- INDENTIFY PROMOTIONS --
local tPromotions = {}
for row in GameInfo.UnitPromotions() do if (pUnit:IsHasPromotion(row.ID)) then table.insert(tPromotions, row.ID) end end -- Have fun reading that :p
-- FIND EXPERIENCE
local iExperience = pUnit:GetExperience() + GameInfo.Units[GameInfoTypes.UNIT_AW_UNIT].XPValueDefense
-- RESURRECT UNIT --
print("Resurrecting unit;")
local pNewUnit = pPlayer:InitUnit(GameInfoTypes.UNIT_AW_UNIT, iX, iY)
pNewUnit:SetExperience(iExperience)
for k,v in pairs(tPromotions) do pMetsikhovne:SetHasPromotion(v, true) end
print("unit brought back from the brink of death!")
Events.GameplayAlertMessage("Invincible HAXX0R unit saved by the power of illuminarty")
else -- find the killer and whisk them off the plot (heaven forbid that we should move)
print("Firing to move the heathen enemy unit;")
for mUnit in Players[iKiller]:Units() do
if (mUnit:GetPlot() == Map.GetPlot(iX, iY)) then
MoveUnitBackwards(mUnit)
print("Heathen enemy unit moved back!")
end
end
end
end)
But looking at the logs, nothing seems to be nesting.
local tFollowers = {}
for row in GameInfo.Religions() do
tFollowers[row.ID] = pCity:GetNumFollowers(row.ID)
end
--this transfers City States and their units to Northumbria at the acquisition of a certain technology
function OnTechNorthumbriaResearched(team, tech, change)
local NorthumbriaTeam
local NorthumbriaTeamID
local DeiraTeam
local DeiraTeamID
local Northumbria
local Deira
local iNorthumbria
-- Set up Northumbria Player
for iPlayer=0, GameDefines.MAX_MAJOR_CIVS-1 do
local pNorthumbria = Players[iPlayer]
if (GameInfo.Civilizations.CIVILIZATION_RUSSIA.ID == pNorthumbria:GetCivilizationType()) then
Northumbria = pNorthumbria
NorthumbriaTeamID = Northumbria:GetTeam();
NorthumbriaTeam= Teams[ Northumbria:GetTeam() ]
iNorthumbria = iPlayer
end
end
-- Set up Deira Player
for iPlayer=GameDefines.MAX_MAJOR_CIVS, GameDefines.MAX_CIV_PLAYERS-1, 1 do
local pDeira = Players[iPlayer]
if (GameInfo.MinorCivilizations.MINOR_CIV_DEIRA.ID == pDeira:GetMinorCivType()) then
Deira = pDeira
DeiraTeamID = Deira:GetTeam();
DeiraTeam= Teams[ Deira:GetTeam() ]
end
end
--local pPlayerTeam
if (tech == (GameInfoTypes["TECH_NOBILITY"])) and team == NorthumbriaTeamID and Deira:IsAlive() and Deira:IsAllies(iNorthumbria) then
-- Find Deira Units
for unit in Deira:Units() do
pUnit = unit
pNewOwner = Northumbria
convertUnitOwner(pUnit, pNewOwner)
end
--convert Deira Cities
for pCity in Deira:Cities() do
if pCity ~= nil then
print("Transferring...", pCity:GetName(), "to" , Northumbria:GetName(), "from", Deira:GetName() )
Northumbria:AcquireCity(pCity, false, true)
pCity:DoTask(TaskTypes.TASK_UNRAZE);
end
end
end
end
GameEvents.TeamTechResearched.Add(OnTechNorthumbriaResearched);
-- Convert Units
function convertUnitOwner(pUnit, pNewOwner)
print(string.format("convertUnit(%s, %s)", pUnit:GetName(), pNewOwner:GetName()))
local pNewUnit = pNewOwner:InitUnit(pUnit:GetUnitType(), pUnit:GetX(), pUnit:GetY())
pNewUnit:SetOriginalOwner(pUnit:GetOwner());
pNewUnit:SetDamage(pUnit:GetDamage())
pNewUnit:SetExperience(pUnit:GetExperience())
pNewUnit:SetLevel(pUnit:GetLevel())
for unitPromotion in GameInfo.UnitPromotions() do
local iPromotionID = unitPromotion.ID;
if (pUnit:IsHasPromotion(iPromotionID)) then
if (pNewUnit:IsPromotionValid(iPromotionID)) then
pNewUnit:SetHasPromotion(iPromotionID, true)
end
end
end
return pNewUnit
end
I might, um, not have known that that function existed.
...well, it obsoletes a day of coding, but if it works...
Although, what's the convertUnitOwner function? Is that basically the unit equivalent of what I've so far been doing for cities?
Also: In my mod the UU can be expended to construct a unique improvement. Or, is supposed to be, anyway - the improvement shows up in the unit panel as buildable, but upon pressing the button... the first clue that something is wrong is that neither the unit dies nor does an improvement show up.
If anyone wants to take a look, the mod is here --> https://www.dropbox.com/s/jp23t9yx0itf2vv/AW's Improvement Gone All Screwy Mod (v 1).zip?dl=0
function OnCaptureCityClick()
if IGE.currentPlayerID ~= currentCity:GetOwner() then
local pPlayer = Players[IGE.currentPlayerID];
pPlayer:AcquireCity(currentCity);
end
InvalidateCity();
end
Controls.CaptureCityButton:RegisterCallback(Mouse.eLClick, OnCaptureCityClick);
function ConvertState(state, sourceID, targetID, toConvert)
-- Enough people from that other religion?
local converted = toConvert
if state[sourceID] < toConvert then
converted = state[sourceID]
end
state[sourceID] = state[sourceID] - converted;
state[targetID] = state[targetID] + converted;
return toConvert - converted;
end
function SetFollowers(religionID, num)
local current = currentCity:GetNumFollowers(religionID);
if (num == current) then return end
-- Get followers state
local count = 0;
local state = {}
for _, v in pairs(data.religions) do
state[v.ID] = currentCity:GetNumFollowers(v.ID);
count = count + state[v.ID];
end
state[-1] = currentCity:GetPopulation() - count;
--print("Converting...");
--PrintReligionState(state);
if num < current then
-- Convert to atheists
ConvertState(state, religionID, -1, current - num);
else
local toConvert = num - current;
-- Convert from atheists
toConvert = ConvertState(state, -1, religionID, toConvert)
-- Convert from pantheon
toConvert = ConvertState(state, 0, religionID, toConvert)
-- Convert from group with max followers, one at a time
while toConvert > 0 do
local maxFollowers = 0;
local sourceID = -1;
for _, v in pairs(data.religions) do
if v.ID ~= religionID and v.ID > 0 then
if state[v.ID] > maxFollowers then
sourceID = v.ID;
maxFollowers = state[v.ID];
end
end
end
if sourceID == -1 then break end
if ConvertState(state, sourceID, religionID, 1) == 0 then
toConvert = toConvert - 1;
end
end
end
SetReligionState(state);
preserveSortOrder = true;
LuaEvents.IGE_Update();
Events.SerialEventCityInfoDirty();
end
function SetReligionState(state)
PrintReligionState(state);
-- What is the majority?
local maxFollowers = -1;
local majority = -1;
for i in pairs(state) do
state[i] = math.floor(state[i] + 0.5)
if state[i] > maxFollowers then
majority = i;
maxFollowers = state[i]
end
end
-- EDIT: Those crashes may actually have only been caused by tests with a religion not founded yet. Doesn't matter, leave the code like that
-- ConvertPercentFollowers is full of nasty bugs (can only convert from majority to minority) hence this twisted method
currentCity:AdoptReligionFully(majority);
print("Done fully adopting")
for i, v in pairs(state) do
if i ~= majority and i >= 0 then
-- Convert 1% at a time because followers are internally stored as real numbers.
while (currentCity:GetNumFollowers(i) + 0.5) < v do
currentCity:ConvertPercentFollowers(i, majority, 1)
end
end
end
print("Done increasing minorities.")
-- We do atheists in the end because of a rounding error in civ5 (sum of followers can be population + 1)
-- Since they're never displayed, we actually use the majority as a loop condition.
if majority >= 0 then
while (currentCity:GetNumFollowers(majority) - 0.5) > state[majority] do
currentCity:ConvertPercentFollowers(-1, majority, 1)
end
end
print("Done lowering majority.")
end