Jump to content
⚠ Known Issue: Media on User Profiles ×

zx64

Members
  • Posts

    19
  • Joined

  • Last visited

Nexus Mods Profile

About zx64

Profile Fields

  • Country
    None

zx64's Achievements

Apprentice

Apprentice (3/14)

0

Reputation

  1. -allowconsole should work from Steam but there's something special going on with launching via StartDebugging.bat that enables the debug main menu. The non-cheat start does indeed simulate the first mission, tracing the flow from the debug menu button ends up in NonCheatDebugStuff() in XGStrategy.uc, which uses SimCombat() from X2StrategyGame_SimCombat.uc.
  2. You need to start the game with XCOM 2\Binaries\Win64\Launcher\StartDebugging.bat instead (or F5 in ModBuddy). Console keys are normally ' and \ (referenced as Quote and Backslash in DefaultInput.ini), not sure if they're hardcoded to match the key locations on these layouts https://en.wikipedia.org/wiki/British_and_American_keyboards but it might help.
  3. LevelUpBarracks 1 will increase all soldiers' rank by one. You'll need to exit the view soldiers screen and go back to see changes.
  4. Oh that's annoying, it doesn't seem to want to generate a VIP mission after all that - it seems to always pick "destroy relay". The code doesn't appear to be hard coded to that mission type so it's probably something more subtle. If you've not read through it yet, SpawnVIPWithXComSquad() in XComTacticalMissionManager.uc looks like a relevant starting point: // find a spot with the squad and spawn the unit ParcelManager = `PARCELMGR; ParcelManager.SoldierSpawn.GetValidFloorLocations(SpawnLocations); foreach SpawnLocations(SpawnLocation) { if(WorldData.IsPositionOnFloorAndValidDestination(SpawnLocation)) { // put the unit here WorldData.GetFloorTileForPosition(SpawnLocation, SpawnTile); Unit = CreatePawnCommon(NewGameState, SpawnTile, 0); break; } }Also looks like there's a SpawnMission console command, implemented in XComTacitcalHeadquartersCheatManager.uc: exec function SpawnMission(name MissionSourceName, name MissionRewardName, optional name ExtraMissionRewardName) Going by the names in DefaultMissions.ini, this might work (I tried a bunch of different combinations, scanned and had a rescue scientist mission come up) spawnmission MissionSource_Council Reward_Scientist
  5. Tactical Quick Launch mode lets you generate missions with specific objectives: http://forums.nexusmods.com/index.php?/topic/3770770-developer-skirmish-mode/ You'll want to pick a city map which allows you to select VIP. Make sure you pick a squad setting other than the default, you may softlock the UI.
  6. That selection behaviour seems specific to ModBuddy, it's quite annoying as I'm used to ctrl+shift+left/right to select by word and instead that selects to start or end of line. It's not consistent with the defaults that come with VS2013 or VS2015 Community edition. Not sure if it is possible to load the extension that ModBuddy uses to customise the VS Isolated Shell into a proper install of VS, but it would be useful.
  7. While I wasn't running into freezes or logspam, I was getting lots of lighting glitches with my replay mod that ultimately went away when I stopped storing a reference to the UIScreen instance in my UIScreenListener class. I had suspected the reference was causing the object to not be GC'd at the right time, but setting the reference to none in the OnLoseFocus event wasn't enough.
  8. Updated to fix graphical glitching when in mission. Root cause was me storing a reference to the UI Shell inside my class. Changing it to store a reference to the UIMovie seems to resolve the issue. // Do not store a reference to UIScreen here, it causes graphical glitching in game var UIMovie Movie; event OnInit(UIScreen Screen) { // Need this to activate the load save dialog Movie = Screen.Movie; ... } simulated function OnLoadReplay(UIButton button) { ... Movie.Pres.UILoadScreen(); } Also as I learned from reading through the LWS mods, you don't need ModClassOverrides entries for UIScreenListeners.
  9. Btw, if you have the SDK installed, the source to XComGame.u is unpacked into XCOM 2 SDK\Development\SrcOrig\XComGame\Classes.
  10. Strategic, "Debug NonCheat Start". You can skip the intro cutscene once it has finished loading in the background.
  11. DefaultAI.ini Certain AI actions will pick high health units over shots likely to kill them: ; Health Scoring - Strongest First (prioritize high health), ignore low health UNLESS kill shot ; changing most "do not favors" from reducing the score to adding a bonus if the condition ISN'T true, to garaunteed that someone will be shot at. Behaviors=(BehaviorName=TargetScoreHealth_HighFirst, NodeType=Selector, Child[0]=PenalizeIfKillShot, Child[1]=ScoreIfTarget_MaxHP, Child[2]=ScoreIfTarget_HighHP, Child[3]=AddToTargetScore_5) Behaviors=(BehaviorName=PenalizeIfKillShot, NodeType=Sequence, Child[0]=TargetIsKillable, Child[1]=AddToTargetScore_0) ; If the attack would kill the target, deemphasize (but don't ignore) So far it's only used for: Stun lanceMark targetPSI Behaviors=(BehaviorName=EvaluateTargetForStunLance, NodeType=Sequence, Child[0]=TargetScoreHitChance, Child[1]=TargetScoreHealth_HighFirst, Child[2]=TargetScoreMarked, Child[3]=AvoidBoundAndPanickedTargets, Child[4]=TargetScoreCivilian, ) Behaviors=(BehaviorName=ScoreMarkTargetOption, NodeType=Sequence, Child[0]=TargetIsEnemy, Child[1]=TargetIsNotCivilian, Child[2]=ScoreByHP, Child[3]=TargetScoreHealth_HighFirst, Child[4]=TargetScoreHighestSoldierRank, Child[5]=TargetScoreTeamVisibility, Child[6]=SometimesRandomizeTarget, Child[7]=AvoidBoundAndPanickedTargets) Behaviors=(BehaviorName=PsiEvaluateTargetsGeneric, NodeType=Sequence, Child[0]=SetNextTarget, Child[1]=TargetScorePsiAttack, Child[2]=TargetScoreHighestSoldierRank, Child[3]=TargetScoreHealth_HighFirst, Child[4]=SometimesRandomizeTarget, Child[5]=ApplyDifficultyModifiers, Child[6]=AvoidBoundAndPanickedTargets, Child[7]=TargetScoreInvalidateCivilians, Child[8]=UpdateBestTarget) Behaviors=(BehaviorName=PsiEvaluateTargetsMindControl, NodeType=Sequence, Child[0]=SetNextTarget, Child[1]=TargetScoreMindControl, Child[2]=TargetScoreHighestSoldierRank, Child[3]=TargetScoreHealth_HighFirst, Child[4]=TargetScoreInvalidateCivilians, Child[5]=AvoidBoundAndPanickedTargets, Child[6]=UpdateBestTarget) So I guess if you remove the TargetScoreHealth_HighFirst from the sequences, especially mark target and stun lance, you'll enjoy facing against those classes even more! I'm curious if adding it to more abilities would result in firefights that are more health attrition based than your more squishy units getting nuked, since the AI will tend towards targeting units with higher health which will shift around as your units get shot.
  12. For others to learn from, here's a collection of notes on how I made this mod. The source is included in the standalone download in the OP, but I'll include bits for context. First was to find how much of replay mode was exposed to UnrealScript. > dir *replay* Volume in drive F has no label. Volume Serial Number is 9C8C-E0D4 Directory of F:\steam\steamapps\common\XCOM 2 SDK\Development\SrcOrig\XComGame\Classes 2016-02-05 03:09 6,874 UIReplay.uc 2016-02-05 03:09 4,721 XComMPReplayMgr.uc 2016-02-05 03:09 9,365 XComReplayMgr.uc UIReplay.uc isn't immediately useful, but we'll get back to that. Not concerned with MP, so let's have a look at XComReplayMgr.uc: /// <summary> /// Switches the running tactical game into a replay mode, where the visualization is driven by frames already in the /// game state history. /// </summary> simulated event StartReplay(int SessionStartStateIndex)Bingo. Now let's trace where that function is called: > findstr StartReplay * [...] X2TacticalGameRuleset.uc: // init the UI before StartReplay() because if its the Tutorial, Start replay will hide the UI which needs to have been created already X2TacticalGameRuleset.uc: XComTacticalGRI(class'WorldInfo'.static.GetWorldInfo().GRI).ReplayMgr.StartReplay(StartStateIndex); [...] Here's part of the function where those search results came up: if( `ONLINEEVENTMGR.bInitiateReplayAfterLoad ) { //Start the replay from the most recent start state StartStateIndex = CachedHistory.FindStartStateIndex(); FullGameState = CachedHistory.GetGameStateFromHistory(StartStateIndex, eReturnType_Copy, false); // init the UI before StartReplay() because if its the Tutorial, Start replay will hide the UI which needs to have been created already XComPlayerController(GetALocalPlayerController()).Pres.UIReplayScreen(); XComTacticalGRI(class'WorldInfo'.static.GetWorldInfo().GRI).ReplayMgr.StartReplay(StartStateIndex); `ONLINEEVENTMGR.bInitiateReplayAfterLoad = false;bInitiateReplayAfterLoad looks promising, let's find where that's set to true: > findstr /C:"bInitiateReplayAfterLoad = true" * UIDebugChallengeMode.uc: `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; UIShell.uc: `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; UIShell.uc: `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; UIShell.uc: `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; UIShellDifficulty.uc: `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; XComCheatManager.uc: `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true;UIShell.uc is where the debug main menu is set up and this is where we find the "Load Replay" button's implementation: // Button callbacks simulated function OnMenuButtonClicked(UIButton button) { [...] switch( button.MCName ) { [...] case 'Special': `XCOMHISTORY.ResetHistory(); `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; XComShellPresentationLayer(Owner).UILoadScreen(); break;So all I have to do is create a new button that does the same thing. Fortunately there's some documentation on this at: XCOM 2 SDK\Documentation\Tech\XCOM2Mods_UserInterface.pdf "Manipulating current UI elements" is exactly what we're after, so let's follow along with the example and extend a UIScreenListener and attach it to the main menu. class LoadReplay_ZX extends UIScreenListener; event OnInit(UIScreen Screen) { } defaultproperties { ScreenClass = ??? } But hang on, we don't yet know the ScreenClass for the non-debug main menu. As it happens, the debug main menu has a button that switches back to the final menu: Button = Spawn(class'UIButton', DebugMenuContainer); Button.InitButton('FinalShellMenu', m_sFinalShellDebug, UIDebugButtonClicked); [...] case 'FinalShellMenu': XComShellPresentationLayer(Owner).UIFinalShellScreen(); break;and there's a UIFinalShell.uc, so let's go with that: defaultproperties { ScreenClass = class'UIFinalShell'; }Now here's where I ran into a few fun extra challenges... You see that Spawn in the example and just above? That didn't compile for my UIScreenListener for some reason. Now, UIShell.uc etc. is actually a UIScreen rather than a UIScreenListener, so maybe we can call Spawn using the Screen object that's passed into our OnInit event handler. event OnInit(UIScreen Screen) { local UIButton Loadreplay; Loadreplay = Screen.Spawn(class'UIButton', Screen); Loadreplay.InitButton('LoadReplay_ZX', "Load Replay", OnLoadReplay); Loadreplay.SetPosition(0,0); } Something to watch out here: UnrealScript has two separate types, Names and Strings. Names use single quotes and Strings use double quotes. This caught me out as I was getting a compile error when writing e.g.: Loadreplay.InitButton("LoadReplay_ZX", "Load Replay", OnLoadReplay); I had to dig through UIButton.uc before realising that single vs double quotes was significant! So all we have to do now is copy that replay code from earlier into our OnLoadReplay, right? simulated function OnLoadReplay(UIButton button) { `XCOMHISTORY.ResetHistory(); `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; XComShellPresentationLayer(Owner).UILoadScreen(); } Warning/Error Summary --------------------- F:\steam\steamapps\common\XCOM 2 SDK\Development\Src\LoadReplay\Classes\LoadReplay_ZX.uc(21) : Error, 'XComShellPresentationLayer': Bad command or expressionDamn! I think this is another UIScreen vs UIScreenListener thing, but even if I store the UIScreen reference, it still doesn't compile: var UIFinalShell Shell; event OnInit(UIScreen Screen) { [...] Shell = UIFinalShell(Screen); } simulated function OnLoadReplay(UIButton button) { `XCOMHISTORY.ResetHistory(); `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; Shell.XComShellPresentationLayer(Owner).UILoadScreen(); } Warning/Error Summary --------------------- F:\steam\steamapps\common\XCOM 2 SDK\Development\Src\LoadReplay\Classes\LoadReplay_ZX.uc(22) : Error, Unrecognized member 'XComShellPresentationLayer' in class 'UIFinalShell' So now we have to do more source digging. What does that UILoadScreen method do? > findstr "UILoadScreen" * UICombatLose.uc: Movie.Pres.UILoadScreen(); UIFinalShell.uc: XComShellPresentationLayer(Owner).UILoadScreen(); UILoadScreenAnimation.uc:// FILE: UILoadScreenAnimation.uc UILoadScreenAnimation.uc:class UILoadScreenAnimation extends UIScreen; UIPauseMenu.uc: Movie.Pres.UILoadScreen(); UIShell.uc: XComShellPresentationLayer(Owner).UILoadScreen(); UIShell.uc: XComShellPresentationLayer(Owner).UILoadScreen(); UIShellStrategy.uc: XComShellPresentationLayer(Owner).UILoadScreen(); XComPresentationLayerBase.uc:var protected UILoadScreenAnimation m_kLoadAnimation; XComPresentationLayerBase.uc:simulated function UILoadScreen() XComPresentationLayerBase.uc: HandleInvalidStorage(m_strSelectSaveDeviceForLoadPrompt, UILoadScreen); XComPresentationLayerBase.uc: m_kLoadAnimation = Spawn( class'UILoadScreenAnimation', self );So let's take a peek in XComPresentationLayerBase.uc: simulated function UILoadScreen() { local UIMovie TargetMovie; TargetMovie = XComShellPresentationLayer(self) == none ? Get2DMovie() : Get3DMovie(); if( `ONLINEEVENTMGR.HasValidLoginAndStorage() ) { ScreenStack.Push( Spawn( class'UILoadGame', self ), TargetMovie ); } else { HandleInvalidStorage(m_strSelectSaveDeviceForLoadPrompt, UILoadScreen); // Failed to enter state } }Hmm, nothing that obvious, but wait a second, what's this Movie.Pres thing in the pause menu? At this point, I figured it was worth a try and plugged it into my OnLoadReplay: simulated function OnLoadReplay(UIButton button) { `XCOMHISTORY.ResetHistory(); `ONLINEEVENTMGR.bInitiateReplayAfterLoad = true; Shell.Movie.Pres.UILoadScreen(); } Success! Movie though? What's up with that? As noted in UserInterface.pdf, XCOM uses Flash for the UI (you might recognise the name "Scaleform" from various logo splashes). I expect the term "Movie" dates way back to their Flashplayer and Shockwave days and they've never felt the need to rename the concept to reflect the more general use of that technology. Finally, I wanted to streamline the replay UI with another button that hid the UI and started automatic playback. This means a new UIScreenListener, this time attached to UIReplay. I'd spotted a ConsoleCommand function being used in a variety of places, so figured I'd just need to do: ConsoleCommand("ReplayToggleUI"); ConsoleCommand("ReplayAutoplay"); but again, not available to UIScreenListener. Instead I went digging for the source of those console commands and copied over what those commands did: simulated function OnAutoPlay(UIButton button) { `REPLAY.ToggleUI(); XComTacticalGRI(class'WorldInfo'.static.GetWorldInfo().GRI).ReplayMgr.StepReplayAll(); } Other important thing, remember to update XComEngine.ini to include the new class: [Engine.ScriptPackages] +NonNativePackages=LoadReplay [Engine.Engine] +ModClassOverrides=(BaseGameClass="UIScreenListener", ModClass="LoadReplay_ZX") +ModClassOverrides=(BaseGameClass="UIScreenListener", ModClass="ReplayUITweaks_ZX") Final aside, I had to edit my x2proj by hand to get it to add the new ReplayUITweaks_ZX.uc to the right location, VS kept insisting on adding it to the root of the project. And that's it! Hope you learned something. :-)
  13. Is there any tooling related to maintaining (i.e. visualising, validating, authoring) the config data? The behemoth of X2AIBTBehaviorTreeNode instances in DefaultAI.ini must have been a nightmare to develop if all they could do was slog away in their text editors of choice and pray for as few merge conflicts as possible.
  14. https://dl.dropboxusercontent.com/u/1542468/xcom/allconsole.txt are all the commands I found in the SDK source (lines that begin with exec function, which might have picked up code that was in multiline comments).
×
×
  • Create New...