Madin 11 Posted June 6, 2017 So I am trying to add the functionality of the RA3 Veteran academy (a neutral tech structure that upon capture causes all units produced by the side that has captured it veterancy) into C&C3. The method that I am using has the production structures allowed to produce veteran units due to the fact that the veteran academy upgrading their rank. The issue is that I cannot remove the production structures rank level, if the veteran academy is captured by the enemy team, or if it is destroyed. Here is the veteran academy xml code: <!-- Send attribute modifier to owner teams structures --> <AttributeModifierAuraUpdate id="ModuleTag_AttributeModifierAuraUpdate" AttributeModifierName="VeteranAcademy_AttributeModifier" RefreshDelay="1.0s" Range="99999" AffectHordeMembersOnly="false" InitiallyActive="true"> <ObjectFilter Rule="NONE" Relationship="SAME_PLAYER" Include="STRUCTURE"></ObjectFilter> </AttributeModifierAuraUpdate> <!-- Attribute modifier sets a model condition in the target building, for Script events to read --> <AttributeModifier id="VeteranAcademy_AttributeModifier" Category="NONE" Duration="1.5s" ModelConditionsSet="USER_60"></AttributeModifier> <!-- An upgrade for Lua to use --> <UpgradeTemplate id="Upgrade_AddVeterancyLevel" Type="OBJECT" /> Here is a sample production structure xml code, the production structures have the required extra experience level templates coded in: <!-- The upgrade is added to the object via Lua, the level must be higher than rank 2 for veteran unit production --> <LevelUpUpgrade id="ModuleTag_LevelUpUpgrade_VeteranAcademy" LevelCap="4" LevelsToGain="3" DoFlash="false"> <TriggeredBy>Upgrade_AddVeterancyLevel</TriggeredBy> </LevelUpUpgrade> <!-- 'VeteranUnitsFromVeteranFactory' = true, added --> <ProductionUpdate id="ModuleTag_ProductionUpdate" GiveNoXP="true" Type="VEHICLE" NumDoorAnimations="1" DoorOpeningTime="0.66s" DoorWaitOpenTime="3.00s" DoorCloseTime="0.66s" VeteranUnitsFromVeteranFactory="true" /> Here is the Scriptevents code: <!-- Model condition provided by Veteran Academies attribute modifier --> <ModelConditionEvent Name="AddVeterancy"> <Conditions>+USER_60</Conditions> </ModelConditionEvent> <ModelConditionEvent Name="RemoveVeterancy"> <Conditions>-USER_60</Conditions> </ModelConditionEvent> <EventList Name="SovietWarfactoryFunctions" Inherit="BaseScriptFunctions"> <EventHandler EventName="AddVeterancy" ScriptFunctionName="OnAddVeterancyRecieved" DebugSingleStep="false"/> <EventHandler EventName="RemoveVeterancy" ScriptFunctionName="OnRemoveVeterancyRecieved" DebugSingleStep="false"/> </EventList> Here is the production Lua code: -- This function works function OnAddVeterancyRecieved(self) if ObjectHasUpgrade( self, "Upgrade_Veterancy_VETERAN" ) == 0 then ObjectGrantUpgrade( self, "Upgrade_AddVeterancyLevel" ) end end -- This function does not work function OnRemoveVeterancyRecieved(self) ExecuteAction("UNIT_SET_EXPERIENCE_POINTS", self, 1) end To experience coders it should be obvious that I am struggling with how to remove the structures rank. I am not sure if it is possible in C&C3. Any ideas? Share this post Link to post
Stygs 25 Posted June 6, 2017 (edited) Dumb question, but istn there a easier way? 1. Give every unit (BaseObject) a LevelUpUpgrade that gets triggered by a ObjectUpgrade and grants 1 level. (or even better: use Upgrade_Veterancy_VETERAN, that allready fuly coded if I remeber right). 2. Have the academy grant a player upgrade upon capture (and remove it once the buildings gets lost). 3. Use the OnCreated Event on the units to trigger a function that checks for the player upgrade - if the player has the acadamy upgrade, the script grants the unit the object upgrade and the unit gains a level. Edited June 6, 2017 by Stygs 1 Share this post Link to post
Madin 11 Posted June 7, 2017 3 hours ago, Stygs said: Dumb question, but istn there a easier way? 2. Have the academy grant a player upgrade upon capture (and remove it once the buildings gets lost). But that is my issue, how to remove the upgrade. There is the 'UpgradeDie' module, but the tech building is not dying if another side captures it. However I could try broadcasting the attribute modifier directly to units, and then have the units 'OnCreated' check for the modelcondition 'USER_60', and if there, upgrade a level. The existing Level code in the base object uses a 'PLAYER' upgrade, I would use the 'OBJECT' code I have. So good ideas. Share this post Link to post
Madin 11 Posted June 7, 2017 Well that never worked at all. Units are not getting upgraded, the 'OnCreated' is probably too early for the model condition to be received. Share this post Link to post
Lauren 78 Posted June 7, 2017 Why not just check if the player owns one of these buildings in the OnCreate? Share this post Link to post
Madin 11 Posted June 7, 2017 9 hours ago, Lauren said: Why not just check if the player owns one of these buildings in the OnCreate? Using Lua? I tried this, but it never worked: function OnSovietTankKillerCreated(self) if ExecuteAction("NAMED_OWNED_BY_PLAYER", "SubwayHub", self) == 1 then ExecuteAction("SHOW_MILITARY_CAPTION", "HAS_VETERAN_ACADEMY", 5) end I'll check if there is anything else. Share this post Link to post
Stygs 25 Posted June 7, 2017 13 hours ago, Madin said: But that is my issue, how to remove the upgrade. There is the 'UpgradeDie' module, but the tech building is not dying if another side captures it. How about a dummy drone? The building spawns the drone and kills it if captured or destroyed while the drone itself grants/removes the upgrade when killed by the sturcture. Of course, that might not work if the player can have more than one academy. Share this post Link to post
Madin 11 Posted June 7, 2017 1 minute ago, Stygs said: How about a dummy drone? The building spawns the drone and kills it if captured or destroyed while the drone itself grants/removes the upgrade when killed by the sturcture. Of course, that might not work if the player can have more than one academy. What I currently have is a Model condition event that requires: <ModelConditionEvent Name="AddVeterancy"> <Conditions>+COMING_OUT_OF_FACTORY +USER_60</Conditions> </ModelConditionEvent> I have greatly decreased the Attribute aura refresh time: <AttributeModifierAuraUpdate id="ModuleTag_AttributeModifierAuraUpdate" AttributeModifierName="VeteranAcademy_AttributeModifier" RefreshDelay="0.25s" Range="99999" AffectHordeMembersOnly="false" InitiallyActive="true"> <ObjectFilter Rule="ALL" Relationship="SAME_PLAYER" Exclude="STRUCTURE"></ObjectFilter> </AttributeModifierAuraUpdate> To better catch units that would most likely be coming from multiple factories. I am then using the script: function OnAddVeterancyRecieved(self) if ObjectHasUpgrade( self, "Upgrade_Veterancy_VETERAN" ) == 0 then ObjectGrantUpgrade( self, "Upgrade_AddVeterancyLevel" ) ExecuteAction("SHOW_MILITARY_CAPTION", "UPGRADE_COMPLETE", 5) end end Currently this works on vehicles, when the academy is captured, and stops if it is destroyed, captured by enemy. It does not give infantry experience, I will probably have to add the level upgrade code to the BaseSquad object. I am using the base script function, so that the code is inherited by everything that has a Lua event list. Together with the code that resides in the baseObject of infantry and vehicles, it is saving a load of work. <EventList Name="BaseScriptFunctions"> <!-- If there are any events that need to apply to all units, put them here. jba --> <EventHandler EventName="AddVeterancy" ScriptFunctionName="OnAddVeterancyRecieved" DebugSingleStep="false"/> </EventList> I am currently testing this, although it is not a stress test. Share this post Link to post
Mjjstral 25 Posted June 7, 2017 However you want to do in the end, here some more input: For giving a specific veterancy level to a unit you can use ExecuteAction("UNIT_GIVE_EXPERIENCE_LEVEL", ObjectStringName, ExperienceLevelTemplateName) For experience templates look into the ExperienceLevels.xml from the C&C3 modsdk source code. In meta mod I made this function (copy code dependencies if you want to use it): function SetObjectsRank(object,rank,objecttype) if objecttype == nil then objecttype=GetObj.Type(object) end ExecuteAction("UNIT_GIVE_EXPERIENCE_LEVEL",GetObj.String(object),objecttype .. ExperienceLevel_ .. rank) end There is also: ObjectCapturingObjectPlayerSide(object) --if not captured before returns nil, so test if ~= nil ObjectTeamName(object) --to associate veterancy production building with a team, store each b. into a table OnCreate For removing player upgrades there is of course ExecuteAction("REMOVE_PLAYER_UPGRADE",...) but we still have no way of using the player parameter for scripts without tricks. Same goes for EvaluateCondition("NAMED_OWNED_BY_PLAYER",GetObj.String(self),PlayerName) But you can use: <RemoveUpgradeUpgrade id="ModuleTag_RemoveUpgradeUpgrade_01"> <TriggeredBy>Upgrade_TestUpgrade1</TriggeredBy> <UpgradeToRemove>Upgrade_TestUpgrade2</UpgradeToRemove> </RemoveUpgradeUpgrade> <RemoveUpgradeUpgrade id="ModuleTag_RemoveUpgradeUpgrade_02"> <TriggeredBy>Upgrade_TestUpgrade2</TriggeredBy> <UpgradeToRemove>Upgrade_TestUpgrade1</UpgradeToRemove> </RemoveUpgradeUpgrade> And then use lua event OnDestroyed and trigger ObjectGrantUpgrade(self, "Upgrade_TestUpgradeX"). 1 Share this post Link to post
Madin 11 Posted June 7, 2017 Some interesting information, thanks to everyone for the help. What I have now 'works'. I will do further testing in the future to see if there are any issues in an extended play test. Share this post Link to post