-
Posts
1186 -
Joined
-
Last visited
Everything posted by wghost81
-
Couldn't find any documentation for it myself, but you're probably right. Well, let's hope making it a config class will work. :)
-
Currently Checkpoint class has this flags set: ClassFlags = 0x080000B2 0x00000002: Compiled 0x00000010: Parsed 0x00000020: Localized 0x00000080: RuntimeStatic We need to add 0x00000004 (Config) to it and init ConfigNameIdx with some name from namelist. Checkpoint should do, as it will result in DefaultCheckpoint.ini filename: [BEFORE_CODE] <%u 0x080000B2> // ClassFlags <Core.Object> // WithinRef <None> // ConfigNameIdx [AFTER_CODE] <%u 0x080000B6> // ClassFlags <Core.Object> // WithinRef <Checkpoint> // ConfigNameIdx In theory this should turn Checkpoint into ini configurable class: [ModCheckpointRecord.Checkpoint_StrategyGame_Mod] ActorClassesToRecord=...
-
Hmm... var const array< class<Actor> > ActorClassesToRecord; var const array< class<Actor> > ActorClassesToDestroy; Both are const. But we can try to remove const flag from them. We won't be able to config them directly, as adding config to class with no config defined won't work, but we should be able to create out own variables like var config array< class<Actor> > ActorClassesToRecord_Mod; var config array< class<Actor> > ActorClassesToDestroy_Mod; And then assign them to ActorClassesToRecord and ActorClassesToDestroy. Another way is, as you suggested, to try adding config to Checkpoint class directly. Then all the child classes will have access to it and we can make both arrays directly configurable.
-
I believe we can make child classes of Checkpoint_StrategyGame classes and Checkpoint_TacticalGame classes. The trick will be to initialize StrategySaveGameClass and TacticalSaveGameClass variables in XComHeadquartersGame and XComGameInfo classes. I think we can do it by converting var Class TacticalSaveGameClass; var Class StrategySaveGameClass; into var config Class TacticalSaveGameClass; var config Class StrategySaveGameClass; Both are defined in XComGameInfo class. Property flags for both are zero, we need to add Config flag to both of them: [BEFORE_CODE] <%s 1> <%s 0> <%u 0x00000000> // flags L <%u 0x00000000> // flags H [AFTER_CODE] <%s 1> <%s 0> <%u 0x00004000> // flags L: Config <%u 0x00000000> // flags H After this we should be able to initialize both variables in DefaultGame.ini with something like [XComGame.XComGameInfo] TacticalSaveGameClass=class'Checkpoint_TacticalGame_Mod' [XComStrategyGame.XComHeadquartersGame] StrategySaveGameClass=class'Checkpoint_StrategyGame_Mod' Checkpoint_TacticalGame_Mod and Checkpoint_StrategyGame_Mod classes should point to the same (or different) config file where ActorClassesToRecord and ActorClassesToDestroy should be filled with vanilla and modded classes.
-
I had to add Mutator class to Default__Checkpoint_TacticalGame list of saved classes to make it work on tactical layer. But you need an object reference to make it work. Engine.Mutator already was there, but you can't import your new class reference. If you're subclassing an existing class and it is already in Default__Checkpoint* list, saves will work. If it's not in the list, but you can add it there, saves will work. If you're making a completely new class, you can use a mutator for the sole purpose of saving your variables.
-
Thanks :smile: [ Although it's hot as hell here right now :smile: ]
-
Yes I still have a project pending named XCOMModUtil. It's all-in-one thing with GUI support and some bugfixes/enhancements. I had big plans for this utility, but then Witcher 3 got me completely distracted :) and when I returned to modding XCOM Firaxis announced XCOM2. Kinda discouraged me from returning to this and I still can't bring myself to continue my work, sorry. :( I mean, I'm happy about XCOM2 and all the new modding possibilities, but still.
-
Yes, it actually is a bug. Only reliable fix for this is to introduce escape characters, but I still haven't implemented these.
-
Compiled u files are uncooked but have the same structure as upk. I prefer to use them instead of cooked upk packages, because cooking removes all debug information. And I also compile all the packages with debug flag on to get additional logging possibilities. To get your package in game you need to add it to DefaultEngine.ini Engine.ScriptPackages section to NonNativePackages array. And as we understand it now, you must add it after main game packages. Note that not me nor Amineri have tested DynamicLoadObject thing. It's just a theory. But if it works, adding your package to ini and loading new class with DynamicLoadObject will be enough to replace parent spawn with its child spawn.
-
Yes, but class can only access one specific ini which is set as class parameter. Well, actually child classes can have different ini and still access parent's ini, but still it doesn't give us direct access to MP ini variables. Unless they are static or const, if I'm not mistaken. Actually, that's why I completely moved to mutators. Despite all the ugliness of the linking code in Mutate, it allows to simply clone hex part for different functions and do everything I want with unrealscipt and with no limitations. Kinda made me lazy, but allowed to create some really complex things. :smile:
-
The idea with DynamicLoadObject looks good. This way is it possible to do without mutators at least when we need to spawn modded child class instead of original parent class. INI thing is problematic for existing packages, though, as we'll need to re-purpose some of the existing ini variables to hold class names. And with mutator loader class we have our own fully customizable config file. ;) So, there are pros and cons to both methods. Fully mutator based method allows to change hex code just once and then do all the modding with unrealscript and UDK. But the drawback of this method is indirect access to objects and functions being passes with Mutate and its string param. DynamicLoadObject allows to bypass mutators and spawn modded child class directly. However, it isn't suitable for the case when we need to insert new functionality into existing method without creating a new class, as it won't allow to dynamically load new functions. Still, we have some more options now, which no doubt is a good thing. :)
-
Amineri just discovered an interesting thing, which probably was preventing us from getting import references in: there can be no circular dependencies between game packages. So, XComGame has no references to XComStrategyGame, because XComStrategyGame is loaded after XComGame package. I tested it with UDK and it seems to be true. So, all new packages are loaded after existing ones and we are able to reference existing classes. But this makes it impossible to reference our new packages from the old ones.
-
Long War for Mac OS/X - pointers / advice?
wghost81 replied to thither's topic in XCOM's Enemy Unknown
Pre b15e uninstaller is bugged. You will need to reinstall the game now. -
PS I got the idea about not turning XComMutator into one big and heavy interface and I will think about it. I like it as it is now because it hides this ugly implementation and allows me to focus on the task with a child mutator. But I can see how this can be inconvenient for some users/cases.
-
I don't mind the criticism at all, but keep in mind that there are a lot of things I cannot change. :wink: So, let's go deeper into this situation. I can't just call spawn with a new class, because I need an import reference to class'XGStrategyAI_Mod', which is not present in the XComStrategyGame.upk package. Things look a little simpler from unrealscript side then they do from bytecode side. :smile: And this is the most basic problem with getting new classes to work: we need references that are not there. Second problem is related to the fact that BaseMutator is of Mutator class which is defined in Engine.upk. So we can't just create a new child with all the new methods we need and call these methods instead of Mutate or any of the old ones, because to access new methods we need to cast BaseMutator to our child class and for that we need the damn reference which is not there. I hope now you can understand my frustration. :smile: I need method to pass some params and return some values, but I don't have one and I can't create one. The only suitable method is Mutate, because I can use string param to pass some values like "XGUnit.RecordKill"$Name$kVictim.Name. And sometimes I need to invent some convoluted methods to notify the original script about mutator code being successfully executed. Spawning an object is the easiest case, as I can check for null pointer. Also, the original code should be safe and should not CTD if mutator is not present. Everything else looks like the matter of optimization to me. :wink: But I have a rule here: if code is not slowing down the system considerably, I have no need to care about optimization. :smile: Probably, I'm just a lazy person. :smile: The way it works now, Mutate is subsequently called for all the mutators, performs about 20 if-else checks and successfully does nothing if some mutator is not supposed to process some call. Plus it is called from like 20 different places, but, thankfully, not at the same time. :smile: To be honest, the idea is stolen from UT mutators, only difference is that instead of 20 calls for the same method it has 20 calls for 20 different methods. But mutators were never meant to be big and heavy, they meant to do one small thing just once. I tried to keep this approach, at least with latest mods. BTW, original mutator class has category, relevance and active/inactive checks, so my version is surely less complicated in that respect. :smile:
-
Yes, there aren't that much of tutorials on mutators, I know. :smile: I'll try to think of something, I promise. :smile: I believe I mentioned it somewhere, that the basic difference between UT (the game that mutators were designed for) and XCOM is that XCOM objects have a lot of back references. UT mutators are aimed to replace stand-alone objects in the world, like weapons. When the weapon is created or picked up, CheckReplacement is called and object is re-spawned with mutator. Object's owner gets the new reference and in case of weapon it's everything it needs. Similar methods are implemented for taking damage and entering the level, for example. To make the long story short, UT mutators allow to modify specific things in specific places and those places are inappropriate for XCOM. Let's take a new strategy AI mod I made for Beagle as an example as it's the most recent one. I needed to override a lot of methods in existing XGStrategyAI class and code wise the best way was to make a child class and re-write the code to keep the core things unchanged and overload some of the methods. So I did. But I couldn't just use CheckReplacement to respawn AI class as a stand-alone object in the world, because it is not stand-alone and other objects have references to it as well as it also has tons of back references. I tried it, btw, in one of my earlier attempts and it didn't work. So I ended up modifying XGStrategy.NewGame method: if(class'Engine'.static.GetCurrentWorldInfo().Game.BaseMutator != none) { class'Engine'.static.GetCurrentWorldInfo().Game.BaseMutator.Mutate("XGStrategy.NewGame", class'Engine'.static.GetCurrentWorldInfo().GetALocalPlayerController()); } if(m_kAI == none) { m_kAI = Spawn(class'XGStrategyAI'); } I wrote a base XComMutator class which has Mutate method heavily modified and provides a set of functions for its child mutators to work with. For this example the relevant part of the code looks like: function Mutate(string MutateString, PlayerController Sender) { ... if (MutateString == "XGStrategy.NewGame") { MutateStrategyAI(Sender); } .. } So, if I could, I would just replace XGStrategy.NewGame code with m_kAI = class'Engine'.static.GetCurrentWorldInfo().Game.BaseMutator.MutateStrategyAI(class'XGStrategyAI');but since I can't get new references into existing packages, I simply can't do it. MutateStrategyAI is just an empty method in XComMutator waiting to be overloaded by an actual StrategyAI mutator. Note that if mutator is not there or not supposed to mutate StrategyAI, nothing happens and vanilla code is executed. Now here's my XComStrategyAIMutator class for finally replacing default StrategyAI with its modded child: class XComStrategyAIMutator extends XComMutator; function MutateStrategyAI(PlayerController Sender) { local XGStrategy Game; Game = XComHeadquartersGame(class'Engine'.static.GetCurrentWorldInfo().Game).GetGameCore(); Game.m_kAI = Spawn(class'XGStrategyAI_Mod'); } I won't post XGStrategyAI_Mod here as it has over 1000 lines of code, but I hope you got the idea. :smile:
-
TechTree rework mod to add as a 2nd Wave option
wghost81 replied to Dethraker's topic in XCOM's Enemy Unknown
Yes, you need only notepad and script compiler to write your own script packages with UDK. Here are some explanations on setting up the environment: https://github.com/wghost/XCOM-Mutators/wiki/Setting-up-UDK-to-compile-XCOM-scripts The basic idea is that references to another packages are just names with no actual code behind them. So you can create dummy XCOM classes with just an appropriate names and then reference these from inside your own packages: https://github.com/wghost/XCOM-Mutators/wiki/Dummy-classes-and-stub-functions This will allow you to compile a new XCOM related class, but it won't allow you to get it into the game. Note that up to this point there are no mutators involved, just unrealscript classes. Since old packages have no reference to your new packages, you can't simply call for your new class from inside any of the existing classes. Here's where mutators come in handy. Mutators in their current state for XCOM are just the bridge between old classes and newly created ones. For example, for random LZ mods to work, I needed to rearrange a lot of map objects after the map is loaded. So I ended up inserting a call into existing PostLevelLoaded method. If I could simply call for my new class, I would. But I couldn't so I created a bridge - mutator class that gets loaded and called and then calls for my new class to do the actual job. One problem with mutators is that they are not supposed to act like this. So I couldn't use any of the standard methods and ended up re-purposing Mutate(string) method into a parser to do the things I need. If you decide to go this route, you'll need to modify this method even further to support your custom calls. -
Yes, it's native and you will most probably break it by turning it into regular function. EW console enabler by Drakous79 used this method of making native function into non-native one, but there was just "return true" statement and nothing more. SkeletalMeshComponent.AppendSockets function looks like it is way more complicated, so I don't think this method applies here.
-
TechTree rework mod to add as a 2nd Wave option
wghost81 replied to Dethraker's topic in XCOM's Enemy Unknown
I suggested mutators only because you said you needed new variables. But you can still find a way to code your mod completely in hex and using existing classes/variables/functions only. In most of the cases it is possible, but requires a lot of work. First thing you should do, IMO, is to write down a detailed plan on what you want to do and how you want it to be configured. Then look at how it is done currently. After that you will be able to decide which approach to use. -
CheckReplacement is not usable for XCOM because of all the back references. What I finally came to is inserting Mutate call before an object spawn code, pass a bunch of params to it as text (as it only accepts text) and then spawn the new object with mutator depending on these params. After that I add another check in the original code, which confirms if an object is spawned (its reference is not equal to 'none') and if not, executes vanilla code to spawn vanilla class.
-
Welcome to the club. :) One thing that works for sure: adding new names to namelist and referencing virtual functions with void return values. Everything else works weird. Patcher has all the functionality to insert new export and import entries, but sometimes it doesn't work. Actually, it was most of the time for me. :) Personally, I had no success adding new import references to script packages. I was able to add and use new export variable, but that was magic, because it worked for one place and didn't work for another and finally turned out to cause CTD under Linux/Mac. What this means, basically, if you have something which is not referenced in upk - you're out of luck. You need to use either indirect access with means that are available or switch to mutators. Which can also be tricky. :) There is a native method AttachComponent, which has relative scale as a parameter and is referenced in xcomgame.upk. This parameter is optional and might not appear in UEE decompiled scripts, but it is still there and you can use it. You can also try to edit HeadArchetype parameters, which is requested with PawnContentRequest. This one is probably somewhere in ini (?).
-
TechTree rework mod to add as a 2nd Wave option
wghost81 replied to Dethraker's topic in XCOM's Enemy Unknown
>Can't seem to find the PDF relating to adding variables to existing classes though. Because it crashes 90% of the time, so no one is ready to write a tutorial yet. :smile: You can find some explanations and examples in PatchUPK readme file. And you will also need to familiarize yourself with UPK data structure (pdf is available for download from UPKUtils nexus page). Personally, I tried this approach several times, but decided not to use it finally. Adding new names to namelist is fine, everything else is just too glitchy. -
TechTree rework mod to add as a 2nd Wave option
wghost81 replied to Dethraker's topic in XCOM's Enemy Unknown
I agree with tracktwo. I wouldn't go that route. I mean adding new variables to existing upks. It's unreliable and doesn't work under Linux and Mac. If you absolutely need to use more variables and functions, I suggest looking into mutators for XCOM project. -
Long War for Mac OS/X - pointers / advice?
wghost81 replied to thither's topic in XCOM's Enemy Unknown
Uninstall script was fixed fo b15e, you can use it instead of older versions. -
OW related bugs investigation (vanilla and LW)
wghost81 replied to wghost81's topic in XCOM's Enemy Unknown
wghost81 AT gmail DOT com