Jump to content
Madin

Iron Curtain Harvester support?

Recommended Posts

I am looking to add a passive support ability to the Iron Curtain structure, and I was wondering what the best way to go about it would be.

The ability would basically fire an RA1 style Iron Curtain (ie a single vehicle only version), at a Harvester on the same team whose health had gone below 25%. This passive ability would be ready every 30 seconds, and the Iron Curtain effect would last 30 seconds (ie it could only protect one Harvester at a time).

The ability would be completely passive, the player would have no control over it at all. Obviously if the Iron Curtain structure was on low power, or had been manually powered down, the ability would not work.

Any ideas how I could best implement this?

Share this post


Link to post
Share on other sites

From the top of my head:

Have the ironcurtain use a fireweaponupdate with a fireonobject nugget, target = PLAYER harvesters. with a     ForbiddenTargetModelCondition="PRISTINE RUBBLE" so it only fires when the harvester is DAMAGED/REALLY_DAMAGED ? Give the weapon a AttributeModifierNugget that does the actual ironcurtain effect and invulnerability stuff.

Have a dummy specialability SP. with a 30 second recharge, use the MonitorSpecialPowerTimerUpdate to set a modelcondition like (SPECIALPOWER1_READY), use that modelcondition to trigger a status through lua that enables/disables the weapon by using ForbiddenFiringObjectStatus or RequiredFiringObjectStatus in the weapon.

Trigger the dummy sp to fire itself on whenever the ironcurtain attacks/fires its weapon (ATTACKING condition should trigger of the Fireweapon module iirc) , have that condition trigger the Dospecialpower function in lua firing the SP.

Alternatively you might work of your prismforwarding coding, take the fire weapon on object coding in there and adapt it to fire on harvesters? Maybe...

Share this post


Link to post
Share on other sites
4 hours ago, Ravendark said:

From the top of my head:

Have the ironcurtain use a fireweaponupdate with a fireonobject nugget, target = PLAYER harvesters. with a     ForbiddenTargetModelCondition="PRISTINE RUBBLE" so it only fires when the harvester is DAMAGED/REALLY_DAMAGED ? Give the weapon a AttributeModifierNugget that does the actual ironcurtain effect and invulnerability stuff.

Have a dummy specialability SP. with a 30 second recharge, use the MonitorSpecialPowerTimerUpdate to set a modelcondition like (SPECIALPOWER1_READY), use that modelcondition to trigger a status through lua that enables/disables the weapon by using ForbiddenFiringObjectStatus or RequiredFiringObjectStatus in the weapon.

Trigger the dummy sp to fire itself on whenever the ironcurtain attacks/fires its weapon (ATTACKING condition should trigger of the Fireweapon module iirc) , have that condition trigger the Dospecialpower function in lua firing the SP.

Alternatively you might work of your prismforwarding coding, take the fire weapon on object coding in there and adapt it to fire on harvesters? Maybe...

Thanks for your input! I do wonder about the 'fireweaponupdate' and 'fireonobject' nugget, as I have found them unreliable in the past.

Share this post


Link to post
Share on other sites

Very true, they can be a bit spammy depending on conditions. But in your case you are applying a very strong filter. Dmg state + none-spammy unit + range (perhaps), so there might be the occasional multiple harvesters getting targeted at the same time by your ironcurtain, but that would mean multiple harvester drop down in health to the dmg condition at the exact same moment (most likely if multiple harvesters get hit by a aoe of magnitude like a nuke or so).

But like i said, that's from the top of my mind, without having worked on something similar. Probably better solutions out there.

 

Share this post


Link to post
Share on other sites

My solution assumes that a player will only have 1 iron curtain building at the same time (code adaption for more than 1 possible).

1. Make it a special power that triggers a weapon and then an attribute modifier. Use Ravendarks idea to trigger a SPECIALPOWER1_READY lua event that calls the function OnIronCurtainReady.

On 12.11.2017 at 1:10 PM, Ravendark said:

Have a dummy specialability SP. with a 30 second recharge, use the MonitorSpecialPowerTimerUpdate to set a modelcondition like (SPECIALPOWER1_READY),

2. In additon for the harvesters use these events to trigger the functions OnHarvesterHealth25Percent and OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead.

		<ModelConditionEvent Name="HEALTH_PERCENT_25">
			<Conditions>+HEALTH_PERCENT_25</Conditions>
		</ModelConditionEvent>
		
		<ModelConditionEvent Name="HEALTH_PERCENT_25_NOT">
			<Conditions>-HEALTH_PERCENT_25</Conditions>
		</ModelConditionEvent>

3. Now the lua code:

IronCurtain = {}
IronCurtain["Targets"] = {}
IronCurtain["BuildingRef"] = {}
IronCurtain["Ready"] = {}

function OnIronCurtainBuildingCreated(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = self
	IronCurtain["Targets"][ObjectTeamName(self)] = {}
	IronCurtain["Ready"][ObjectTeamName(self)] = false
end

function OnIronCurtainBuildingDestroyed(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = nil
	IronCurtain["Ready"][ObjectTeamName(self)] = false
end

function OnIronCurtainReady(self)
	IronCurtain["Ready"][ObjectTeamName(self)] = true
	if getn(IronCurtain["Targets"][ObjectTeamName(self)]) > 0 and ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then
		--ObjectCreateAndFireTempWeapon(IronCurtain["Targets"][1],"IronCurtainWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(self),"SpecialPower_IronCurtain",GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1]))
		IronCurtain["Ready"][ObjectTeamName(self)] = false
	end
end

function OnHarvesterHealth25Percent(self)
	tinsert(IronCurtain["Targets"][ObjectTeamName(self)],self)
	if IronCurtain["BuildingRef"][ObjectTeamName(self)] and IronCurtain["Ready"][ObjectTeamName(self)] and not ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then 
		--ObjectCreateAndFireTempWeapon(self,"IronCurtainWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(IronCurtain["BuildingRef"][ObjectTeamName(self)]),"SpecialPower_IronCurtain",GetObj.String(self))
		IronCurtain["Ready"][ObjectTeamName(self)] = false
	end
end

function OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead(self)
	local Index = GetIndexOfTableElement(IronCurtain["Targets"][ObjectTeamName(self)],self)
	if Index then tremove(IronCurtain["Targets"][ObjectTeamName(self)], Index) end
end

function GetIndexOfTableElement(table,element)
	for i=1,getn(table),1 do
		if table[i]==element then	return i end
	end
end

So you need in total 5 lua events (3 for the structure and 2 for the harvesters).

4. optionaly if you want to always attack the harbester with the lowest health from the pool of all harvesters that have health < 25:

function GetMinHealthUnit(UnitTable)
	if getn(UnitTable) == 0 then return nil end
	local MinHealthUnitRef = UnitTable[1]
	local MinHealth =  GetHealth(UnitTable[1])
	for i=2,getn(UnitTable),1 do
		if GetHealth(UnitTable[i]) < MinHealth then MinHealthUnitRef = UnitTable[i] end
	end
	return MinHealthUnitRef
end

function GetHealth(Unit)
	local UnitRef = GetObj.String(Unit)
	for i=1,101,1 do	
       if EvaluateCondition("UNIT_HEALTH", UnitRef, CompareTable["<"], i) then return i-1 end
	end
	return 0
end

So replace GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1]) with GetObj.String(GetMinHealthUnit(IronCurtain["Targets"][ObjectTeamName(self)]))

Edited by Mjjstral

Share this post


Link to post
Share on other sites

And here is an alternative I made earlier but you can disregard. It uses lua script timers (meta mod) and gets the harvester refs automatically. So it's a more lua self contained solution.

IronCurtainBuildingList = {}

function IronCurtainBuildingOnCreated(self)
	tinsert(IronCurtainBuildingList,self)
	SetScriptTimer(1,IronCurtainAttackManagement)
end

function IronCurtainBuildingOnDestroyed(self)
	local Index = GetIndexOfTableElement(IronCurtainBuildingList,self)
	if Index then tremove(IronCurtainBuildingList, Index) end
	DeleteScriptTimerAction(IronCurtainAttackManagement)
end

function IronCurtainBuildingOnPowerOutage(self)
	local Index = GetIndexOfTableElement(IronCurtainBuildingList,self)
	if Index then tremove(IronCurtainBuildingList, Index) end
	DeleteScriptTimerAction(IronCurtainAttackManagement)
end

function IronCurtainBuildingOnPowerRestore(self)
	tinsert(IronCurtainBuildingList,self)
	SetScriptTimer(1,IronCurtainAttackManagement)	
end

IronCurtainSchedule = {}

function IronCurtainAttackManagement()
	local IronCurtainObjectWhiteList = GetObjectTypeListForTeam(team,AddToObjectTypeList("HarvesterTypeList","GDIHarvester","NODHarvester","ALIENHarvester"))
	for i=1,getn(IronCurtainBuildingList),1 do
		if IronCurtainSchedule[IronCurtainBuildingList[i]] == 0 and not ObjectTestModelCondition(GetObj.Table(IronCurtainBuildingList[i]),"UNDERPOWERED") then
			for j=1,getn(IronCurtainObjectWhiteList),1 do
				if GetHealth(IronCurtainObjectWhiteList[j].ref) <= 25 then 
					ObjectCreateAndFireTempWeapon(IronCurtainObjectWhiteList[j].ref,"IronCurtainWeapon")
					--ExecuteAction("NAMED_USE_COMMANDBUTTON_ABILITY_ON_NAMED", IronCurtainBuildingList[i], "Command_IronCurtainWeapon", IronCurtainObjectWhiteList[j].ref)
				end 
			end
		else
			IronCurtainSchedule[IronCurtainBuildingList[i]] = IronCurtainSchedule[IronCurtainBuildingList[i]] - 1
		end
	end   
end

function GetObjectTypeListForTeam(team,ObjectType) --ObjectType or ObjectTypeList 
      local RefList = {}
	  local ObjRef = ""
	  local y = 1
      local TempObjectRefTable={}
	  ExecuteAction("SET_IGNORE_SKIRMISH_VICTORY_CONDITIONS", 1)	
       repeat
		ObjRef=RandomString(5)
		ExecuteAction("TEAM_SET_PLAYERS_NEAREST_UNIT_OF_TYPE_TO_REFERENCE",ObjectType,team,ObjRef)
		  if EvaluateCondition("NAMED_NOT_DESTROYED",ObjRef) then 
		  	RefList[y]={}
			RefList[y]["ref"]=ObjRef
			RefList[y]["team"]=team
			RefList[y]["type"]=ObjectType
			RefList[y]["powered"]=1
			tinsert(TempObjectRefTable,ObjRef)
			ExecuteAction("UNIT_SET_TEAM",ObjRef,"team")  
			y=y+1	
		  else break end
	   until(not EvaluateCondition("NAMED_NOT_DESTROYED",ObjRef))
	  for j=1,getn(TempObjectRefTable),1 do
		ExecuteAction("UNIT_SET_TEAM",TempObjectRefTable[j],team)
	  end	  
	  ExecuteAction("SET_IGNORE_SKIRMISH_VICTORY_CONDITIONS", 0)	
	  return RefList
end

function AddToObjectTypeList(ObjectTypeList,...)
  for i=1,getn(arg),1 do
    ExecuteAction("OBJECTLIST_ADDOBJECTTYPE", ObjectTypeList, arg[i])
  end
  return ObjectTypeList
end

function GetHealth(input,HealthType)
 local HealthCompareType = ""
 if HealthType == nil or HealthType == "unit" or HealthType == 1 then HealthCompareType = "UNIT_HEALTH"
 else HealthCompareType = "EVAL_TEAM_HEALTH" end
	for i=1,101,1 do	
       if EvaluateCondition(HealthCompareType, input, CompareTable["<"], i) then return i-1 end
	end
	return 0
end

function GetIndexOfTableElement(table,element)
	for i=1,getn(table),1 do
		if table[i]==element then	return i end
	end
end

function GetObj.Table(object) 
    if type(object) == "table" then return object
	else  
		for k,v in globals() do
		  if strfind(k,"ObjID") ~= nil and strfind(ObjectDescription(v),object) then
			return rawget(globals(),k)   --v
		  end
		end
		return object
	end
end

 

  • Upvote 1

Share this post


Link to post
Share on other sites

Thanks for your reply!

I am getting an error message once the Special power used to trigger the Iron Curtain LUA is ready:

ErrorMessage_01.jpg

Since I moved to Windows 7, I am no longer getting 'ErrorLog' text files.

IronCurtain = {}
IronCurtain["Targets"] = {}
IronCurtain["BuildingRef"] = {}
IronCurtain["Ready"] = {}

function OnIronCurtainBuildingCreated(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = self
	IronCurtain["Targets"][ObjectTeamName(self)] = {}
	IronCurtain["Ready"][ObjectTeamName(self)] = false
end

function OnIronCurtainBuildingDestroyed(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = nil
	IronCurtain["Ready"][ObjectTeamName(self)] = false
end

function OnIronCurtainReady(self)
	IronCurtain["Ready"][ObjectTeamName(self)] = true
	if getn(IronCurtain["Targets"][ObjectTeamName(self)]) > 0 and ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then
		--ObjectCreateAndFireTempWeapon(IronCurtain["Targets"][1],"IronCurtainWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(self),"SpecialPower_IronCurtain",GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1]))
		IronCurtain["Ready"][ObjectTeamName(self)] = false
	end
end

function OnHarvesterHealth25Percent(self)
	tinsert(IronCurtain["Targets"][ObjectTeamName(self)],self)
	if IronCurtain["BuildingRef"][ObjectTeamName(self)] and IronCurtain["Ready"][ObjectTeamName(self)] and not ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then 
		--ObjectCreateAndFireTempWeapon(self,"IronCurtainWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(IronCurtain["BuildingRef"][ObjectTeamName(self)]),"SpecialPower_IronCurtain",GetObj.String(self))
		IronCurtain["Ready"][ObjectTeamName(self)] = false
	end
end

function OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead(self)
	local Index = GetIndexOfTableElement(IronCurtain["Targets"][ObjectTeamName(self)],self)
	if Index then tremove(IronCurtain["Targets"][ObjectTeamName(self)], Index) end
end

function GetIndexOfTableElement(table,element)
	for i=1,getn(table),1 do
		if table[i]==element then	return i end
	end
end

 

Edited by Madin

Share this post


Link to post
Share on other sites
15 hours ago, Madin said:

I am getting an error message

This should fix it. It's now more error robust in general:

IronCurtain = {}
IronCurtain["Targets"] = {}
IronCurtain["BuildingRef"] = {}
IronCurtain["Ready"] = {}

function OnIronCurtainBuildingCreated(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = self
	if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end
	IronCurtain["Ready"][ObjectTeamName(self)] = false
end

function OnIronCurtainBuildingDestroyed(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = nil
	IronCurtain["Ready"][ObjectTeamName(self)] = false
end

function OnIronCurtainReady(self)
	IronCurtain["Ready"][ObjectTeamName(self)] = true	
	if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end
	if IronCurtain["Targets"][ObjectTeamName(self)] and getn(IronCurtain["Targets"][ObjectTeamName(self)]) > 0 and not ObjectTestModelCondition(self,"UNDERPOWERED") then
		--ObjectCreateAndFireTempWeapon(IronCurtain["Targets"][1],"IronCurtainWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(self),"SpecialPower_IronCurtain",GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1]))
		IronCurtain["Ready"][ObjectTeamName(self)] = false
	end
end

function OnHarvesterHealth25Percent(self)
	if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end
	tinsert(IronCurtain["Targets"][ObjectTeamName(self)],self)
	if IronCurtain["BuildingRef"][ObjectTeamName(self)] and IronCurtain["Ready"][ObjectTeamName(self)] and not ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then 
		--ObjectCreateAndFireTempWeapon(self,"IronCurtainWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(IronCurtain["BuildingRef"][ObjectTeamName(self)]),"SpecialPower_IronCurtain",GetObj.String(self))
		IronCurtain["Ready"][ObjectTeamName(self)] = false
	end
end

function OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead(self)
	local Index = GetIndexOfTableElement(IronCurtain["Targets"][ObjectTeamName(self)],self)
	if Index then tremove(IronCurtain["Targets"][ObjectTeamName(self)], Index) end
end

function GetIndexOfTableElement(table,element)
	if not table then return nil end
	for i=1,getn(table),1 do
		if table[i]==element then	return i end
	end
end

 

15 hours ago, Madin said:

Since I moved to Windows 7, I am no longer getting 'ErrorLog' text files.

Hm I'm also on win7... Shouldn't be system dependent acually.

Why does the lua code pasted in these forum text boxes appear so whitish and unreadable ?

 

  • Upvote 1

Share this post


Link to post
Share on other sites

This is still not working fully (although now there are no errors).

IronCurtain = {}
IronCurtain["Targets"] = {}
IronCurtain["BuildingRef"] = {}
IronCurtain["Ready"] = {}

function OnIronCurtainBuildingCreated(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = self
	if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end
	IronCurtain["Ready"][ObjectTeamName(self)] = false
	ExecuteAction("SHOW_MILITARY_CAPTION", "IRONCURTAIN_BUILT", 5)
end

function OnIronCurtainBuildingDestroyed(self)
	IronCurtain["BuildingRef"][ObjectTeamName(self)] = nil
	IronCurtain["Ready"][ObjectTeamName(self)] = false
end

function OnIronCurtainReady(self)
	IronCurtain["Ready"][ObjectTeamName(self)] = true
	ExecuteAction("SHOW_MILITARY_CAPTION", "IRONCURTAIN_READY", 5)
	if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end
	ExecuteAction("SHOW_MILITARY_CAPTION", "IRONCURTAIN_NOT_FIRED", 5)
	if IronCurtain["Targets"][ObjectTeamName(self)] and getn(IronCurtain["Targets"][ObjectTeamName(self)]) > 0 and not ObjectTestModelCondition(self,"UNDERPOWERED") then
		-- ObjectCreateAndFireTempWeapon(IronCurtain["Targets"][1],"RA1IronCurtainInfantryDeathWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(self),"SpecialPowerIronCurtainRA1_Start",GetObj.String(IronCurtain["Targets"][ObjectTeamName(self)][1]))
		ExecuteAction("SHOW_MILITARY_CAPTION", "IRONCURTAIN_FIRED", 5)
		IronCurtain["Ready"][ObjectTeamName(self)] = false
		ExecuteAction("SHOW_MILITARY_CAPTION", "IRONCURTAIN_FINISHED", 5)
	end
end

function OnHarvesterHealth25Percent(self)
	if IronCurtain["Targets"][ObjectTeamName(self)] == nil then IronCurtain["Targets"][ObjectTeamName(self)] = {} end
	ExecuteAction("SHOW_MILITARY_CAPTION", "HARVESTER_FIRST", 5)
	tinsert(IronCurtain["Targets"][ObjectTeamName(self)],self)
	ExecuteAction("SHOW_MILITARY_CAPTION", "HARVESTER_IN_TABLE", 5)
	if IronCurtain["BuildingRef"][ObjectTeamName(self)] and IronCurtain["Ready"][ObjectTeamName(self)] and not ObjectTestModelCondition(IronCurtain["BuildingRef"][ObjectTeamName(self)],"UNDERPOWERED") then 
		-- ObjectCreateAndFireTempWeapon(GetObj.String(self),"RA1IronCurtainInfantryDeathWeapon")
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(IronCurtain["BuildingRef"][ObjectTeamName(self)]),"SpecialPowerIronCurtainRA1_Start",GetObj.String(self))
		ExecuteAction("SHOW_MILITARY_CAPTION", "IRONCURTAIN_HARVESTER", 5)
		IronCurtain["Ready"][ObjectTeamName(self)] = false
		ExecuteAction("SHOW_MILITARY_CAPTION", "HARVESTER_CODE_FINISHED", 5)
	end
end

function OnHarvesterHealth25PercentNOT_OR_OnHarvesterDead(self)
	local Index = GetIndexOfTableElement(IronCurtain["Targets"][ObjectTeamName(self)],self)
	if Index then tremove(IronCurtain["Targets"][ObjectTeamName(self)], Index) end
	ExecuteAction("SHOW_MILITARY_CAPTION", "HARVESTER_NOT_IN_TABLE", 5)
end

function GetIndexOfTableElement(table,element)
	if not table then return nil end
	for i=1,getn(table),1 do
		if table[i]==element then	return i end
	end
end

The parts of the code that are supposed to fire either a 'Special Power' or weapon, do not work. The test messages before that point do play.

The Harvester gets to the "HARVESTER_IN_TABLE" message when its gets to 25% health or lower, and gets the "HARVESTER_NOT_IN_TABLE" message when it goes above 25% health (they have self heal).

When the Iron Curtain comes to ready, it will correctly get to the "IRONCURTAIN_NOT_FIRED" message (I have not tried having the Harvesters damaged before the Iron Curtain special power is ready).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


×