Jump to content
Madin

Prism Fowarding, Part IV (idea storm thread)

Recommended Posts

Oh well.

The script does not like to fire object specific targeted special powers, and the 'NAME_ATTACK_NAMED' method still has the issue with it using the 'PRIMARY', then 'TERTIARY' weapons alternately. It also still has occasions were the support beam will continue to fire when the main Obelisk has no target (in this case it will only use the 'TERTIARY' weapon!).

I am wondering if there would be as many issues with a RA3 style support (Main Obelisk gets target, Obelisk within range fire support beam at it to boost weapon, no supporting of support Obelisk).

Share this post


Link to post
Quote

The script does not like to fire object specific targeted special powers

I use targeted special powers via script on many occasions in meta mod, maybe have a look and find out the difference.

Quote

It also still has occasions were the support beam will continue to fire when the main Obelisk has no target

The NodObelisk_RELOADING function is responsible for avoiding such cases. The towers search for theri "mother" tower and test if it is still attacking, if not they should get the "NAMED_STOP" command. Do some live lua script testing, as such things most of the time get resolved by rapid prototyping/ try and error.

Quote

.. (in this case it will only use the 'TERTIARY' weapon!).

That means that a support tower that is already firing tertiary should't get another attack command. You can add a test before they get the attack command in the cascade forwarding function, to find out if they already attack ( test model comditions preattack, firing, reloading and such).

Quote

I am wondering if there would be as many issues with a RA3 style support (Main Obelisk gets target, Obelisk within range fire support beam at it to boost weapon, no supporting of support Obelisk).

Would't make a big difference with my full lua script way, because the main logic won't differ. Only the attack distribution of support tower will get much easier. But for simple RA3 style forwardings you can also take a non lua way into consideration (see Lauren's solution, which is not bad either).

Edited by Mjjstral

Share this post


Link to post
	for i=2,getn(ObjectList),1 do
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(ObjectList[i]),"SpecialPower_PrismForwarding",SupportConnection[tostring(ObjectList[i])])	
		-- ExecuteAction("NAMED_STOP",ObjectList[i])
		-- ExecuteAction("NAMED_ATTACK_NAMED",ObjectList[i],SupportConnection[tostring(ObjectList[i])])		
	end

Is the first 'GetObj' correct, and how would the syntax go for the second one?

Share this post


Link to post
	for i=2,getn(ObjectList),1 do
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(ObjectList[i]),"SpecialPower_PrismForwarding",GetObj.String(SupportConnection[tostring(ObjectList[i])]))	
		-- ExecuteAction("NAMED_STOP",ObjectList[i])
		-- ExecuteAction("NAMED_ATTACK_NAMED",ObjectList[i],SupportConnection[tostring(ObjectList[i])])		
	end
  • Upvote 1

Share this post


Link to post

So, Special power supporting beam now works!

So the final major obstacle is the attribute modifier which still refuses to work:

function CascadeForwarding(self) --made for "Madin" (cncnz forums)
	self=GetObj.Table(self)
	local IsObjectInSupporterList = function(object)
		for q,p in MainTowerSupporterList do  --to test if a tower already supports another tower
			if q~=tostring(%self) then
				for i=1,getn(p),1 do if p[i]==object then return true end end
			end
		end
		return false
	end	
	local MaximumSupportDistance = 13000
	local TowerAttackRange = 375 --here attack range of nod obelisk
	if ObjectCountNearbyEnemies(self,TowerAttackRange)==0 and IsObjectInSupporterList(self) then return end
	local ObjectList = {}
	local DistanceTable = {}
	local SupportConnection={}
	--create object list of all support towers
	for k,v in globals() do
		if strfind(k,"ObjID") and GetObj.Hash(self)==GetObj.Hash(v) and self~=v and ObjectTeamName(self)==ObjectTeamName(v) then
			if ObjectCountNearbyEnemies(v,TowerAttackRange)==0 and EvaluateCondition("DISTANCE_BETWEEN_OBJ", GetObj.String(self),GetObj.String(v), CompareTable["<="], MaximumSupportDistance) then
				if not IsObjectInSupporterList(v) then tinsert(ObjectList,v) end
			end
		end
	end
  	tinsert(ObjectList,self)
	if getn(ObjectList)<2 then return end
	--create 2d matrix with distances
	for i=1,getn(ObjectList),1 do
		DistanceTable[tostring(ObjectList[i])]={}
	end
	for i=1,getn(ObjectList),1 do
		for j=i,getn(ObjectList),1 do
			if i==j then 
				DistanceTable[tostring(ObjectList[i])][tostring(ObjectList[j])]=0
			else 
				if DistanceTable[tostring(ObjectList[i])][tostring(ObjectList[j])] == nil then
					DistanceTable[tostring(ObjectList[i])][tostring(ObjectList[j])]=GetObjectDistance(GetObj.String(ObjectList[i]),GetObj.String(ObjectList[j]))
					DistanceTable[tostring(ObjectList[j])][tostring(ObjectList[i])]=DistanceTable[tostring(ObjectList[i])][tostring(ObjectList[j])]	
				end
			end
		end	
	end
	--sort object list by distance to main tower
	local SortHelper=function(Object1,Object2)
		if %DistanceTable[tostring(%self)][tostring(Object1)] < %DistanceTable[tostring(%self)][tostring(Object2)] then return true end
	end
	sort(ObjectList,SortHelper)
	--main part: distribute one tower for each tower to support
	local MainNodeTable = {}
	tinsert(MainNodeTable,self)
	local i = 2
	local ObjectListSize
	for i=2,getn(ObjectList),1 do
		local MainNodeCriteria = true
		local NextMainNode, NextMainNodeAlternative  --closest main node
		local NextMainNodeDistance = 13000
		for k=1,getn(MainNodeTable),1 do
			if NextMainNodeDistance > DistanceTable[tostring(MainNodeTable[k])][tostring(ObjectList[i])] then
				NextMainNodeDistance = DistanceTable[tostring(MainNodeTable[k])][tostring(ObjectList[i])]
				NextMainNode = MainNodeTable[k]
			end
		end		
		local ShortestLinkToNextMainNodeDistance = 13000
		for j=3,getn(ObjectList),1 do	
			if not i==j and ObjectList[j]~=nil then
				local iNodeTojNodeDistance = DistanceTable[tostring(ObjectList[i])][tostring(ObjectList[j])]
				local iNodeToNextMainNodeDistance = DistanceTable[tostring(NextMainNode)][tostring(ObjectList[i])]
				local jNodeToNextMainNodeDistance = DistanceTable[tostring(NextMainNode)][tostring(ObjectList[j])]
				if jNodeToNextMainNodeDistance < iNodeToNextMainNodeDistance then 
					if iNodeTojNodeDistance < iNodeToNextMainNodeDistance then
						MainNodeCriteria = false
						local LinkToNextMainNodeDistance = iNodeTojNodeDistance + jNodeToNextMainNodeDistance
						if ShortestLinkToNextMainNodeDistance > LinkToNextMainNodeDistance then
							NextMainNodeAlternative=ObjectList[j]
							ShortestLinkToNextMainNodeDistance = LinkToNextMainNodeDistance
						end
					end
				end
			end
		end
		if MainNodeCriteria == true then 
			if TowerAttackRange > DistanceTable[tostring(NextMainNode)][tostring(ObjectList[i])] then
				tinsert(MainNodeTable,ObjectList[i])
				SupportConnection[tostring(ObjectList[i])]=NextMainNode
			else
				ObjectList[i]=nil
			end
		else 
			if TowerAttackRange > ShortestLinkToNextMainNodeDistance then 
				SupportConnection[tostring(ObjectList[i])]=NextMainNodeAlternative
			else 
				ObjectList[i]=nil
			end
		end
	end	
	--remove all unneccasary towers
	local CleanedObjectList = {}
	for i=1,getn(ObjectList),1 do
		if not ObjectList[i]==nil then tinsert(CleanedObjectList,ObjectList[i]) end
	end
	ObjectList=CleanedObjectList
	MainTowerSupporterList[tostring(self)] = CleanedObjectList
	MainTowerSupportConnectionList[tostring(self)]=SupportConnection
	--fire cumulative attribute modifier weapon on main tower (self)
	for i=2,getn(ObjectList),1 do
		ObjectCreateAndFireTempWeapon(self,"PrismTowerSupportWeapon")
	end		
	--fire special power to display visual support beams
	for i=2,getn(ObjectList),1 do
		ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",GetObj.String(ObjectList[i]),"SpecialPower_PrismForwarding",GetObj.String(SupportConnection[tostring(ObjectList[i])]))	
		-- ExecuteAction("NAMED_STOP",ObjectList[i])
		-- ExecuteAction("NAMED_ATTACK_NAMED",ObjectList[i],SupportConnection[tostring(ObjectList[i])])		
	end
end

Weapon:

  <WeaponTemplate id="PrismTowerSupportWeapon" Name="PrismTowerSupportWeapon" RadiusDamageAffects="ALLIES" AttackRange="50000.0" AntiMask="ANTI_GROUND ANTI_STRUCTURE">
    <Nuggets>
      <DamageNugget Damage="1.0" Radius="1.0" DelayTimeSeconds="0.0s" DamageType="SNIPER" DeathType="NORMAL" DamageFXType="NOD_BOMB"></DamageNugget><!-- So there will be a large visual FX if the weapon is fired -->
      <AttributeModifierNugget Radius="5" PartitionFilterTestType="SPHERE" AttributeModifierName="AttributeModifier_PrismTowerSupport">
        <SpecialObjectFilter Rule="NONE" Relationship="SAME_PLAYER">
          <IncludeThing>NODObelisk</IncludeThing>
        </SpecialObjectFilter>
      </AttributeModifierNugget>
    </Nuggets>
  </WeaponTemplate>
  <AttributeModifier id="AttributeModifier_PrismTowerSupport" Category="BUFF" StackingLimit="999" Duration="3.0s">
    <Modifier Type="DAMAGE_MULT" Value="500" /><!-- 5x damage, so it is obvious -->
  </AttributeModifier>

I added "SELF" to the 'RadiusDamageAffects' and it is kind of working now. It has an issue were force firing with an Obelisk will always trigger the attribute modifier, even on lone Obelisk, far away from any support towers.

Edited by Madin
Further test

Share this post


Link to post

Currently the issue is that the attribute modifier only works if I force fire on a target! and there is still the issue with the lone tower receiving an atrribute modifier 9again a force fire issue).

:dazed:

Edited by Madin

Share this post


Link to post

Wow I did not know this prism forwarding effect works in C&C3. If the prism towers work with this effect so shall the prism tanks.

Share this post


Link to post
Quote

Currently the issue is that the attribute modifier only works if I force fire on a target!

This is strange. I mean regardless of how it is attacking, it must trigger the preload event and if it gets support towers then there must be a weapon fired on it for each tower. You don't need the NodObelisk_RELOADING(self) function anymore by doing the support via special power.

Quote

and there is still the issue with the lone tower receiving an atrribute modifier again a force fire issue).

I have to look over the whole code again maybe. Try to change the MaximumSupportDistance first. There is actually that line 

if getn(ObjectList)<2 then return end

that should prevent such cases..hm

Share this post


Link to post

OK it is time to stress test this!

Changing:

local MaximumSupportDistance = 13000

to:

local MaximumSupportDistance = 375

Means that only towers within a radius of 375 will fire a support beam at the attacking tower (so there is no chain of support beams).

Keeping it at a high number like 13000, means that the 'lone tower' force fire bug will happen (a tower that is not with range of other towers will still get attribute modifier boost from all towers within "MaximumSupportDistance" radius number without any visible support beam being drawn, this would be a major exploit).

An even bigger issue is that once a tower has either fired on a target, or fired a support beam, it can no longer fire a support beam at any other tower. The net result of this is that eventually most towers will not use their support beams, as they get their own targets, or other towers request support and are ignored (because they were not the first tower that had its request answered).

Share this post


Link to post

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

  • Recently Browsing   0 members

    No registered users viewing this page.

×