Madin 10 Posted May 28, 2017 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
Mjjstral 25 Posted May 28, 2017 (edited) 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 May 28, 2017 by Mjjstral Share this post Link to post
Madin 10 Posted June 1, 2017 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
Mjjstral 25 Posted June 1, 2017 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 1 Share this post Link to post
Madin 10 Posted June 1, 2017 (edited) 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 June 2, 2017 by Madin Further test Share this post Link to post
Madin 10 Posted June 2, 2017 (edited) 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). Edited November 10, 2017 by Madin Share this post Link to post
PurpleGaga27 37 Posted June 2, 2017 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
Mjjstral 25 Posted June 2, 2017 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
Madin 10 Posted November 11, 2017 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
ztz2019 1 Posted September 26, 2019 14 hours ago, Madin said: Congratulations Share this post Link to post