Civ V Corpse Decay Mod

adreal

Chieftain
Joined
Oct 7, 2015
Messages
7
I've never seen a mod that altered how long corpses stay on the ground before vanishing. Personally, I like to see hundreds of soldiers marching off to war in neat array and then beating each other senseless in a free-for-all with ensuing carnage that litters the ground in a corpse-ridden, smoldering aftermath. But with the way Civ V currently handles warfare the land looks relatively unstained by the blemishes of war.

So is there a mod out there that slows corpse decay? If not, I propose a mod with the following features:

1. Permanent corpses: units lie however and wherever they fell in battle.
2. Corpses can be cleaned up with a clean pollution or similar function by workers.
3. When corpses are cleared off of terrain, it yields a small amount of gold (since essentially you are recycling the metal of burned-out tanks, reusing uniforms and rifles, etc.). Rationalize it however you wish. But this gives the AI and players a practical reason to tidy their lands and bury their dead.
 
Sure. If you can spare 64GB of RAM :)

You have to admit - and I'm grateful that you already have - that you would want to play this sort of mod. Anyone who's played the Total War series knows what I'm talking about. Why doesn't that series just make all of the corpses instantly vanish after they fall? Because that would be asinine, less realistic and less interesting. Are we a bunch of overprotective mothers or six year-olds that are offended by pixelated corpses?

We both know that the idea would make the game more interesting and more immersive, which is what good modding is about. If it's CPU requirements that you're worried about, then consider these options:

1. Include a statement that the gameplay for this mod is best for smaller maps.
2. Include a dynamic that automatically garbage cleans the corpses from the world's terrain 20 turns after each has fallen or, in general, every 20 turns.
3. Make it so whatever fresh batch of corpses falls on a certain tile of land automatically replaces the previous batch that was lying there so there is less overlay and it uses fewer resources.

I currently do not have the knowledge or the skills, but I've spent some time looking into it and I have the impression it would be a simple task for a good modder.
 
I'm sure you and most people in the world wouldn't play half of the mods out there. In fact, anyone with a mild case of trypophobia wouldn't even come close to this game. No one's forcing you to play a mod. This thread is for people who would find this mod interesting and are open to ideas on how to make it work.

If you are one of these people, then you're welcome to offer your input. If there are any Total War fans out there who would like to try a mod like this, let's hear your ideas.
 
I can post whether I like the idea or not. And I never said anyone's forcing me to play a mod.

I hope someone can make that kind of mod for you and that people who like that sort of thing enjoy it.

Good luck :)
 
I've never seen a mod that altered how long corpses stay on the ground before vanishing. Personally, I like to see hundreds of soldiers marching off to war in neat array and then beating each other senseless in a free-for-all with ensuing carnage that litters the ground in a corpse-ridden, smoldering aftermath. But with the way Civ V currently handles warfare the land looks relatively unstained by the blemishes of war.

So is there a mod out there that slows corpse decay? If not, I propose a mod with the following features:

1. Permanent corpses: units lie however and wherever they fell in battle.
2. Corpses can be cleaned up with a clean pollution or similar function by workers.
3. When corpses are cleared off of terrain, it yields a small amount of gold (since essentially you are recycling the metal of burned-out tanks, reusing uniforms and rifles, etc.). Rationalize it however you wish. But this gives the AI and players a practical reason to tidy their lands and bury their dead.

Well, it is possible with LUA but.. the corpses would be of course an improvement. If LUA detects a unit killed event then replace it with corpse improvement, if the tile the unit is killed on has an improvement give it a chance to be replaced with the corpse improvement. Functioning similarly to "chopping" forests, you would obtain gold from "scouting" these corpses. It's possible with LUA I hope and not that CPU-heavy with this method of course.
 
Just having the corpses last for the length of the turn would be a nice feature.
 
Functioning similarly to "chopping" forests ...

Forests are a feature, not an improvement, so you'd need something functionally similar to pillage.

You'd also need a "unit killed" event that fired consistently for both human and AI players, and there isn't a standard one as CombatEnded has a whole load of conditions that apply to it (using 3d not SV map, human player only, only if one unit "survives" (so MAD combats don't trigger it, neither do suicides against cities, IIRC)

You'd also need an "improvement pillaged" event (as you need to remove the "smoking" bodies and remove them), again something you need to code either as an event or as a map scan.
 
You'd also need a "unit killed" event that fired consistently for both human and AI players, and there isn't a standard one as CombatEnded has a whole load of conditions that apply to it (using 3d not SV map, human player only, only if one unit "survives" (so MAD combats don't trigger it, neither do suicides against cities, IIRC)
From my testing GameEvents.UnitPrekill(iOwner, iUnit, iUnitType, iX, iY, bDelay, iKiller) does actually fire when any unit is removed from the gameboard for any reason, but it can also fire up to three times as I recall for the same 'unit removal' from the game, and is dreadfully cumbersome in any case.

From running this code borrowed from DarkScythe:
Code:
function prekillListener(iOwner, iUnit, iUnitType, iX, iY, bDelay, iKiller)
	print("prekillListener: Dumping data..")
	print("iOwner: " .. iOwner)
	print("iUnit: " .. iUnit)
	print("iUnitType: " .. iUnitType .. " (" .. GameInfo.Units[iUnitType].Type .. ")")
	print("iX: " .. iX)
	print("iY: " .. iY)
	print("bDelay: " .. tostring(bDelay))
	-- bDelay returns true before unit is killed (before UnitKilledInCombat) and only has one unit on the plot
	-- bDelay returns false after the unit is killed (after UnitKilledInCombat) and an enemy melee unit may be on the same plot at this point
	print("iKiller: " .. iKiller)
	local pPlot = Map.GetPlot(iX, iY)
	local iNumTileUnits = pPlot:GetNumUnits()
	print("numUnits: " .. iNumTileUnits)
end
GameEvents.UnitPrekill.Add(prekillListener)
These were some of the results I got. You can see from the lua-log time-stamps getting a minimum in most cases of two firings. Note that you cannot get useful info about a ranged unit that just killed another unit, but you can get useful information about a direct-attack unit that just killed off another unit but only if that victorious unit attacks:
Spoiler settler used to create a city :
Code:
--
[1913.281]\Lua Script1: prekillListener: Dumping data..
[1913.281]\Lua Script1: iOwner: 0
[1913.281]\Lua Script1: iUnit: 8192
[1913.281]\Lua Script1: iUnitType: 0 (UNIT_SETTLER)
[1913.281]\Lua Script1: iX: 80
[1913.281]\Lua Script1: iY: 16
[1913.281]\Lua Script1: bDelay: true
[1913.281]\Lua Script1: iKiller: -1
[1913.281]\Lua Script1: numUnits: 1
[1913.281]\Lua Script1: prekillListener: Dumping data..
[1913.281]\Lua Script1: iOwner: 0
[1913.281]\Lua Script1: iUnit: 8192
[1913.281]\Lua Script1: iUnitType: 0 (UNIT_SETTLER)
[1913.281]\Lua Script1: iX: 80
[1913.281]\Lua Script1: iY: 16
[1913.281]\Lua Script1: bDelay: false
[1913.281]\Lua Script1: iKiller: -1
[1913.281]\Lua Script1: numUnits: 1
Spoiler barb spearman killed with a crossbowman :
Code:
--
[2995.703]\Lua Script1: prekillListener: Dumping data..
[2995.703]\Lua Script1: iOwner: 63
[2995.703]\Lua Script1: iUnit: 204822
[2995.703]\Lua Script1: iUnitType: 78 (UNIT_SPEARMAN)
[2995.703]\Lua Script1: iX: 81
[2995.703]\Lua Script1: iY: 19
[2995.703]\Lua Script1: bDelay: true
[2995.703]\Lua Script1: iKiller: 0
[2995.703]\Lua Script1: numUnits: 1
[2995.703]\Lua Script1: prekillListener: Dumping data..
[2995.703]\Lua Script1: iOwner: 63
[2995.703]\Lua Script1: iUnit: 204822
[2995.703]\Lua Script1: iUnitType: 78 (UNIT_SPEARMAN)
[2995.703]\Lua Script1: iX: 81
[2995.703]\Lua Script1: iY: 19
[2995.703]\Lua Script1: bDelay: false
[2995.703]\Lua Script1: iKiller: -1
[2995.703]\Lua Script1: numUnits: 1
Spoiler barb warrior killed with a mech infantry who occupied the tile :
Code:
--
[2487.312]\Lua Script1: prekillListener: Dumping data..
[2487.312]\Lua Script1: iOwner: 63
[2487.312]\Lua Script1: iUnit: 196630
[2487.312]\Lua Script1: iUnitType: 85 (UNIT_BARBARIAN_WARRIOR)
[2487.312]\Lua Script1: iX: 82
[2487.312]\Lua Script1: iY: 15
[2487.312]\Lua Script1: bDelay: true
[2487.312]\Lua Script1: iKiller: 0
[2487.312]\Lua Script1: numUnits: 1
[2487.375]\Lua Script1: prekillListener: Dumping data..
[2487.375]\Lua Script1: iOwner: 63
[2487.375]\Lua Script1: iUnit: 196630
[2487.375]\Lua Script1: iUnitType: 85 (UNIT_BARBARIAN_WARRIOR)
[2487.375]\Lua Script1: iX: 82
[2487.375]\Lua Script1: iY: 15
[2487.375]\Lua Script1: bDelay: false
[2487.375]\Lua Script1: iKiller: -1
[2487.375]\Lua Script1: numUnits: [B][COLOR="Blue"]2[/COLOR][/B]
As I recall from testing;
  • I would get results for all players, Barbs, City-States, AI, and whether or not I could 'see' the action.
  • Certain actions, such as disbanding a unit or killing it via lua would only fire once
  • Using lua to kill a unit (with unit:kill()) as I recall would always seem to return the 'Killer' as being the player # (as I recall) for the player whose 'turn' was being processed.
  • Settlers or workers captured by barbs would fire (I think only once) when captured
  • Settlers or workers 'rescued' from barbarians would result in the extra 3rd+ firing because the Barbarian Settler or Worker was also 'killed' as part of the event 'transaction'.
Although since whoward probably wrote the original code, discussing the ins and outs for how UnitPrekill works is probably somewhat like trying to teach the big dog a new trick. :)
 
From my testing GameEvents.UnitPrekill(iOwner, iUnit, iUnitType, iX, iY, bDelay, iKiller) does actually fire when any unit is removed from the gameboard for any reason, but it can also fire up to three times as I recall for the same 'unit removal' from the game

You will only get one event per unit with bDelay = false

Bear in mind that the "kill" part of "UnitPrekill" has nothing to do with combat but everything to do with the C++/Lua Kill() method that removes a unit from a player. You will also get prekill events when a unit is upgraded - as an upgrade creates a new unit of the upgrade type, copies all the data (HP, XP, promotions, etc) from the old out-of-date unit to the new unit and then calls Kill() on the old unit.

You'll also get prekill events for missionary/prophet final spread, workboat builds, inquisitor usage, city founding, unit capture (the captured unit is not switched to the new owner, a new unit is created for the new owner, data transferred and then the old unit removed), and probably others I can't think of/remember at the moment [edit] ... disbanding due to no income

Using lua to kill a unit (with unit:kill()) as I recall would always seem to return the 'Killer' as being the player # (as I recall) for the player whose 'turn' was being processed.

The full signature of pUnit:Kill() is pUnit:Kill(bDelay=false, iPlayer=-1), so to fake a unit being killed by the barbs, use pUnit:Kill(false, 63)

Note that you cannot get useful info about a ranged unit that just killed another unit
and others, such as a ground unit being killed by an air-unit, an air unit being taken down by air interception or an AA unit, a ground unit being killed by or suiciding against a city, an attacking ground unit being killed by a defender. The reason for this is that there is no general C++ method in the DLL that handles the outcome of ALL combats, but the code is spread across many methods, so there is nowhere to place the event that is guaranteed to be called under ALL situations

Spoiler :
PS. Discover the benefits of string.format() ;)

Code:
  print("iOwner: " .. iOwner)
  print("iUnit: " .. iUnit)
  print("iUnitType: " .. iUnitType .. " (" .. GameInfo.Units[iUnitType].Type .. ")")
  print("iX: " .. iX)
  print("iY: " .. iY)
  print("bDelay: " .. tostring(bDelay))

Code:
  print(string.format("Owner: %i, Unit: %i, Type: %i (%s), At: (%i,%i), Delay: %s", iOwner, iUnit, iUnitType, GameInfo.Units[iUnitType].Type, iX, iY, tostring(bDelay)))
 
Bear in mind that the "kill" part of "UnitPrekill" has nothing to do with combat but everything to do with the C++/Lua Kill() method that removes a unit from a player. You will also get prekill events when a unit is upgraded - as an upgrade creates a new unit of the upgrade type, copies all the data (HP, XP, promotions, etc) from the old out-of-date unit to the new unit and then calls Kill() on the old unit.
I did say it was a dreadfully cumbersome method to use. :)

I did make successful use of it in my Scipio's Rome mod, but Bog! If I knew then what I know now about how hard it is (in terms of the logic you need to think through and apply) to use the method I would never have tried to use it.

Given the magic I've learned from you since then on data-driven techniques, etc., I need to re-visit that whole chunk of code and gut out the bloat by using those better techniques.

The real trouble IMO with trying to apply UnitPrekill is that in some cases when bDelay=false, iKiller=-1, and in other cases iKiller is reporting the player number, all depending on the 'type' of 'event' that lead to the removal of the unit. When bDelay=true you can grab and cache the info for iKiller, but then you need to sort out for the occurances where there is no firing of the event with bDelay=true.

I really cannot understand why Firaxis never provided a GameEvents.CombatOccured(a, b, c, d). Well, OK, I understand why: they never encountered a need for one. But the lack has really made it a pain for those of us who wish to mod, especially in a game touted as 'the bestest most moddable thingie evar, hurrah!'
 
If dead units (for example, smoking tanks or marine corpses - I wouldn't recommend this mod to be applied to air units or naval vessels) are applied to a terrain tile with properties similar to a forest, then would a dead unit replace a forest on the land tile? Or would it overlay? And if there are multiple dead units, then could they overlay each other?
 
are applied to a terrain tile with properties similar to a forest, then would a dead unit replace a forest on the land tile?
Yes. A tile only has one feature (and also only one of each - plot type, terrain type, improvement and route)

Or would it overlay?
No (see above)

And if there are multiple dead units, then could they overlay each other?
No (see above)
 
Yes. A tile only has one feature (and also only one of each - plot type, terrain type, improvement and route)


No (see above)


No (see above)

Just replace the radiation effect with the unit corpse effect. The radiation effect can overlay all of the aforementioned terrain attributes, correct?
 
Just replace the radiation effect with the unit corpse effect. The radiation effect can overlay all of the aforementioned terrain attributes, correct?

As far as I can recall, fallout is a feature.
 
By that do you mean that there can't be fallout and a forest on the same tile? Like someone else said, a forest is a feature as well.
 
These are all features, meaning there can only be one per tile:
Spoiler :
Code:
<Regular Features>

FEATURE_ICE
FEATURE_JUNGLE
FEATURE_MARSH
FEATURE_OASIS
FEATURE_FLOOD_PLAINS
FEATURE_FOREST
FEATURE_FALLOUT
FEATURE_ATOLL

<Natural Wonders>

FEATURE_CRATER
FEATURE_FUJI
FEATURE_MESA
FEATURE_REEF
FEATURE_VOLCANO
FEATURE_GIBRALTAR
FEATURE_GEYSER
FEATURE_FOUNTAIN_YOUTH
FEATURE_POTOSI
FEATURE_EL_DORADO
FEATURE_SRI_PADA
FEATURE_MT_SINAI
FEATURE_MT_KAILASH
FEATURE_ULURU
FEATURE_LAKE_VICTORIA
FEATURE_KILIMANJARO
FEATURE_SOLOMONS_MINES
Then there are the two 'fake' features each of which follows its own set of rules:
Code:
FEATURE_LAKE
FEATURE_RIVER

** I thought there was a listing like this on the wiki but for the life of me I couldn't find it. Maybe because I was looking in the 'Modding" part of the wiki.
 
These are all features, meaning there can only be one per tile:
Spoiler :
Code:
<Regular Features>

FEATURE_ICE
FEATURE_JUNGLE
FEATURE_MARSH
FEATURE_OASIS
FEATURE_FLOOD_PLAINS
FEATURE_FOREST
FEATURE_FALLOUT
FEATURE_ATOLL

<Natural Wonders>

FEATURE_CRATER
FEATURE_FUJI
FEATURE_MESA
FEATURE_REEF
FEATURE_VOLCANO
FEATURE_GIBRALTAR
FEATURE_GEYSER
FEATURE_FOUNTAIN_YOUTH
FEATURE_POTOSI
FEATURE_EL_DORADO
FEATURE_SRI_PADA
FEATURE_MT_SINAI
FEATURE_MT_KAILASH
FEATURE_ULURU
FEATURE_LAKE_VICTORIA
FEATURE_KILIMANJARO
FEATURE_SOLOMONS_MINES
Then there are the two 'fake' features each of which follows its own set of rules:
Code:
FEATURE_LAKE
FEATURE_RIVER

** I thought there was a listing like this on the wiki but for the life of me I couldn't find it. Maybe because I was looking in the 'Modding" part of the wiki.

Thanks for the reply.

It doesn't seem odd to anybody that there can't be fallout and floodplains on the same tile? Does fallout never fall on floodplains? Or when it falls on floodplains, does it replace the floodplains? Just trying to understand, because it seems to me that with the explanation I've been given there can be multiple features on one tile. Why not a unit corpse feature on top of floodplains as well?
 
Top Bottom