Jump to content

Mjjstral

Members
  • Content count

    110
  • Joined

  • Last visited

Everything posted by Mjjstral

  1. I use targeted special powers via script on many occasions in meta mod, maybe have a look and find out the difference. 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. 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). 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).
  2. Meta Mod Tiberium Wars Version now released on MODDB. Some more bugfixes made, but still with limitations.
  3. Just a sidenote observation: You can trigger an untargeted special power in 4 ways, it's crazy: ExecuteAction("NAMED_FIRE_SPECIAL_POWER",...) ExecuteAction("NAMED_FIRE_METAGAME_OP_INSTANT",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ABILITY",...) ObjectDoSpecialPower(object,specialpowername) And a lame single forwarded prism forwarding could be achieved with ExecuteAction("NAMED_USE_COMMANDBUTTON_ON_NEAREST_OBJECTTYPE",...) Plus some testings of course.
  4. In general your options for special powers/commandbuttons/abilities/attacking are: ExecuteAction("NAMED_FIRE_SPECIAL_POWER",...) ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_NAMED",...) ExecuteAction("NAMED_FIRE_SPECIAL_POWER_AT_WAYPOINT",...) ExecuteAction("NAMED_FIRE_WEAPON_FOLLOWING_WAYPOINT_PATH",...) ExecuteAction("NAMED_FIRE_METAGAME_OP_INSTANT",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ABILITY",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ABILITY_AT_WAYPOINT",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ABILITY_ON_NAMED",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ON_NEAREST_ENEMY_BUILDING",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ON_NEAREST_ENEMY_BUILDING_CLASS",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ON_NEAREST_ENEMY_UNIT",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ON_NEAREST_GARRISONED_BUILDING",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ON_NEAREST_KINDOF",...) ExecuteAction("NAMED_USE_COMMANDBUTTON_ON_NEAREST_OBJECTTYPE",...) ExecuteAction("NAMED_ATTACK_NAMED",...) ObjectDoSpecialPower(object,specialpowername) Try to figure out a way to use your sp with these commands, else WeaponFireSpecialAbilityUpdate could be mandatory/easier to use ? ExecuteAction("NAMED_USE_COMMANDBUTTON_ABILITY_ON_NAMED",...) looks promising. No the code will work with a special power too, but uncomment "--MainTowerSupporterList[tostring(self)]=nil" in NodObelisk_RELOADING function then.
  5. I made a very very early meta mod port for tiberium wars. Many things still do not work correctly, but for modders it's still usefull at this point, as the whole meta mod io does work and also many other elements, like the meta command text menu and meta control tab menu (for the most part). Among the many issues that need to get resolved are the following: meta tech faction broken diplomacy alliance changes broken multiplayer compatibility not finished yet lua object tables still with kane's wrath objects The source code will probably become universally compileable for kane's wrath as well as tiberium wars in the future. Download comes with source code of course Note: The lua work folder gets created on first start up and can be found in the tw userdata folder, named "MetaModIO". For modders/scripters run the game in windowed mode and push the lua script button in the meta control tab menu to create the LUA_INPUT.lua. Then open that file and have fun, running your scripts live. You can overwrite any existing function from the scripts.lua within the LUA_INPUT.lua. DOWNLOAD
  6. That was my idea too, just try it. Should't interfere with the script. Or use the special power
  7. Ok you also need to include all functions from previous posts. And be aware to always take the most recent functions I've posted. It can't find the GetObj table in which we stored the functions like GetObj.String and more. See above, we declared GetObj = {}.
  8. Hey I've changed quite alot, so that towers that have enemies in attack range and do not have "attack on position" commands issued won't support other tower anymore. That means you can now test the system with attack on position commands without enemies even. The problems: I also didn't succeed to make it work via a special power on the xml coding side. My advice is to create that special power as a button ability and make sure it is actually working via manual use. Then it will surely work on the lua side. There was something similiar with the devourer conversion reserve use we worked on, where the special power use on another object also worked. My alternative approach is to still use ExecuteAction("NAMED_ATTACK_NAMED",...) , but with a tertiary non damaging weapon that only can be used on the respective tower object (here NodObelisk). The very strange thing for me was, that every second support beam, does damage to the tower they support. This can probably get solved by reissueing the attack command precisely after each attack. Last problem: The attribute modifier didn't work for me at all, there's something missing that you need to find. I've used attribute modifiers with ObjectCreateAndFireTempWeapon before, so in theory it is viable. If it has to do with the weapon with it's damage attribute already locked after EventName="PREATTACK_A" then you can use EventName="ATTACKING" which gets triggered before. This gets more and more complicated each day xD So here is all the code: MainTowerSupporterList= {} MainTowerSupportConnectionList= {} 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",ObjectList[i],"SpecialPower_PrismForwarding",SupportConnection[tostring(ObjectList[i])]) ExecuteAction("NAMED_STOP",ObjectList[i]) ExecuteAction("NAMED_ATTACK_NAMED",ObjectList[i],SupportConnection[tostring(ObjectList[i])]) end end And here are the additional functions: function GetMyMainTower(object) for q,p in MainTowerSupporterList do if q~=tostring(object) then for i=1,getn(p),1 do if p[i]==object then return p[1] end end end end end function IsTowerStillAttacking(MainTower) if ObjectTestModelCondition(MainTower,"ATTACKING") or ObjectTestModelCondition(MainTower,"PREATTACK_A") or ObjectTestModelCondition(MainTower,"RELOADING_A") or ObjectTestModelCondition(MainTower,"FIRING_A") then return true else return false end end function NodObelisk_RELOADING(self) local TowerAttackRange = 375 if MainTowerSupporterList[tostring(self)]~=nil then --and ObjectCountNearbyEnemies(self,TowerAttackRange)==0 then for i=2,getn(MainTowerSupporterList[tostring(self)]),1 do ExecuteAction("NAMED_STOP",MainTowerSupporterList[tostring(self)][i]) end --MainTowerSupporterList[tostring(self)]=nil else if ObjectCountNearbyEnemies(self,TowerAttackRange)==0 then ExecuteAction("NAMED_STOP",self) end local MainTower = GetMyMainTower(self) if not IsTowerStillAttacking(MainTower) then MainTowerSupporterList[tostring(MainTower)]=nil else ExecuteAction("NAMED_STOP",self) ExecuteAction("NAMED_ATTACK_NAMED",self,MainTowerSupportConnectionList[tostring(MainTower)][tostring(self)]) end end end function getn2(table) local size = 0 for k,v in table do size=size+1 end return size end And for the scriptevents.xml: <EventList Name="NodObeliskEvents"> <!-- <EventHandler EventName="ATTACKING" ScriptFunctionName="CascadeForwarding" DebugSingleStep="false"/> --> <EventHandler EventName="PREATTACK_A" ScriptFunctionName="CascadeForwarding" DebugSingleStep="false"/> <!-- <EventHandler EventName="PREATTACK_B" ScriptFunctionName="CascadeForwarding" DebugSingleStep="false"/> --> <!-- <EventHandler EventName="FIRING_A" ScriptFunctionName="NodObelisk_FIRING_A" DebugSingleStep="false"/> --> <EventHandler EventName="RELOADING_A" ScriptFunctionName="NodObelisk_RELOADING" DebugSingleStep="false"/> <EventHandler EventName="RELOADING_C" ScriptFunctionName="NodObelisk_RELOADING" DebugSingleStep="false"/> </EventList> <ModelConditionEvent Name="PREATTACK_A"> <Conditions>+PREATTACK_A</Conditions> </ModelConditionEvent> <ModelConditionEvent Name="PREATTACK_B"> <Conditions>+PREATTACK_B</Conditions> </ModelConditionEvent> <ModelConditionEvent Name="FIRING_A"> <Conditions>+FIRING_A</Conditions> </ModelConditionEvent> <ModelConditionEvent Name="RELOADING_A"> <Conditions>+RELOADING_A</Conditions> </ModelConditionEvent> <ModelConditionEvent Name="RELOADING_C"> <Conditions>+RELOADING_C</Conditions> </ModelConditionEvent> <ModelConditionEvent Name="ATTACKING"> <Conditions>+ATTACKING</Conditions> </ModelConditionEvent> And here is the NodObelisk object and it's weapons and stuff, I've used: <?xml version="1.0" encoding="utf-8"?> <AssetDeclaration xmlns="uri:ea.com:eala:asset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude"> <Tags></Tags> <Includes> <Include type="all" source="ART:NBObelisk.w3x" /> <Include type="all" source="ART:NBObeliskA_SN.w3x" /> <Include type="all" source="ART:NBObeliskA_AN.w3x" /> <Include type="all" source="ART:NBObeliskD2_SN.w3x" /> <Include type="all" source="ART:NBObeliskD2_AN.w3x" /> <Include type="all" source="ART:NBObeliskD3_SN.w3x" /> <Include type="all" source="ART:NBObeliskD3_AN.w3x" /> <Include type="all" source="ART:FXObeliskLaser.xml" /> <Include type="all" source="ART:FXLaserOverlay.xml" /> <Include type="all" source="ART:NBObeliskCrstl.w3x" /> <Include type="all" source="DATA:GlobalData/GlobalDefines.xml" /> <Include type="all" source="ART:FXspotlight.w3x" /> <!-- Base Object --> <Include type="instance" source="DATA:BaseObjects/BaseStructure.xml" /> </Includes> <GameObject id="NODObelisk" inheritFrom="BaseStructure" SelectPortrait="Portrait_NODObeliskofLight" ButtonImage="Portrait_NODObeliskofLight" Side="NOD" EditorSorting="STRUCTURE" TransportSlotCount="1" BuildCost="2000" BuildTime="20" EnergyProduction="-15" CommandSet="NODObeliskCommandSet" KindOf="STRUCTURE SELECTABLE IMMOBILE CAN_CAST_REFLECTIONS FS_BASE_DEFENSE POWERED AUTO_ACQUIRABLE_BY_AI COVER CAN_ATTACK CAN_SEE_THROUGH_STRUCTURE ATTACK_NEEDS_LINE_OF_SIGHT LINE_OF_SIGHT_IGNORES_BUILDINGS" RadarPriority="STRUCTURE" PlacementViewAngle="315d" ProductionQueueType="OTHER_STRUCTURE" BuildPlacementTypeFlag="OTHER_STRUCTURE" EditorName="NODObelisk" WeaponCategory="CANNON" TypeDescription="Type:NODObelisk" Description="Desc:NODObelisk"> <DisplayName>Name:NODObelisk</DisplayName> <GameDependency> <RequiredObject>NODTechAssemblyPlant</RequiredObject> </GameDependency> <ArmorSet Armor="NodObeliskArmor" DamageFX="FactionStructureDamageFX" /> <SkirmishAIInformation BaseBuildingLocation="SPREAD" /> <Draws> <ScriptedModelDraw id="ModuleTag_01" OkToChangeModelColor="true" ExtraPublicBone="FXBONE01"> <ModelConditionState ParseCondStateType="PARSE_DEFAULT"> <Model Name="NBObelisk" /> <WeaponFireFXBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> <WeaponLaunchBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> </ModelConditionState> <ModelConditionState ParseCondStateType="PARSE_NORMAL" ConditionsYes="STRUCTURE_UNPACKING"> <Model Name="NBObeliskA_SN" /> <WeaponFireFXBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> <WeaponLaunchBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> </ModelConditionState> <ModelConditionState ParseCondStateType="PARSE_NORMAL" ConditionsYes="DAMAGED"> <Model Name="NBObeliskD2_SN" /> <WeaponFireFXBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> <WeaponLaunchBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> <ParticleSysBone BoneName="FXBone01" FXParticleSystemTemplate="NODObDamagedSteam" FollowBone="true" /> <ParticleSysBone BoneName="FXBone01" FXParticleSystemTemplate="NODObDamagedDist" FollowBone="true" /> </ModelConditionState> <ModelConditionState ParseCondStateType="PARSE_NORMAL" ConditionsYes="REALLYDAMAGED"> <Model Name="NBObeliskD2_SN" /> <WeaponFireFXBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> <WeaponLaunchBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> <ParticleSysBone BoneName="FXBone01" FXParticleSystemTemplate="NODObDamagedSpew" FollowBone="true" /> <ParticleSysBone BoneName="FXBone01" FXParticleSystemTemplate="NODObDamagedSpewDist" FollowBone="true" /> <ParticleSysBone BoneName="FXBone02" FXParticleSystemTemplate="NODObDamagedSmoke" FollowBone="true" /> </ModelConditionState> <ModelConditionState ParseCondStateType="PARSE_NORMAL" ConditionsYes="DYING"> <Model Name="NBObeliskD3_SN" /> <WeaponFireFXBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> <WeaponLaunchBone WeaponSlotType="PRIMARY_WEAPON" BoneName="FX_Weapon" /> </ModelConditionState> <AnimationState ParseCondStateType="PARSE_DEFAULT"></AnimationState> <!-- BUILD UP ANIMATION --> <AnimationState ParseCondStateType="PARSE_NORMAL" ConditionsYes="STRUCTURE_UNPACKING" StateName="STATE_Buildup"> <Animation AnimationName="NBObeliskA_AN" AnimationMode="ONCE" /> <ParticleSysBone BoneName="NONE" FXParticleSystemTemplate="Con_Small" FollowBone="true" /> </AnimationState> <AnimationState ParseCondStateType="PARSE_NORMAL" ConditionsYes="DAMAGED" StateName="STATE_Damaged" Flags="START_FRAME_FIRST"> <Animation AnimationName="NBObeliskD2_AN" AnimationMode="MANUAL" /> </AnimationState> <!-- REALLY DAMAGED ANIMATION --> <AnimationState ParseCondStateType="PARSE_NORMAL" ConditionsYes="REALLYDAMAGED" StateName="STATE_ReallyDamaged"> <Animation AnimationName="NBObeliskD2_AN" AnimationMode="ONCE" /> <Script> Prev = CurDrawablePrevAnimationState(); if Prev == "STATE_Damaged" then CurDrawableSetTransitionAnimState("TRANS_DamagedToReallyDamaged") end; </Script> </AnimationState> <!-- DYING ANIMATION --> <AnimationState ParseCondStateType="PARSE_NORMAL" ConditionsYes="DYING"> <Animation AnimationName="NBObeliskD3_AN" AnimationMode="ONCE" /> <ParticleSysBone BoneName="NONE" FXParticleSystemTemplate="Des_Small" FollowBone="false" /> </AnimationState> <!-- Transitions --> <AnimationState ParseCondStateType="PARSE_TRANSITION" ConditionsYes="TRANS_DamagedToReallyDamaged"> <Animation AnimationName="NBObeliskD2_AN" AnimationMode="ONCE" /> </AnimationState> </ScriptedModelDraw> <!-- DRAW CRYSTAL --> <ScriptedModelDraw id="ModuleTag_Draw_Crystal" OkToChangeModelColor="true"> <ModelConditionState ParseCondStateType="PARSE_DEFAULT"> <Model Name="NBObeliskCrstl" /> </ModelConditionState> <AnimationState ParseCondStateType="PARSE_DEFAULT" Flags="START_FRAME_FIRST"> <Animation AnimationName="NBObeliskCrstl" AnimationMode="MANUAL" /> </AnimationState> <AnimationState ParseCondStateType="PARSE_NORMAL" ConditionsYes="PREATTACK_A"> <Animation AnimationName="NBObeliskCrstl" AnimationMode="ONCE" /> <ParticleSysBone BoneName="FX_Weapon" FXParticleSystemTemplate="NODObeliskFireDistort" /> <ParticleSysBone BoneName="FX_Weapon" FXParticleSystemTemplate="NODObeliskFireGlow" /> </AnimationState> <AnimationState ParseCondStateType="PARSE_NORMAL" ConditionsYes="PREATTACK_C"> <Animation AnimationName="NBObeliskCrstl" AnimationMode="ONCE" /> <ParticleSysBone BoneName="FX_Weapon" FXParticleSystemTemplate="NODObeliskFireDistort" /> <ParticleSysBone BoneName="FX_Weapon" FXParticleSystemTemplate="NODObeliskFireGlow" /> </AnimationState> <AnimationState ParseCondStateType="PARSE_NORMAL" ConditionsYes="FIRING_A" Flags="START_FRAME_LAST"> <Animation AnimationName="NBObeliskCrstl" AnimationMode="MANUAL" /> </AnimationState> </ScriptedModelDraw> <SpotlightDraw id="ModuleTag_Spotlight" AttachToBoneInAnotherModule="FXBone01" RefreshTime="2.0s" SweepTime="1.0s"> <ModelConditionState ParseCondStateType="PARSE_DEFAULT"> <Model Name="FXspotlight" /> </ModelConditionState> </SpotlightDraw> <LaserDraw id="ModuleTag_LaserDraw" Texture1_UTile="1" Texture1_VTile=".5" Texture1_UScrollRate="0" Texture1_VScrollRate=".2" Texture1_NumFrames="1" Texture1_FrameRate="30" Texture2_UTile="1" Texture2_VTile=".03" Texture2_UScrollRate="0" Texture2_VScrollRate="1" Texture2_NumFrames="1" Texture2_FrameRate="30" LaserWidth="20" LaserStateID="1"> <FXShader ShaderName="Laser.fx" TechniqueIndex="0"> <Constants> <Texture Name="Texture1"> <Value>FXObeliskLaser</Value> </Texture> <Texture Name="Texture2"> <Value>FXLaserOverlay</Value> </Texture> </Constants> </FXShader> </LaserDraw> <LaserDraw id="ModuleTag_AntiInfantryLaserDraw" Texture1_UTile="1" Texture1_VTile=".5" Texture1_UScrollRate="0" Texture1_VScrollRate=".2" Texture1_NumFrames="1" Texture1_FrameRate="30" Texture2_UTile="1" Texture2_VTile=".03" Texture2_UScrollRate="0" Texture2_VScrollRate="1" Texture2_NumFrames="1" Texture2_FrameRate="30" LaserWidth="20" LaserStateID="2"> <FXShader ShaderName="Laser.fx" TechniqueIndex="0"> <Constants> <Texture Name="Texture1"> <Value>FXObeliskLaser</Value> </Texture> <Texture Name="Texture2"> <Value>FXLaserOverlay</Value> </Texture> </Constants> </FXShader> </LaserDraw> </Draws> <Behaviors> <WeaponSetUpdate id="ModuleTag_WeaponSetUpdate"> <WeaponSlotHardpoint ID="1"> <Weapon Ordering="PRIMARY_WEAPON" Template="NODObeliskLaser" /> <Weapon Ordering="SECONDARY_WEAPON" Template="NODObeliskAntiInfantryLaser" /> <Weapon Ordering="TERTIARY_WEAPON" Template="NODObeliskLaserSupport" /> </WeaponSlotHardpoint> </WeaponSetUpdate> <SpecialPower id="ModuleTag_PrismForwardingSpecialPower" SpecialPowerTemplate="SpecialPower_PrismForwarding" UpdateModuleStartsAttack="true"> </SpecialPower> <WeaponFireSpecialAbilityUpdate id="ModuleTag_PrismForwardingBeamUpdate" SpecialPowerTemplate="SpecialPower_PrismForwarding" SpecialWeapon="NODObeliskLaserSupport" StartAbilityRange="99999.0" UnpackTime="0s" WhichSpecialWeapon="1"> </WeaponFireSpecialAbilityUpdate> <LaserState id="ModuleTag_LaserState" LaserId="1" /> <SweepingLaserState id="ModuleTag_AntiInfantryLaserState" LaserId="2" Radius="25.0" SweepFXList="FX_NodLaserSweep" SweepWeapon="NODObeliskSweepWeapon" /> <SlowDeath id="ModuleTag_Death" SinkDelay="3.0s" SinkRate="4.0" DestructionDelay="8.0s"> <Sound Type="INITIAL" List="HumanFaction_SmallBuilding_DieMS" /> <DieMuxData DeathTypes="ALL" /> </SlowDeath> <StealthDetectorUpdate id="ModuleTag_StealthDetect" DetectionRange="200" /> <FXListBehavior id="ModuleTag_FXList"> <DieMuxData DeathTypes="ALL" /> <Event Index="onTransitionToDamaged" FX="FX_BuildDamaged_Medium" /> <Event Index="onTransitionToReallyDamaged" FX="FX_BuildDamaged_Medium" /> <Event Index="onTransitionToRubble" FX="FX_BuildDamaged_Medium" /> </FXListBehavior> <StructureUnpackUpdate UnpackTime="1.5s" /> <!--This is temporary and should be replaced by an inherited object--> <xi:include href="../../Includes/GenericBuildingRepair.xml" /> <xi:include href="../../Includes/GenericNODBuildingSuicide.xml" /> <xi:include href="../../Includes/RepairAlliesEngineerContain.xml" /> </Behaviors> <AI> <AIUpdate id="ModuleTag_AIUpdate" AutoAcquireEnemiesWhenIdle="YES" AILuaEventsList="NodObeliskEvents"> <UnitAITargetChooserData SympathyRange="25.0" /> </AIUpdate> </AI> <Body> <ActiveBody id="ModuleTag_ActiveBody" MaxHealth="7500.0" /> </Body> <ClientBehaviors> <ModelConditionAudioLoopClientBehavior id="ModuleTag_NOD_Obelisk_LaserChargeUp"> <ModelConditionSound Sound="NOD_Obelisk_LaserChargeUp" RequiredFlags="PREATTACK_A" ExcludedFlags="DYING" /> <ModelConditionSound Sound="NOD_Obelisk_LaserChargeUp" RequiredFlags="PREATTACK_C" ExcludedFlags="DYING" /> </ModelConditionAudioLoopClientBehavior> </ClientBehaviors> <Geometry IsSmall="false"> <Shape Type="CYLINDER" MajorRadius="18.0" Height="10.0"></Shape> <Shape Type="CYLINDER" MajorRadius="13.0" Height="10.0"> <Offset x="0" y="0" z="10" /> </Shape> <Shape Type="CYLINDER" MajorRadius="10.0" Height="10.0"> <Offset x="0" y="0" z="20" /> </Shape> <Shape Type="CYLINDER" MajorRadius="7.0" Height="15.0"> <Offset x="2" y="0" z="30" /> </Shape> <Shape Type="CYLINDER" MajorRadius="5.0" Height="15.0"> <Offset x="5" y="0" z="45" /> </Shape> <Shape Type="CYLINDER" MajorRadius="4.0" Height="14.0"> <Offset x="9" y="0" z="60" /> </Shape> <ContactPoint> <Pos x="-2.0" y="2.0" z="40" /> </ContactPoint> <ContactPoint> <Pos x="5.0" y="5.0" z="0" /> </ContactPoint> <ContactPoint> <Pos x="2.0" y="2.0" z="40" /> </ContactPoint> <ContactPoint> <Pos x="-5.0" y="-5.0" z="0" /> </ContactPoint> <ContactPoint> <Pos x="2.0" y="-2.0" z="40" /> </ContactPoint> <ContactPoint> <Pos x="5.0" y="-5.0" z="0" /> </ContactPoint> <ContactPoint> <Pos x="-2.0" y="-2.0" z="40" /> </ContactPoint> <ContactPoint> <Pos x="-5.0" y="5.0" z="0" /> </ContactPoint> </Geometry> <AudioArrayVoice> <AudioEntry Sound="NOD_ObeliskOfLightSelect" AudioType="voiceSelect" /> </AudioArrayVoice> <AudioArraySound> <AudioEntry Sound="HumanFaction_SmallBuilding_LightDamageMS" AudioType="soundOnDamaged" /> <AudioEntry Sound="HumanFaction_SmallBuilding_HeavyDamageMS" AudioType="soundOnReallyDamaged" /> </AudioArraySound> <ShadowInfo Type="VOLUME" /> <VisionInfo VisionRange="450" ShroudClearingRange="500" /> <ProjectedBuildabilityInfo Radius="10.0" BuildPlacementTypes="MAIN_STRUCTURE OTHER_STRUCTURE" /> </GameObject> <WeaponTemplate id="NODObeliskLaserSupport" Name="NODObeliskLaserSupport" AttackRange="375.0" CanFireWhileMoving="false" WeaponSpeed="999999.0" FireSound="NOD_Obelisk_LaserFireMS" RadiusDamageAffects="ALLIES" AcceptableAimDelta="180d" PreAttackType="PER_SHOT" ReAcquireDetailType="PRE_FIRE" ClipSize="1" AutoReloadsClip="AUTO"> <PreAttackDelay MinSeconds="2s" MaxSeconds="2s" /> <FiringDuration MinSeconds="1s" MaxSeconds="1s" /> <ClipReloadTime MinSeconds="1.0s" MaxSeconds="1.0s" /> <Nuggets> <ActivateLaserNugget Lifetime="0.75s" LaserId="1"> <SpecialObjectFilter Rule="NONE" Relationship="SAME_PLAYER"> <IncludeThing>NODObelisk</IncludeThing> </SpecialObjectFilter> </ActivateLaserNugget> <DamageNugget Damage="0.0" Radius="0.0" DelayTimeSeconds="0.1s" DamageType="CANNON" DamageFXType="NOD_LASER" DeathType="NORMAL"> <SpecialObjectFilter Rule="NONE" Relationship="SAME_PLAYER"> <IncludeThing>NODObelisk</IncludeThing> </SpecialObjectFilter> </DamageNugget> </Nuggets> </WeaponTemplate> <WeaponTemplate id="PrismTowerSupportWeapon" Name="PrismTowerSupportWeapon" RadiusDamageAffects="ALLIES" AttackRange="15000.0"> <Nuggets> <AttributeModifierNugget Radius="15000" PartitionFilterTestType="SPHERE" AttributeModifierName="AttributeModifier_PrismTowerSupport"> <SpecialObjectFilter Rule="ANY" Relationship="SAME_PLAYER"> <IncludeThing>NODObelisk</IncludeThing> </SpecialObjectFilter> </AttributeModifierNugget> </Nuggets> </WeaponTemplate> <AttributeModifier id="AttributeModifier_PrismTowerSupport" Category="BUFF" StackingLimit="999" Duration="4.0s"> <Modifier Type="DAMAGE_MULT" Value="100%"/> </AttributeModifier> <!-- actually not needed if solution via tertiary weapon --> <SpecialPowerTemplate id="SpecialPower_PrismForwarding" Flags="NEEDS_OBJECT_FILTER" TargetType="OBJECT"> <ObjectFilter Relationship="SAME_PLAYER" Rule="NONE"> <IncludeThing>NODObelisk</IncludeThing> </ObjectFilter> </SpecialPowerTemplate> <UnitAbilityButtonTemplate id="ButtonSpecialPower_PrismForwarding" LogicCommand="Command_SpecialPower_PrismForwarding"> <Data> <TargetedSpecialPower StateData="ButtonStateSpecialPower_PrismForwarding" ValidTargetCursor="Bombard" /> </Data> </UnitAbilityButtonTemplate> <ButtonSingleStateData id="ButtonStateSpecialPower_PrismForwarding"> <State Image="Portrait_NODObeliskofLight" Title="Name:NODObelisk"/> </ButtonSingleStateData> <LogicCommand Options="NEED_TARGET_ALLY_OBJECT" Type="SPECIAL_POWER" id="Command_SpecialPower_PrismForwarding"> <SpecialPower>SpecialPower_PrismForwarding</SpecialPower> </LogicCommand> <LogicCommandSet id="NODObeliskCommandSet"> <Cmd>Command_SpecialPower_PrismForwarding</Cmd> </LogicCommandSet> </AssetDeclaration>
  9. Oh sorry, that one function was missing. Simple math round: Let's see what comes next ;).
  10. Ok copy the now updated code and also all the helper functions from my main post and try again. For lua error logs use the following function and insert it into your scripts.lua file: function _ALERT(message) ExecuteAction("SHOW_MILITARY_CAPTION", "\n\n\n\n" .. tostring(message) .. "\n", 20) local file = "" local filehandle = openfile("ErrorLog",'a') if filehandle ~= nil then write(filehandle,"\n" .. "ErrorLogToFile(" .. date() .. "): " .. message) else local filehandle = writeto(file) write(filehandle,"\n" .. "ErrorLogToFile(" .. date() .. "): " .. message) end flush(filehandle) closefile(filehandle) end It will save/refresh a file called "ErrorLog" which will be in the same folder where your "cnc3game.dat" is placed. Send the logs to me then if you can't solve it. Else there must be a xml coding flaw somewhere we missed. Here some pictures of some more tests, also in first person mode which looks epic with all the towers doing their action at once:
  11. The only thing needed is the attacking unit/prism tower/obelisk or whatever to use that function on attacking: <ModelConditionEvent Name="BeginPreAttackA"> <Conditions>+PREATTACK_A</Conditions> </ModelConditionEvent> <EventList Name="PrismTower_EventList" Inherit="BaseScriptFunctions"> <EventHandler EventName="BeginPreAttackA" ScriptFunctionName="CascadeForwarding" DebugSingleStep="false"/> </EventList> No more broadcasting to other towers needed. That function (CascadeForwarding) handles everything else for you conveniently. I will possibly edit my main post above in the next days and change some lines and add all necessary helper functions needed for completness. It is indeed not a trivial script and also some more problems will possibly occur while setting everything up for the real prism tower. Just keep me updated and we will fix everything one by one. The things you need to change later for your `final product` is the ObjectHash, TowerAttackradius, MaximumSupportDistance and also adapt the content of the last two for loops according to your taste. For the hash you can actually set ObjectHash=tostring(tonumber(strsub(ObjectTemplateName(self), 6, 13), 16)) Also don`t forget to add the AttributeModifierWeapon and the special power (last two for loops). For the weapon and attribute modifier my idea was something like this maybe: <WeaponTemplate id="PrismTowerSupportWeapon" Name="PrismTowerSupportWeapon" RadiusDamageAffects="ALLIES" AttackRange="15000.0"> <Nuggets> <AttributeModifierNugget Radius="15000" PartitionFilterTestType="SPHERE" AttributeModifierName="AttributeModifier_PrismTowerSupport"> <SpecialObjectFilter Rule="ANY" Relationship="SAME_PLAYER"> </SpecialObjectFilter> </AttributeModifierNugget> </Nuggets> </WeaponTemplate> <AttributeModifier id="AttributeModifier_PrismTowerSupport" Category="NONE" StackingLimit="999" Duration="1.0s"> <Modifier Type="DAMAGE_MULT" Value="100%"/> </AttributeModifier> At least the duration needs adjustment and I^m not sure about the DAMAGE_MULT, as I^ve seen absolute as well as percent values.
  12. See the news blog for updates on development: http://www.moddb.com/mods/mjjstral/news/future-of-meta-mod
  13. Yes but first I want to finish the multiplayer compatibility code for meta mod in Kane`s Wrath.
  14. Mjjstral

    For anyone wanting the C&C4 mobile version

    In that context of C&C mobile gaming, I can recommend the "GPD WIN", an ultra portable pc with full windows 10 that fits in your pocket and can run all C&C games great! I even use it for programming and modding tasks sometimes.
  15. Ok here is my working solution, performance shouldn`t be a problem, although these algorithms could be more optimized if needed. function CascadeForwarding(self) self=GetObj.Table(self) local MaximumSupportDistance = 13000 local TowerAttackRange = 375 --here attack range of nod obelisk 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 EvaluateCondition("DISTANCE_BETWEEN_OBJ", GetObj.String(self),GetObj.String(v), CompareTable["<="], MaximumSupportDistance) and ObjectCountNearbyEnemies(v,TowerAttackRange)==0 then tinsert(ObjectList,v) end end end tinsert(ObjectList,self) --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) for i=2,getn(ObjectList),1 do local MainNodeCriteria = true local NextMainNode --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 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 SupportConnection[tostring(ObjectList[i])]=ObjectList[j] ShortestLinkToNextMainNodeDistance = LinkToNextMainNodeDistance end end end end end if MainNodeCriteria == true then tinsert(MainNodeTable,ObjectList[i]) SupportConnection[tostring(ObjectList[i])]=NextMainNode end end --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",ObjectList[i],"SpecialPower_PrismForwarding",SupportConnection[tostring(ObjectList[i])]) --ExecuteAction("NAMED_ATTACK_NAMED",ObjectList[i],SupportConnection[tostring(ObjectList[i])]) end end All necessary helper functions: GetObj={} function GetObj.String(object) if type(object) == "string" then return object else local _, count = gsub(ObjectDescription(object),"%(","") if count>1 then return strsub(ObjectDescription(object), strfind(ObjectDescription(object),"(",1,true)+1,strfind(ObjectDescription(object),")",1,true)-1) else local StrRef = "object" .. RandomString(5) ExecuteAction("SET_UNIT_REFERENCE", StrRef, object) return StrRef 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) end end return object end end function GetObj.Hash(object) return tostring(tonumber(strsub(ObjectTemplateName(GetObj.Table(object)), 6, 13), 16)) end CompareTable = { LT=0, LE=1, EQ=2, GE=3, GT=4, NE=5, ["<"]=0, ["<="]=1, ["=="]=2, [">="]=3, [">"]=4, ["~="]=5 } function GetObjectDistance(object1 ,object2, start_distance) if object1==nil or object2==nil or not EvaluateCondition("NAMED_NOT_DESTROYED",object1) or not EvaluateCondition("NAMED_NOT_DESTROYED",object2) then return 0 end object1=GetObj.String(object1) object2=GetObj.String(object2) local v = {} v.GetDistance = function(lowerlimit,upperlimit) local mid=(upperlimit+lowerlimit)/2 if upperlimit-lowerlimit<=1 then return lowerlimit elseif EvaluateCondition("DISTANCE_BETWEEN_OBJ", %object1, %object2, CompareTable["<"], mid) then return %v.GetDistance(lowerlimit,mid) else return round(%v.GetDistance(mid,upperlimit)) end end if start_distance then return v.GetDistance(0,tonumber(start_distance)) else return v.GetDistance(0,12870) end --maxdiagsize=ceil(sqrt(2*(7500+2*800)^2))) end function random(...) --overwritting lua native function for multiplayer compatibility local RandomNumber = function(a,b) return floor(a+((b-a)*GetRandomNumber())+0.5) end if getn(arg) == 0 then return floor(GetRandomNumber()+0.5) elseif getn(arg) == 1 then return RandomNumber(1,arg[1]) elseif getn(arg) == 2 then return RandomNumber(arg[1],arg[2]) else return arg[RandomNumber(1,getn(arg))] end end function RandomString(l) if l < 1 then l=5 end local s = "" local ascii_zone = {} for i=1,l,1 do ascii_zone[1] = random(97, 122) ascii_zone[2] = random(65, 90) ascii_zone[3] = random(48, 57) s = s .. strchar(ascii_zone[random(3)]) end return ("_" .. s) end To test in meta mod easily execute (button in meta command menu) tthe following with the LIVE_INPUT.lua in the MetaModIO folder: MainObelisk = spawn("NODObelisk") Then build your Nod Obelisk or any other unit able to attack around the main unit in any way, comment out the spawn code and execute: CascadeForwarding(MainObelisk) Hope that finally solves your problem in a decent way. It`s now up to you to adapt the code for your stuff.
  16. Right, just wanted to give a general solution first. If possible pure usage of EvaluateCondition("DISTANCE_BETWEEN_OBJ", object1, object2, 0, distance) should be a priority. Thanks, never noticed. The functions using it all work well though, so no big deal.
  17. I'm very confident that this is solvable, even for large cascade forwardings. Golan's approach wasn't bad, it just needs some more fine tuning I guess. To decide which tower will support or NOT support you can use this in addition to Golan's code: Use this function to test the minimum distances between the towers: function GetObjectDistance(object1 ,object2) if object1==nil or object2==nil or not EvaluateCondition("NAMED_NOT_DESTROYED",object1) or not EvaluateCondition("NAMED_NOT_DESTROYED",object2) then return 0 end local v = {} v.GetDistance = function(lowerlimit,upperlimit) local mid=(upperlimit+lowerlimit)/2 if upperlimit-lowerlimit<=1 then return lowerlimit elseif EvaluateCondition("DISTANCE_BETWEEN_OBJ", %object1, %object2, CompareTable[">"], mid) then return %v.GetDistance(lowerlimit,mid) else return round(%v.GetDistance(mid,upperlimit)) end end return v.GetDistance(0,12870) --maxdiagsize=ceil(sqrt(2*(7500+2*800)^2))) end CompareTable = { LT=0, LE=1, EQ=2, GE=3, GT=4, NE=5, [">"]=0, [">="]=1, ["=="]=2, ["<="]=3, ["<"]=4, ["~="]=5 } function GetObj.String(object) if type(object) == "string" then return object else local _, count = gsub(ObjectDescription(object),"%(","") if count>1 then return strsub(ObjectDescription(object), strfind(ObjectDescription(object),"(",1,true)+1,strfind(ObjectDescription(object),")",1,true)-1) else local StrRef = "object" .. RandomString(5) ExecuteAction("SET_UNIT_REFERENCE", StrRef, object) return StrRef end end end function RandomString(l) if l < 1 then l=5 end local s = "" local ascii_zone = {} for i=1,l,1 do ascii_zone[1] = random(97, 122) ascii_zone[2] = random(65, 90) ascii_zone[3] = random(48, 57) s = s .. strchar(ascii_zone[random(3)]) end return ("_" .. s) end Then you can use something like that: if GetObjectDistance(GetObj.String(self),GetObj.String(supporter))<150 and ObjectCountNearbyEnemies(supporter,SupportAttackRadius)>0 and ObjectCountNearbyEnemies(self,AttackRadius)>0 then ... end If I have time I can look more detailed into it. You could also avoid broadcasting and iterate through a list of all tower objects. In worst case a coroutine that gets called every n seconds and does all testing and proper attack distribution is also viable instead of every tower having to get triggered its own lua event.
  18. Exchange this line <Include type="all" source="Static/NODSaboteur.xml" /> with this <Include type="all" source="DATA:Static/NODSaboteur.xml" />
  19. Quick answer: Use modelcondition "LOADED". Long answer: You have two ways also depending on where you need to use it: 1. Use modelcondition "LOADED" as LuaEvent or within lua with ObjectTestModelCondition(object,modelconditionname). 2. Also within lua possible: EvaluateCondition("UNIT_HAS_PASSENGER",GetObj.String(object)) (GetObj.String is a metamod function) One general thing to help yourself in such cases: Use the lists ModelConditionList.txt, ObjectStatusList.txt and especially ALL_SAGE_LUA_COMMANDS.txt that come with metamod to find these things. In this case you could find out the modelcondition with metamod easily: 1. select a unit with passenger, 2. Open meta command menu 3. open selected unit info 4. (optional) write the info to a file and you get something like this written to the LIVE_OUTPUT.txt (which is very usefull for modders): Type: SteelTalonsRepairAPC Health: 100 IsAlive: true Position: x:261 y:81 KindOf: SELECTABLE CAN_ATTACK CAN_CAST_REFLECTIONS TRANSPORT PRELOAD SCORE ATTACK_NEEDS_LINE_OF_SIGHT CAN_REVERSE_MOVE VEHICLE CAN_BE_FAVORITE_UNIT ObjectStatus: CREATE_DRAWABLE_WITH_LOW_DETAIL ModelConditions: DOOR_1_CLOSING LOADED SELECTED Upgrades: ObjectPanelFlags: AI Recruitable Enabled Powered Selectable SpecialPowersReady: SpecialPower_TargetedRepairVehicle SpecialPowerGDI_APCMinefield Rank: 1 SkillPoints: 0 DistanceToBase: 120 ThreadLevel: 0 HasPassengers: 0 OrientationAngle: 0 NearbyEnemys(radius=300): 0 ObjectCanSufferFear: true ObjectOwner: Mjjstral ObjectOwnerFaction: SteelTalons ObjectOwnerIsAI: 0 ObjectTeamName: teamPlayer_2 ObjectTeamNameInternal: Player_2/teamPlayer_2 NumberOfSameTypeFromTeam: 1 NumberOfSameTypeFromAll: 1 IsSameTypeInsideBase: false ObjectNumber: 66 StringReference: object_O8zQk TableReference: table: 3958D1C8 ObjectPlayerSide: {0,0}38EA5BC0 ObjectDescription: Object 66 [steelTalonsRepairAPC, owned by player 3 (Mjjstral)] ObjectHash: 2093312067 ObjectTemplateName: {0,0}7CC56843 ObjectCapturingObjectPlayerSide: nil Hope that helps you
  20. Thank you, but the KW link leads to RA3 maps. How complete are these mappacks approx. in % from the pool of all public maps ever available? Does it also contain AOD/TD maps and all moddb maps? Also note that you can sometimes find some rare and custom mappacks posted on the steam community hubs.
  21. How do you even compile a .big if that should be the final product after the compilation? You can extract, decompile and view a .big... So what do you mean, please be more specific. If you can't compile things in general with the standard buildmod.bat (even for the SampleMod), then I have no idea.
  22. Mjjstral

    Help with old logics

    You can test if the compiled code has the correct structure by looking at it with wrathed.exe bigview. It's also possible to compare the .asset files with a hex editor 1. from a tw compiled peace of code thats working with 2. your wrathed compiled code. In worst case you can even create/modify the .asset yourself adjusting the binary code manually in a hexeditor and then put it to ModName/Assets/Static. Wrathed will automatically include it with the asset merger. For this way to begin you can extract a original .asset from the original kw files that has equal code. My guess for the weapon (because SpawnBehaviorModuleData uses it the same way for it's SpawnTemplate entry...): <Asset id="DamageAndSpawnNuggetType"> <EntryInheritance id="base" AssetType="DamageNuggetType" /> <Entry id="SpawnProbability" AssetType="SageReal" IsAttribute="true" Default="1.0" /> <Entry id="SpawnedModelConditionFlags" AssetType="ModelConditionBitFlags" IsAttribute="true" /> <EntryList id="SpawnTemplate" AssetType="GameObjectWeakRef" MinLength="0" MaxLength="0" /> </Asset>
  23. Did you also try to use a ModelConditionEvent?
  24. Just a random idea: Use "ReplaceSelfUpgrade" module to get an equal object but which has an additional "SpawnUnitBehavior" or "SpawnBehavior" module that can give you the (slaved) drone. Give the drone a "SlavedUpdate" module (see here). But wait maybe you can do it without ReplaceSelfUpgrade cause SpawnUnitBehavior has a LogicCommand entry so there might be a direct way. SpawnUnitBehavior was only used in BFME II and ROTWK but seems to be still in the C&C3 game.
  25. That's completely wrong, check the first line in the skudef. That's interesting, you mean there is a 1.00 and/or 1.1 cnc3ep1.dat ? Never have seen these cause I use the steam version of the game which doesn't provide these files. Thanks for clarification my dear Lauren. But if the askers problem is a cnc3ep1.dat issue it can get difficult, cause you need to disassemble. Non the less if you succeed please share a delta patch of your changes with us
×