diff --git a/XCOM2RPGOverhaul/Config/XComRPG.ini b/XCOM2RPGOverhaul/Config/XComRPG.ini index 8fd2555..31373e8 100644 --- a/XCOM2RPGOverhaul/Config/XComRPG.ini +++ b/XCOM2RPGOverhaul/Config/XComRPG.ini @@ -451,11 +451,4 @@ SpecializationMetaInfo = (bUseForRandomClasses=true, AllowedWeaponCategories=(gr SpecializationMetaInfo = (bUseForRandomClasses=true, AllowedWeaponCategories=(gremlin), InventorySlots=(eInvSlot_SecondaryWeapon), bGremlin=true) [Valkyrie X2UniversalSoldierClassInfo] -SpecializationMetaInfo = (bUseForRandomClasses=true, bUniversal=true) - -; Iridar's Akimbo -[DP_GunFu X2UniversalSoldierClassInfo] -SpecializationMetaInfo = (bUseForRandomClasses=true, AllowedWeaponCategories=(pistol), InventorySlots=(eInvSlot_PrimaryWeapon), bDualWield=true, bCantBeComplementary=true, bShoot=true, iWeightPrimary=1) - -[DP_Scrapper X2UniversalSoldierClassInfo] -SpecializationMetaInfo = (bUseForRandomClasses=true, AllowedWeaponCategories=(pistol), InventorySlots=(eInvSlot_PrimaryWeapon), bDualWield=true, bCantBeComplementary=true, bShoot=true, iWeightPrimary=1) +SpecializationMetaInfo = (bUseForRandomClasses=true, bUniversal=true) \ No newline at end of file diff --git a/XCOM2RPGOverhaul/Content/UILibrary_RPG.upk b/XCOM2RPGOverhaul/Content/UILibrary_RPG.upk index 7e066b2..6b6857e 100644 Binary files a/XCOM2RPGOverhaul/Content/UILibrary_RPG.upk and b/XCOM2RPGOverhaul/Content/UILibrary_RPG.upk differ diff --git a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SecondWaveConfigOptions.uc b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SecondWaveConfigOptions.uc index d0f1b0b..7c40afc 100644 --- a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SecondWaveConfigOptions.uc +++ b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SecondWaveConfigOptions.uc @@ -195,59 +195,58 @@ static function array GetSpecIndices_ForRandomClass(XComGameState_Unit Unit } } } - SpecTemplate = ValidSpecTemplates[`SYNC_RAND_STATIC(ValidSpecTemplates.Length)]; - - SelectedSpecTemplates.AddItem(SpecTemplate); - ReturnArray.AddItem(class'X2SoldierClassTemplatePlugin'.static.GetSpecializationIndex(UnitState, SpecTemplate.Name)); - Count--; + if (ValidSpecTemplates.Length > 0) + { + SpecTemplate = ValidSpecTemplates[`SYNC_RAND_STATIC(ValidSpecTemplates.Length)]; - // Record specialization index as a unit value so it can be looked at in class'X2TemplateHelper_RPGOverhaul'.static.CanAddItemToInventory - UnitState.SetUnitFloatValue('PrimarySpecialization_Value', class'X2SoldierClassTemplatePlugin'.static.GetSpecializationIndex(UnitState, SpecTemplate.Name), eCleanup_Never); - `LOG("SELECTED Primary specialization: " @ SpecTemplate.Name,, 'RPG'); + SelectedSpecTemplates.AddItem(SpecTemplate); + ReturnArray.AddItem(class'X2SoldierClassTemplatePlugin'.static.GetSpecializationIndex(UnitState, SpecTemplate.Name)); + Count--; - // Add complementary specializations, if necessary - AddComplementarySpecializations(UnitState, SpecTemplate, ReturnArray, SelectedSpecTemplates, Count); + // Record specialization index as a unit value so it can be looked at in class'X2TemplateHelper_RPGOverhaul'.static.CanAddItemToInventory + UnitState.SetUnitFloatValue('PrimarySpecialization_Value', class'X2SoldierClassTemplatePlugin'.static.GetSpecializationIndex(UnitState, SpecTemplate.Name), eCleanup_Never); + `LOG("SELECTED Primary specialization: " @ SpecTemplate.Name,, 'RPG'); - // Exit function early if necessary - if (Count <= 0) return ReturnArray; + // Add complementary specializations, if necessary + AddComplementarySpecializations(UnitState, SpecTemplate, ReturnArray, SelectedSpecTemplates, Count); + // Exit function early if necessary + if (Count <= 0) return ReturnArray; + } + else `LOG("There were no valid primary specs to choose from.",, 'RPG'); // ######################################################## // Select random specialization for secondary weapon - if (SelectedSpecTemplates[0].SpecializationMetaInfo.bDualWield) - { - `LOG("## Primary spec is Dual Wield, skipping Secondary Spec.",, 'RPG'); - } - else - { - `LOG("## Selecting secondary specialization: " @ Count,, 'RPG'); - ValidSpecTemplates.Length = 0; - foreach AllSpecTemplates(SpecTemplate) - { - // Skip specialization if it was already selected - if (ReturnArray.Find(class'X2SoldierClassTemplatePlugin'.static.GetSpecializationIndex(UnitState, SpecTemplate.Name)) != INDEX_NONE) continue; + `LOG("## Selecting secondary specialization: " @ Count,, 'RPG'); + ValidSpecTemplates.Length = 0; + foreach AllSpecTemplates(SpecTemplate) + { + // Skip specialization if it was already selected + if (ReturnArray.Find(class'X2SoldierClassTemplatePlugin'.static.GetSpecializationIndex(UnitState, SpecTemplate.Name)) != INDEX_NONE) continue; - // Skip specialization if it's mutually exclusive with one of the selected ones. - bSkipSpec = false; - for (i = 0; i < SelectedSpecTemplates.Length; i++) + // Skip specialization if it's mutually exclusive with one of the selected ones. + bSkipSpec = false; + for (i = 0; i < SelectedSpecTemplates.Length; i++) + { + if (SelectedSpecTemplates[i].SpecializationMetaInfo.MutuallyExclusiveSpecs.Find(SpecTemplate.Name) != INDEX_NONE) { - if (SelectedSpecTemplates[i].SpecializationMetaInfo.MutuallyExclusiveSpecs.Find(SpecTemplate.Name) != INDEX_NONE) - { - bSkipSpec = true; - break; - } + bSkipSpec = true; + break; } - if (bSkipSpec) continue; + } + if (bSkipSpec) continue; - if (SpecTemplate.IsSecondaryWeaponSpecialization()) + if (class'X2SoldierClassTemplatePlugin'.static.IsSpecializationValidToBeSecondary(SelectedSpecTemplates, SpecTemplate)) + { + for (i = 0; i < SpecTemplate.SpecializationMetaInfo.iWeightSecondary; i++) { - for (i = 0; i < SpecTemplate.SpecializationMetaInfo.iWeightSecondary; i++) - { - `LOG("Valid spec: " @ SpecTemplate.Name,, 'RPG'); - ValidSpecTemplates.AddItem(SpecTemplate); - } + `LOG("Valid spec: " @ SpecTemplate.Name,, 'RPG'); + ValidSpecTemplates.AddItem(SpecTemplate); } } + } + if (ValidSpecTemplates.Length > 0) + { SpecTemplate = ValidSpecTemplates[`SYNC_RAND_STATIC(ValidSpecTemplates.Length)]; SelectedSpecTemplates.AddItem(SpecTemplate); @@ -263,6 +262,8 @@ static function array GetSpecIndices_ForRandomClass(XComGameState_Unit Unit // Exit function early if necessary if (Count <= 0) return ReturnArray; } + else `LOG("There were no valid secondary specs to choose from.",, 'RPG'); + // ######################################################## // Select several additional specializations that either complement already selected specializations, or are weapon agnostic. `LOG("## Selecting additional specializations: " @ Count,, 'RPG'); diff --git a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SoldierClassTemplatePlugin.uc b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SoldierClassTemplatePlugin.uc index 688bc58..2e85222 100644 --- a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SoldierClassTemplatePlugin.uc +++ b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2SoldierClassTemplatePlugin.uc @@ -163,42 +163,39 @@ static function bool IsSpecializationValidToBeComplementary(array SelectedSpecTemplates, X2UniversalSoldierClassInfo SpecTemplate) { - local X2UniversalSoldierClassInfo CycleSpecTemplate; - - // Specialization cannot be used if it's missing meta information - // Or if it is explicitly forbidden from being complementary - if (!SpecTemplate.SpecializationMetaInfo.bUseForRandomClasses || SpecTemplate.SpecializationMetaInfo.bCantBeComplementary) return false; - - // If the Spec Template is Universal, then it can Complement any other specialization just fine. - if (SpecTemplate.SpecializationMetaInfo.bUniversal) return true; - - // If both the Primary Specailization and this Specialization are Dual Wielding, then just compare their weapon categories. - if (SelectedSpecTemplates[0] != none && - SelectedSpecTemplates[0].SpecializationMetaInfo.bDualWield && - SpecTemplate.SpecializationMetaInfo.bDualWield) - { - return DoSpecializationsUseTheSameWeapons(SelectedSpecTemplates[0], SpecTemplate); - } - - // Otherwise, cycle through Specs that have already been selected. - foreach SelectedSpecTemplates(CycleSpecTemplate) + // Allow only specs with configured meta info. + if (SpecTemplate.SpecializationMetaInfo.bUseForRandomClasses) { - // At least one of the selected specializations roughly does the same thing as this specialization, then this specialization can complement that one. - if (DoSpecializationsUseTheSameSlots(CycleSpecTemplate, SpecTemplate) && - (DoSpecializationsUseTheSameWeapons(CycleSpecTemplate, SpecTemplate) || - SpecTemplate.SpecializationMetaInfo.bShoot && CycleSpecTemplate.SpecializationMetaInfo.bShoot || - SpecTemplate.SpecializationMetaInfo.bGremlin && CycleSpecTemplate.SpecializationMetaInfo.bGremlin || - SpecTemplate.SpecializationMetaInfo.bPsionic && CycleSpecTemplate.SpecializationMetaInfo.bPsionic || - SpecTemplate.SpecializationMetaInfo.bMelee && CycleSpecTemplate.SpecializationMetaInfo.bMelee)) + if (SelectedSpecTemplates.Length > 0) { - return true; + // Primary specs marked as Dual Wield do not get secondary specs. + if (SelectedSpecTemplates[0].SpecializationMetaInfo.bDualWield) + { + //`LOG(SpecTemplate.Name @ "is not valid, because primary spec is dual wield.",, 'RPG'); + return false; + } + + // If this spec is marked as Dual Wield spec, and it uses the same weapons as the primary spec, + if (SpecTemplate.SpecializationMetaInfo.bDualWield && DoSpecializationsUseTheSameWeapons(SelectedSpecTemplates[0], SpecTemplate)) + { + // then this spec can become a secondary spec for it + // Looking up Secondary Weight allows to restrict specific specs from becoming secondary to dual wield specs. + + if (SpecTemplate.SpecializationMetaInfo.iWeightSecondary <= 0) `LOG(SpecTemplate.Name @ "is not valid, because iWeightSecondary is zero or lower.",, 'RPG'); + return SpecTemplate.SpecializationMetaInfo.iWeightSecondary > 0; + } } + // If this spec is not a dual wield spec, then we only check if the spec itself is valid to be a secondary on its own. + //if (!SpecTemplate.IsSecondaryWeaponSpecialization()) + //{ + // `LOG(SpecTemplate.Name @ "is not valid, because it's not a secondary spec.",, 'RPG'); + //} + return SpecTemplate.IsSecondaryWeaponSpecialization(); } return false; } -*/ static function bool DoSpecializationsUseTheSameSlots(X2UniversalSoldierClassInfo SpecTemplateA, X2UniversalSoldierClassInfo SpecTemplateB) { diff --git a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2TemplateHelper_RPGOverhaul.uc b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2TemplateHelper_RPGOverhaul.uc index 7d73714..269f384 100644 --- a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2TemplateHelper_RPGOverhaul.uc +++ b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2TemplateHelper_RPGOverhaul.uc @@ -1180,37 +1180,51 @@ static function bool CanAddItemToInventory_WeaponRestrictions(out int bCanAddIte // Perform the check ONLY if the item has not been forbidden by another mod already, if the soldier is an RPGO soldier, and only if we're looking at a weapon if (DisabledReason == "" && UnitState.GetSoldierClassTemplateName() == 'UniversalSoldier' && WeaponTemplate != none && (Slot == eInvSlot_PrimaryWeapon || Slot == eInvSlot_SecondaryWeapon)) { + //`LOG("Begin check for unit:" @ UnitState.GetFullName() @ "slot:" @ Slot @ "weapon:" @ WeaponTemplate.DataName,, 'IRITEST'); + + // Check if the soldier's primary specs allow using this weapon in this slot. PrimarySpecs = class'X2SoldierClassTemplatePlugin'.static.GetTrainedPrimaryWeaponSpecializations(UnitState); foreach PrimarySpecs(PrimarySpec) { PrimarySpecTemplate = class'X2SoldierClassTemplatePlugin'.static.GetSpecializationTemplate(PrimarySpec); - // If soldier's primary specialization is a Dual Wield one, then look only at primary specialization for both Primary and Secondary weapons. - if (PrimarySpecTemplate.SpecializationMetaInfo.bDualWield || Slot == eInvSlot_PrimaryWeapon) + if (PrimarySpecTemplate != none) { - bAllowed = PrimarySpecTemplate != none && PrimarySpecTemplate.IsWeaponAllowed(WeaponTemplate.InventorySlot, WeaponTemplate.WeaponCat); + //`LOG("Checking primary spec:" @ PrimarySpec.TemplateName,, 'IRITEST'); + + // Primary Spec allows using primary weapon based on their category, or both primary and secondary, if it's marked as Dual Wield spec. + bAllowed = PrimarySpecTemplate.IsWeaponAllowed(WeaponTemplate.WeaponCat) && (Slot == eInvSlot_PrimaryWeapon || PrimarySpecTemplate.SpecializationMetaInfo.bDualWield); if (bAllowed) { + //`LOG("It allows this weapon.",, 'IRITEST'); break; } } + else `LOG("Weapon Restrictions: ERROR, could not get Spec Template for spec:" @ PrimarySpec.TemplateName,, 'RPG'); } + // Check if the weapon is not allowed yet, check if the secondary specs allow it. if (!bAllowed) { SecondarySpecs = class'X2SoldierClassTemplatePlugin'.static.GetTrainedSecondaryWeaponSpecializations(UnitState); foreach SecondarySpecs(SecondarySpec) { + //`LOG("Checking secondary spec:" @ SecondarySpec.TemplateName,, 'IRITEST'); SecondarySpecTemplate = class'X2SoldierClassTemplatePlugin'.static.GetSpecializationTemplate(SecondarySpec); - bAllowed = SecondarySpecTemplate != none && SecondarySpecTemplate.IsWeaponAllowed(WeaponTemplate.InventorySlot, WeaponTemplate.WeaponCat); + + // Secondary Spec can allow only secondary weapons. + bAllowed = SecondarySpecTemplate != none && SecondarySpecTemplate.IsWeaponAllowed(WeaponTemplate.WeaponCat) && Slot == eInvSlot_SecondaryWeapon; if (bAllowed) { + //`LOG("It allows this weapon.",, 'IRITEST'); break; } } } + if (bAllowed) { + //`LOG("Weapon allowed.",, 'IRITEST'); // Weapon allowed DisabledReason = ""; bCanAddItem = 1; @@ -1220,6 +1234,7 @@ static function bool CanAddItemToInventory_WeaponRestrictions(out int bCanAddIte } else { + //`LOG("Weapon NOT allowed.",, 'IRITEST'); // Weapon NOT Allowed LocTag = XGParamTag(`XEXPANDCONTEXT.FindTag("XGParam")); LocTag.StrValue0 = UnitState.GetSoldierClassTemplate().DisplayName; diff --git a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2UniversalSoldierClassInfo.uc b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2UniversalSoldierClassInfo.uc index cd6118d..b790a8a 100644 --- a/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2UniversalSoldierClassInfo.uc +++ b/XCOM2RPGOverhaul/Src/XCOM2RPGOverhaul/Classes/X2UniversalSoldierClassInfo.uc @@ -16,13 +16,9 @@ var localized string ClassSpecializationTitle; var config SpecializationMetaInfoStruct SpecializationMetaInfo; -function bool IsWeaponAllowed(EInventorySlot Slot, name WeaponCat) +function bool IsWeaponAllowed(name WeaponCat) { - if (SpecializationMetaInfo.bDualWield) - { - return SpecializationMetaInfo.AllowedWeaponCategories.Find(WeaponCat) != INDEX_NONE; - } - else return SpecializationMetaInfo.InventorySlots.Find(Slot) != INDEX_NONE && SpecializationMetaInfo.AllowedWeaponCategories.Find(WeaponCat) != INDEX_NONE; + return SpecializationMetaInfo.AllowedWeaponCategories.Find(WeaponCat) != INDEX_NONE; } function string GetClassSpecializationTitleWithMetaData() @@ -106,18 +102,18 @@ function array GetLocalizedWeaponCategories() function bool IsPrimaryWeaponSpecialization() { // Specialization is valid to be soldier's Primary specialization only if has meta information set up, if it is valid for Primry Weapon slot, and only if it specifies some weapon categories it can unlock. - return SpecializationMetaInfo.AllowedWeaponCategories.Length > 0 && SpecializationMetaInfo.InventorySlots.Find(eInvSlot_PrimaryWeapon) != INDEX_NONE; + return SpecializationMetaInfo.iWeightPrimary > 0 && SpecializationMetaInfo.AllowedWeaponCategories.Length > 0 && SpecializationMetaInfo.InventorySlots.Find(eInvSlot_PrimaryWeapon) != INDEX_NONE; } function bool IsSecondaryWeaponSpecialization() { - // Spec is valid to be secondary if it allows using specific weapons in the secondary slot OR if it's a valid primary spec that is also a Dual Wield spec - return SpecializationMetaInfo.AllowedWeaponCategories.Length > 0 && (SpecializationMetaInfo.InventorySlots.Find(eInvSlot_SecondaryWeapon) != INDEX_NONE || SpecializationMetaInfo.bDualWield && IsPrimaryWeaponSpecialization()); + // Spec is valid to be secondary if it allows using specific weapons in the secondary slot + return SpecializationMetaInfo.iWeightSecondary > 0 && SpecializationMetaInfo.AllowedWeaponCategories.Length > 0 && SpecializationMetaInfo.InventorySlots.Find(eInvSlot_SecondaryWeapon) != INDEX_NONE; } function bool IsComplemtarySpecialization() { - return (!SpecializationMetaInfo.bCantBeComplementary && SpecializationMetaInfo.bUniversal); + return SpecializationMetaInfo.iWeightComplementary > 0 && !SpecializationMetaInfo.bCantBeComplementary && SpecializationMetaInfo.bUniversal; } /* {