lamaros Posted February 26, 2016 Author Share Posted February 26, 2016 Back in a different direction, on structs. If I understand this correctly you use this to create a single array, with each entry in the array having three variables. How do I populate this array though? By making these variables arrays, in effect just using the struct to bring them together into a single array? Is there any good guide to unreal script anywhere? I feel like I'm missing so many basic concepts that I'm hitting the wall too often... struct RandomChange { var array<UnitName> Target; var array<UnitStat> StatType; var array<UnitRandAmount> Amount; } var array<RandomChange> RandomChanges; Link to comment Share on other sites More sharing options...
eXecator Posted February 26, 2016 Share Posted February 26, 2016 You can populate an array like this var array<Whatever> SomeStuff; var Whatever Thingy; SomeStuff.AddItem(Thingy); I got my unrealscript knowledge from the officilal referencehttps://udn.epicgames.com/Three/UnrealScriptReference.html but there gota be some tutuorials out there. Link to comment Share on other sites More sharing options...
Deleted32045420User Posted February 26, 2016 Share Posted February 26, 2016 (edited) Ok i got it working, here's the code: Main Code for randomising function RandomEnemyStats(XComGameState_Unit Unit) { local array<int> EnemyCosts; local array<ECharStatType> Stats; local array<int> EnemyStatChanges; local array<int> BaseModifiers; local int points; local bool PointCheck; local int j; local int currentStat; local float tempF; local array<int> RandomStats; local X2CharacterTemplate UnitTemplate; if(bIs_Epigenetics_Activated) { EnemyCosts=GetCosts(); Stats=GetStats(); do { `log(""); points=TotalPoints_Enemy; PointCheck=true; for(j=0;j<10;j=j++) { currentStat=GetRandonStat(Unit,Stats[j]); points-=GetDefaultPoints(Unit,currentStat,EnemyCosts[j],Stats[j]); RandomStats.addItem(currentStat); } `log("Points:"@points); //`log("out of forloop"); if(ABS(points)>=TOLERANCE) { RandomStats.remove(0,RandomStats.Length); PointCheck=false; //`log("PointCheck=false" @points); } } Until(PointCheck==true); Unit.setBaseMaxStat(eStat_HP,RandomStats[0]); Unit.setBaseMaxStat(eStat_Offense,RandomStats[1]); Unit.setBaseMaxStat(eStat_Defense,RandomStats[2]); Unit.setBaseMaxStat(eStat_Mobility,RandomStats[3]); Unit.setBaseMaxStat(eStat_Will,RandomStats[4]); Unit.setBaseMaxStat(eStat_Dodge,RandomStats[5]); Unit.setBaseMaxStat(eStat_ArmorMitigation,RandomStats[6]); Unit.setBaseMaxStat(eStat_ArmorChance,100.00f); Unit.setBaseMaxStat(eStat_SightRadius,RandomStats[7]); Unit.setBaseMaxStat(eStat_PsiOffense,RandomStats[8]); Unit.setBaseMaxStat(eStat_FlankingCritChance,RandomStats[9]); Unit.setCurrentStat(eStat_HP,RandomStats[0]); Unit.setCurrentStat(eStat_Offense,RandomStats[1]); Unit.setCurrentStat(eStat_Defense,RandomStats[2]); Unit.setCurrentStat(eStat_Mobility,RandomStats[3]); Unit.setCurrentStat(eStat_Will,RandomStats[4]); Unit.setCurrentStat(eStat_Dodge,RandomStats[5]); Unit.setCurrentStat(eStat_ArmorMitigation,RandomStats[6]); Unit.setCurrentStat(eStat_ArmorChance,100.00f); Unit.setBaseMaxStat(eStat_SightRadius,RandomStats[7]); Unit.setBaseMaxStat(eStat_PsiOffense,RandomStats[8]); Unit.setBaseMaxStat(eStat_FlankingCritChance,RandomStats[9]); Unit.UnitSize=(0.0006*points*points)+(0.025*points)+1; `log("Stat:HP" @RandomStats[0]); `log("Stat:Aim" @RandomStats[1]); `log("Stat:Defense" @RandomStats[2]); `log("Stat:Mobility" @RandomStats[3]); `log("Stat:Will" @RandomStats[4]); `log("Stat:Dodge" @RandomStats[5]); `log("Stat:Armor" @RandomStats[6]); `log("Stat:SightRadius" @RandomStats[7]); `log("Stat:PsiOffense" @RandomStats[8]); `log("Stat:FlankCritChance" @RandomStats[9]); } } All the actual randomisation function int GetRandomSign() { local int i; i=Rand(2); //`log ("got a random"@i); if(i==1) return 1; else return -1; } function float GetUnitStatModifier(XComGameState_Unit Unit,ECharStatType Stat) { local array<int> BaseStats; BaseStats=GetBaseModifiers(); if(Stat==eStat_HP) return (Unit.GetBaseStat(Stat)/BaseStats[0]); else if(Stat==eStat_Offense) return (Unit.GetBaseStat(Stat)/BaseStats[1]); else if(Stat==eStat_Defense) return (Unit.GetBaseStat(Stat)/BaseStats[2]); else if(Stat==eStat_Mobility) return (Unit.GetBaseStat(Stat)/BaseStats[3]); else if(Stat==eStat_Will) return (Unit.GetBaseStat(Stat)/BaseStats[4]); else if(Stat==eStat_Dodge) return (Unit.GetBaseStat(Stat)/BaseStats[5]); else if(Stat==eStat_ArmorMitigation) return (Unit.GetBaseStat(Stat)/BaseStats[6]); else if(Stat==eStat_SightRadius) return (Unit.GetBaseStat(Stat)/BaseStats[7]); else if(Stat==eStat_PsiOffense) return (Unit.GetBaseStat(Stat)/BaseStats[8]); else if(Stat==eStat_FlankingCritChance) return (Unit.GetBaseStat(Stat)/BaseStats[9]); } function int GetRandonStat(XComGameState_Unit Unit,ECharStatType Stat) { local int tempRet; if(Stat==eStat_HP) tempRet=int( FMAX(2,Round(Rand(1+HP_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_Mobility) tempRet= int(FMAX(10,Round(Rand(1+Mobility_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_Offense) tempRet= int(FMAX(1,Round(Rand(1+Offense_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_Defense) tempRet= int(FMAX(0,Round(Rand(1+Defense_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_Will) tempRet= int(FMAX(0,Round(Rand(1+Will_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_ArmorMitigation) tempRet= int(FMAX(0,Round(Rand(1+ArmorMitigation_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_SightRadius) tempRet= int(FMAX(10,Round(Rand(1+SightRadius_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_PsiOffense) tempRet= int(FMAX(0,Round(Rand(1+PsiOffense_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); else if(Stat==eStat_FlankingCritChance) tempRet= int(FMIN(100,FMAX(0,Round(Rand(1+FlankCrit_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat))))); else if(Stat==eStat_Dodge) tempRet= int(FMAX(0,Round(Rand(1+Dodge_Range)*GetRandomSign()*GetUnitStatModifier(Unit,Stat) + Unit.GetBaseStat(Stat)))); Return tempRet; } Utility functions function int GetDefaultPoints(XComGameState_Unit Unit,int CurrentStat,int StatCost,ECharStatType Stat) { `log(Stat @"Cost:" @(CurrentStat-Unit.GetBaseStat(Stat))*StatCost); return (CurrentStat-Unit.GetBaseStat(Stat))*StatCost; } function array<int>GetCosts() { local array<int> ToRet; ToRet.AddItem(HP_cost_Enemy); ToRet.AddItem(Offense_cost_Enemy); ToRet.AddItem(Defense_cost_Enemy); ToRet.AddItem(Mobility_cost_Enemy); ToRet.AddItem(Will_cost_Enemy); ToRet.AddItem(Dodge_cost_Enemy); ToRet.AddItem(ArmorMitigation_cost_Enemy); ToRet.AddItem(SightRadius_cost_Enemy); ToRet.AddItem(PsiOffense_cost_Enemy); ToRet.AddItem(FlankCrit_cost_Enemy); return ToRet; } function array<int>GetBaseModifiers() { local array<int> ToRet; ToRet.AddItem(8); ToRet.AddItem(80); ToRet.AddItem(10); ToRet.AddItem(12); ToRet.AddItem(50); ToRet.AddItem(20); ToRet.AddItem(1); ToRet.AddItem(27); ToRet.AddItem(120); ToRet.AddItem(33); return ToRet; } function array<ECharStatType>GetStats() { local array<ECharStatType> ToRet; ToRet.AddItem(eStat_HP); ToRet.AddItem(eStat_Offense); ToRet.AddItem(eStat_Defense); ToRet.AddItem(eStat_Mobility); ToRet.AddItem(eStat_Will); ToRet.AddItem(eStat_Dodge); ToRet.AddItem(eStat_ArmorMitigation); ToRet.AddItem(eStat_SightRadius); ToRet.AddItem(eStat_PsiOffense); ToRet.AddItem(eStat_FlankingCritChance); return ToRet; } Edited February 26, 2016 by Guest Link to comment Share on other sites More sharing options...
lamaros Posted February 27, 2016 Author Share Posted February 27, 2016 Good work, I think I mostly follow. I'm stuck on working out how to ask XComGameState_Unit what the unit type/name is for if i wanted to alter this to modify different ones in custom ways, though. Going to run myself through some java lessons so I get a better understanding of how the OOP bit work. Link to comment Share on other sites More sharing options...
Deleted32045420User Posted February 27, 2016 Share Posted February 27, 2016 you can use the Unit.GetMyTemplate() for character template and Unit.GetTemplateName()(might be Unit.GetMyTemplateName() ) Link to comment Share on other sites More sharing options...
lamaros Posted February 27, 2016 Author Share Posted February 27, 2016 I've been poking about your code ElaDdv. Have you used a different way to get the random stats for enemies function to run than you did for the soldier stats? Under the Downloadablecontent info you're still only going with: foreach `XCOMHISTORY.IterateByClassType(class'XComGameState_Unit', Unit ) { `log("Mod Foreach"); SecondWaveObject.RandomStats(Unit); } It's just brought in by the UIAvengerHUD_Listener? function EventListenerReturn Epigenetics(Object EventData, Object EventSource, XComGameState GameState, Name EventID) { local XComGameState_SecondWave Randomiser; Randomiser= new class 'XComGameState_SecondWave'; if(XComGameState_Unit(EventSource).GetTeam() == eTeam_Alien) { `log("An Enemy Unit was NCEd"); Randomiser.RandomEnemyStats(XComGameState_Unit(EventSource)); } return ELR_NoInterrupt; } Link to comment Share on other sites More sharing options...
Deleted32045420User Posted February 27, 2016 Share Posted February 27, 2016 I've been poking about your code ElaDdv. Have you used a different way to get the random stats for enemies function to run than you did for the soldier stats? Under the Downloadablecontent info you're still only going with: foreach `XCOMHISTORY.IterateByClassType(class'XComGameState_Unit', Unit ) { `log("Mod Foreach"); SecondWaveObject.RandomStats(Unit); } It's just brought in by the UIAvengerHUD_Listener? function EventListenerReturn Epigenetics(Object EventData, Object EventSource, XComGameState GameState, Name EventID) { local XComGameState_SecondWave Randomiser; Randomiser= new class 'XComGameState_SecondWave'; if(XComGameState_Unit(EventSource).GetTeam() == eTeam_Alien) { `log("An Enemy Unit was NCEd"); Randomiser.RandomEnemyStats(XComGameState_Unit(EventSource)); } return ELR_NoInterrupt; } Yeah i did, since soldier stats are permanent i can change them on game launch and when they are created(like the end of each month or when you get rookies from a scan). Now Enemies are created on individual missions so i have to check for their creation and there is no simpler way to do that then with a listener for 'OnUnitBeginPlay' and then sort by eTeam. Link to comment Share on other sites More sharing options...
lamaros Posted February 27, 2016 Author Share Posted February 27, 2016 (edited) Worked out the issue, nothing to see here. Edited February 27, 2016 by lamaros Link to comment Share on other sites More sharing options...
lamaros Posted February 28, 2016 Author Share Posted February 28, 2016 (edited) Ok, so I've hit a wall with this. My current understanding is not up to solving, so I'll have to learn more and return to it in the future. For others who might be interested here is what we (almost all EladDv's code) have at the moment, stripped back to try and debug. Here is XComGameState_NCE.uc class XComGameState_NCE extends Object Config(NCE); //-----NCE Vars----- var int vfiLength; var int points; //-----Config Vars Enemy----- var config bool bIs_EnemyNCE_Activated; var config int EnemyHP_randNCE; var config int EnemyHP_cost; var config int EnemyArmorMitigation_randNCE; var config int EnemyArmorMitigation_cost; var config int EnemyTotalPoints; var config int EnemyTolerance; //-----NCE Enemy Units----- function RandomEnemyStats(XComGameState_Unit Unit) { local array<ECharStatType> statGroup; local int Costs[2]; local int ValuesFromINI[2]; local int BaseEnemyValues[2]; local int vfiLength; local int points; local bool PointCheck; local int j,Count; local int currentStat; local array<int> RandomStats; local int testing; local int testing2; local int testing3; testing = Unit.GetMyTemplate().CharacterBaseStats[eStat_HP]; testing2 = Unit.getCurrentStat(eStat_HP); testing3 = Unit.getBaseStat(eStat_HP); statGroup.AddItem(eStat_HP); statGroup.AddItem(eStat_ArmorMitigation); `log("Has Vanilla Stats? " @HasVanillaStats(Unit)); if(bIs_EnemyNCE_Activated&&HasVanillaStats(Unit)) { `log("NCE Enemy Activated"); `log("HP template at start " @testing); `log("HP current stat at start " @testing2); `log("HP base stat at start " @testing3); Costs[0]=EnemyHP_cost; Costs[1]=EnemyArmorMitigation_cost; ValuesFromINI[0]=EnemyHP_randNCE; ValuesFromINI[1]=EnemyArmorMitigation_randNCE; BaseEnemyValues[0]=Unit.getCurrentStat(eStat_HP)-(ValuesFromINI[0]/2); BaseEnemyValues[1]=Unit.getCurrentStat(eStat_ArmorMitigation); vfiLength=2; do { points=EnemyTotalPoints; PointCheck=true; for(j=0;j<vfiLength;j=j+1) { currentStat=(Rand((ABS(ValuesFromINI[j]))+1)); points-=(currentStat*Costs[j]); RandomStats.addItem(BaseEnemyValues[j]+currentStat); } if(ABS(points)>=EnemyTolerance&&Count<75) { RandomStats.remove(0,RandomStats.Length); PointCheck=false; Count++; } else if(Count>75) { `log("too much counting"); } } Until(PointCheck==true); for (j=0;j<vfiLength;j=j+1) { Unit.setBaseMaxStat(statGroup[j],RandomStats[j]); Unit.setCurrentStat(statGroup[j],RandomStats[j]); } Unit.setBaseMaxStat(eStat_ArmorChance,100.00f); Unit.setCurrentStat(eStat_ArmorChance,100.00f); testing = Unit.GetMyTemplate().CharacterBaseStats[eStat_HP]; testing2 = Unit.getCurrentStat(eStat_HP); testing3 = Unit.getBaseStat(eStat_HP); `log("HP template stat at end " @testing); `log("HP current stat at end " @testing2); `log("HP base stat at end " @testing3); `log("Enemy Stats Reported"); } else if (!(bIs_EnemyNCE_Activated&&HasVanillaStats(Unit))) { `log("NCE Enemy Not Active"); `log("HP template stat not active at " @testing); `log("HP current stat not active at " @testing2); `log("HP base stat not active at " @testing3); } } //-----Support Functions----- function array<ECharStatType>GetStats() { local array<ECharStatType> ToRet; ToRet.AddItem(eStat_HP); ToRet.AddItem(eStat_ArmorMitigation); return ToRet; } function bool HasVanillaStats(XComGameState_Unit Unit) { local int tempStat; local int baseStat; local int i; local int count; local array<ECharStatType> Stats; count = 0; Stats = GetStats(); tempStat = Unit.GetMyTemplate().CharacterBaseStats[Stats[i]]; baseStat = Unit.getBaseStat(Stats[i]); for(i=0;i<Stats.length;i++) { if(tempStat==baseStat) { count++; } } if (count>1) return true; else return false; } Here is XComNCE.ini ;Not Created Equal Configuration ;--------------------------------------- [ExtendedFights.XComGameState_NCE] ;-----Enemy Configuration----- bIs_EnemyNCE_Activated=True; Is Not Created Equally Active? ;Randomise Negative and Positive, values are the total range EnemyHP_randNCE=2 EnemyHP_cost=10 ;Randomise Positive Only, values are the total range EnemyArmorMitigation_randNCE=1 EnemyArmorMitigation_cost=20 EnemyTotalPoints=20 ; Total Points allocated to stats. EnemyTolerance=0 And here is where it's trying to hook in with UIAvengerHUD_Listener_NCE.uc class UIAvengerHUD_Listener_NCE extends UIScreenListener Config(NCE); // Set this value in the defaultproperties to filter UI signals based on class var class<UIScreen> ScreenClass; event OnInit(UIScreen Screen) { local Object ThisObj; ThisObj=self; `XEVENTMGR.RegisterForEvent(ThisObj, 'OnUnitBeginPlay', Epigenetics); } function EventListenerReturn Epigenetics(Object EventData, Object EventSource, XComGameState GameState, Name EventID) { local XComGameState_NCE Randomiser; Randomiser= new class 'XComGameState_NCE'; `log("NCE Enemy Start"); if(XComGameState_Unit(EventSource).GetTeam() == eTeam_Alien) { `log("Trying to randomise enemy unit"); Randomiser.RandomEnemyStats(XComGameState_Unit(EventSource)); } return ELR_NoInterrupt; } defaultproperties { // Leaving this assigned to none will cause every screen to trigger its signals on this class ScreenClass = UIAvengerHUD; } And here is what the debug log is saying: http://imgur.com/a/YegYx (that the base stats and current stats have been changed) Yet despite this all enemy units have default stats. Edited February 28, 2016 by lamaros Link to comment Share on other sites More sharing options...
lamaros Posted February 28, 2016 Author Share Posted February 28, 2016 (edited) So, under the X2Character Template we have, function XComGameState_Unit CreateInstanceFromTemplate(XComGameState NewGameState) { local XComGameState_Unit Unit; Unit = XComGameState_Unit(NewGameState.CreateStateObject(class'XComGameState_Unit')); Unit.OnCreation(self); return Unit; } Is this of any relevance? I wish I knew what I was doing... And this this tracks back to XComAISpawnManager? private event XComGameState_Unit CreateUnitInternal( Vector Position, X2CharacterTemplate CharacterTemplate, ETeam Team, XComGameState NewGameState, bool bRollForLoot, bool PerformAIUpdate, XComGameState_Unit ReanimatedFromUnit, optional string CharacerPoolName ) { local XComGameStateHistory History; local XComGameState_Unit UnitState; local XComGameState_Player PlayerState; local bool bUsingStartState, bFoundExistingPlayerState; local TTile UnitTile; History = `XCOMHISTORY; bUsingStartState = (NewGameState == History.GetStartState()); // find the player matching the requested team ID... foreach History.IterateByClassType(class'XComGameState_Player', PlayerState) { if( PlayerState.GetTeam() == Team ) { bFoundExistingPlayerState = true; break; } } // ... or create one if it does not yet exist if( !bFoundExistingPlayerState ) { PlayerState = class'XComGameState_Player'.static.CreatePlayer(NewGameState, Team); NewGameState.AddStateObject(PlayerState); } // create the unit UnitTile = `XWORLD.GetTileCoordinatesFromPosition(Position); UnitState = CharacterTemplate.CreateInstanceFromTemplate(NewGameState); UnitState.PostCreateInit(NewGameState, CharacterTemplate, PlayerState.ObjectID, UnitTile, Team == eTeam_Alien, bUsingStartState, PerformAIUpdate, ReanimatedFromUnit, CharacerPoolName); // Auto loot UnitState.bAutoLootEnabled = bRollForLoot; //// Timed Loot //if( bRollForTimedLoot ) //{ // UnitState.RollForTimedLoot(); //} if( !CharacterTemplate.bIsCosmetic && `PRES.m_kUnitFlagManager != none ) { `PRES.m_kUnitFlagManager.AddFlag(UnitState.GetReference()); } return UnitState; } Not sure what X2StrategyGame_SimCombat does, but doesn't seem as relevant? Edited February 28, 2016 by lamaros Link to comment Share on other sites More sharing options...
Recommended Posts