Page 1 of 1

Health on kill [Solved]

Posted: Mon Apr 12, 2021 9:00 pm
by Tempo
Can I add something to the mission script so that when a specific class kills an enemy they get a certain amount of health? There was an old post that felt close to this (http://www.gametoast.com/viewtopic.php? ... ll#p305671), but I couldn't quite figure it out based on that

Re: Health on kill

Posted: Wed Apr 14, 2021 10:46 am
by Sporadia
You can do it inside an OnCharacterDeath(function(charIndex, charIndex)) event:

Code: Select all

OnCharacterDeath(
	function(playerIndex, killerIndex)
		-- code here
	end
)
Then you do the following:
  1. Check that the killer is still alive.
  2. Check that the killer is on a specific team.
  3. Check that the dead character (player) was on a different team.
  4. Check that the killer is a specific class (has to be done after checking the killer's team).

Code: Select all

local killerTeam = GetCharacterTeam(killerIndex)
local killerData = GetCharacterUnit(killerIndex) -- returns nil if killer is dead, returns the killer's objectData if killer is alive
if killerData then -- check that the killer is alive
	if killerTeam == 1 then -- check the killer is on team 1
		if killerTeam != GetCharacterTeam(playerIndex) then -- check for a team kill
			if GetCharacterClass(killerIndex) == 5 then -- check that the killer is class 5
				-- code here
			end
		end
	end
end

Using GetCharacterClass(charIndex)
Hidden/Spoiler:
GetCharacterClass(charIndex) is a bit weird so I'll try explain how it works. Every class on each team is given a number, starting with 0. In the mission lua, you add the classes inside of ScriptInit(). You might do this with AddUnitClass() or you might do it with SetupTeams(). If you use AddUnitClass(), then the first line of AddUnitClass() will be class 0, the second line will be class 1, the next line will be class 2 and so on.

If you use SetupTeams(), it actually calls a bunch of AddUnitClass() functions, but it does it in this order: soldier, pilot, assault, sniper, marine, engineer, officer, special. These classes are always added in the same order, and any class that you don't add won't be given a number. So for example if you only had an assault, soldier and marine on a team: the soldier will be class 0, the assault will be class 1 and the marine will be class 2.

The hero is added last (normally) with SetHeroClass(). So a for a team with 3 regular units (class 0, 1, 2), the hero would be added as class 3. For a team with 6 regular units, the hero is added as class 6 etc. Each team has a separate set of class numbers, starting at 0. If you want to check what number a specific class is, you can also just count where it appears on the spawn select screen (class 0 is at the top of the screen).

GetCharacterClass(charIndex) returns the class number of a player, so you need to know what class number you're looking for. If you use it on a dead player, you might get the class number for the unit they just played as, or you might get the number of the unit they're going to play as when they next spawn. I think that's a but unreliable. But on living players it works fine.

Here's some example code for finding class numbers:

Code: Select all

SetupTeams{
	rep = {	
		team = REP,
		units = 32,
		reinforcements = 150,
		soldier  = { "rep_inf_ep3_rifleman", 7, 25}, -- rep class 0
		engineer = { "rep_inf_ep3_engineer", 1, 4}, -- rep class 1
		special  = { "rep_inf_ep3_jettrooper", 1, 4}, -- rep class 2
	},
	cis = {
		team = CIS,
		units = 32,
		reinforcements = 150,
		sniper   = { "cis_inf_sniper", 1, 4}, -- cis class 1
		soldier  = { "sep_inf_rifleman", 7, 25}, -- cis class 0
		special  = { "cis_inf_droideka", 1, 4}, -- cis class 3
		officer  = { "sep_inf_officer", 1, 4}, -- cis class 2
	}
}

AddUnitClass(REP, "rep_inf_ep3_rocketeer", 1, 4) -- rep class 3
AddUnitClass(CIS, "cis_inf_marine", 1, 4) -- cis class 4

SetHeroClass(REP, "rep_hero_macewindu") -- rep class 4
SetHeroClass(CIS, "cis_hero_darthmaul") -- cis class 5

Finally you add more health. I'd use GetObjectHealth(objectData) and SetProperty(objectData, odfparameters):

Code: Select all

local killerHealthTable = {GetObjectHealth(killerData)}
if killerHealthTable[1] <= (killerHealthTable[2] + 80) then -- if CurHealth is less than (MaxHealth + 80)
	local newHealth = killerHealthTable[1] + 80 -- add 80 health to CurHealth
	SetProperty(killerData, "CurHealth", newHealth)
elseif killerHealthTable[1] < killerHealthTable[2] then -- elseif CurHealth is only slightly less than MaxHealth
	SetProperty(killerData, "CurHealth", killerHealthTable[2]) -- set CurHealth to MaxHealth
end

To better explain GetObjectHealth() (I write charUnit instead of objectData in this post, but they're the same thing): http://www.gametoast.com/viewtopic.php?p=537695#p537695

Full thing looks something like this:

Code: Select all

OnCharacterDeath(
	function(playerIndex, killerIndex)
		local killerTeam = GetCharacterTeam(killerIndex)
		local killerData = GetCharacterUnit(killerIndex) -- returns nil if killer is dead, returns the killer's objectData if killer is alive
		
		-- filters
		if killerData then -- check that the killer is alive
			if killerTeam == 1 then -- check the killer is on team 1
				if killerTeam != GetCharacterTeam(playerIndex) then -- check for a team kill
					if GetCharacterClass(killerIndex) == 5 then	-- check that the killer is class 5
					
						local killerHealthTable = {GetObjectHealth(killerData)}
						if killerHealthTable[1] <= (killerHealthTable[2] + 80) then	-- if CurHealth is less than (MaxHealth + 80)
							local newHealth = killerHealthTable[1] + 80		-- CurHealth + 80
							SetProperty(killerData, "CurHealth", newHealth)
						elseif killerHealthTable[1] < killerHealthTable[2] then	-- elseif CurHealth is only slightly less than MaxHealth
							SetProperty(killerData, "CurHealth", killerHealthTable[2]) -- set CurHealth to MaxHealth
						end
						
					end -- filters
				end
			end
		end -- filters end
	end -- function end
) -- event end

Re: Health on kill

Posted: Wed Apr 14, 2021 9:58 pm
by Tempo
Every time I try munging this I get the error message " `then' expected near `!' ". And I have no experience with events so I'm not 100% sure where to put this in the script? I've tried a couple places but some other posts seem to suggest it's put at the end of function ScriptPostLoad(). But the failed munge seems to prevent it from working regardless.

Re: Health on kill

Posted: Thu Apr 15, 2021 6:27 am
by Sporadia
Oh there's just a syntax mistake in my example. I've used != as a not equal sign, but in lua the correct symbol is ~=

Edit: Also I've just seen on another thread that there's an alternative way to check the character's class. You can compare GetEntityClass(objectData) with FindEntityClass(string) because they both return the same kind of data. Like this:

Code: Select all

if GetEntityClass(killerData) == FindEntityClass("rep_inf_ep3_rifleman") then
    -- code here
end
This might be simpler than checking the class number.

Re: Health on kill

Posted: Thu Apr 15, 2021 3:35 pm
by Tempo
ah, ok. Yeah that worked. I know a little more about java than lua so I was really confused why it didn't like that. Thanks for the help! (But just in case someone else wants to know later, I had to change "if killerHealthTable[1] <= (killerHealthTable[2] + 80)" to "if killerHealthTable[1] <= (killerHealthTable[2] - 80)" unless you want your unit to be able to surpass their max health with the health steal.)