Jump to content

XMarksTheSpot

Members
  • Posts

    165
  • Joined

  • Last visited

Nexus Mods Profile

About XMarksTheSpot

Profile Fields

  • Country
    Germany

XMarksTheSpot's Achievements

Collaborator

Collaborator (7/14)

  • First Post
  • Collaborator Rare
  • Week One Done
  • One Month Later
  • One Year In

Recent Badges

0

Reputation

  1. From my experience it's possible to reference external ActionScript classes, you don't even need to explicitly import them like you do for sprite assets. Most of the game's Flash movies contain copies of commonly used classes, but those are just dummies; the actual classes reside in the gfxInterfaceMgr SWF movie. As menus are nested inside one another I suppose ActionScript classes are handed down along the hierarchy, too, i.e. sub-movies prefer to use classes from their ancestor movies instead of their local copies. I have sucessfully registered sprites as instances of AS classes that weren't embedded in the Flash movie I edited, so it's definitely possible. Adobe Flash won't allow exporting such a setup though, so at the very least you'll need stubs of the game's AS classes you're trying to reference. As for your data mining woes, I don't really know what the journal entries you're parsing look like, are they really plaintext items you're trying to parse? If that's the case, wouldn't it maybe make sense to hack into the code that prints those entries and alter them to be more compact and easier to parse? You could even go as far as encoding them in a binary format and printing them as Base64 strings. Or at the very least you could add missing information like the '[resource] increased from [old value] to [new value]' example you gave. If the journal is as large as you say, loading all of it into memory is probably a bad idea to begin with. In such a situation you'd typically want some form of parallelized streaming solution combined with an indexing system, but I kind of have my doubts that you can perform low-level tasks like this via UnrealScript, script languages typically aren't designed around that kind of functionality. Basically, a plaintext log is a very inefficient form of data storage, which puts considerable strain on re-parsing that into a data model. So my suggestion would be to condense the journal into something more usable - maybe some small additions could already help lessening the burden of data processing. For example, maybe it would be possible to insert a summary line of sorts at regular intervals (monthly, weekly, etc.) that would contain aggregated values. So to determine the value of a resource at any given point in time you wouldn't need to parse all those '[resource] has been incremented by [amount]' entries from the beginning, just from the last summary entry.
  2. Looks like it's coming along nicely, good job :thumbsup: I think the layout could use some more work. Some notes: I'd suggest hooking up your timeline control to the existing XComSlider widget AS class, that should have all the interactivity features you're looking for out-of-the box. Or just place one of the default slider widgets, though that probably clashes with your intended green color scheme, so you'll want a re-skinned widget :smile: What I think would be pretty nifty would be if the journal entries would be folded into the event list component you see in various base menus (main view, mission control, engineering, etc.). So in a sense playing back the timeline would also re-display the list of events that you were seeing at the corresponding points in time. Event list items allow you to categorize items (denoted via event icon) and are accompanied by a 'time left' display and a short text description. I imagine it would be nice if the event list could be filtered to only show items of specific categories, e.g. for tracking research progress or missions undertaken, etc. Again, extending a stock XCOM widget class could help you out here. Depending on what you have in mind when talking about 'scrolling' there's a few options. For instance, you could employ an auto-scrolling text component as it is used for research reports (XComVerticalScrollingTextField, I think, not sure about the name off the top of my head). If you're thinking about manually scrolling, an XComList would probably be best, i.e. wrapping your journal entries in list items and populating a vertical list with it. This is basically what the aforementioned event list does, so personally I would favor that solution over a plain text dump :smile: What do you mean by 'get flash to...'? Are you talking about Adobe Flash as in the authoring software? In that case there should be the usual alignment options if you have one or more elements selected in the stage [further reading]. I think centering is based on the pivot of your movie clip objects, so you should make sure to neatly align your sub-clips to make things easier. If you're talking about aligning stuff with ActionScript, there's no convenient shortcut for it, but playing around with the _x, _y, _width and _height MovieClip properties is pretty straightforward. It's usually a matter of something along the lines of this._x = (this._parent._width - this._width) / 2.0 if the object you want to align is a child of the object you want to align to. If 'aligner' and 'alignee' share a common parent it would be this._x = that._x + (that._width - this._width) / 2.0 Again, taking good care of your movie clips' pivots is good practice as the _x property refers to the pivot location, not the left edge of the clip itself. Using text-based buttons would be a viable alternative, however you'd have to take localization into consideration. The icons you're using are pretty universally understood, which is a rather elegant solution in my book :smile: Finally, a few random notes about the visuals (just my personal opinion, so to be taken with a grain of salt): I don't think the slanted look suits the track and knob very wellthe control buttons could use a slightly thicker border and maybe a few of the trademark double-thickness corner segments (might make them look too 'heavyweight' for their small-ish size though)the bottom text view could stand to be much smaller horizontally, there's lots of wasted space currently that could be used for other components (e.g. event list view, filter buttons *nudge nudge* :wink:)the timeline slider component on the other hand could be made much wider and more detailed, e.g. it could feature begin-of-month tick marks (maybe with month labels) or show little marker icons pointing to the track denoting certain events-of-interest, have a crappy mockup: the bottom section could be moved down a bit to overlap a little less with with map portion I'm quite interested to see how this develops, looking pretty promising so far :)
  3. How about simply wrapping the controls in a scrollable list? The widget components all implement IContainerItem so it should be pretty straightforward to drop them in a list, I'd say.
  4. Very interesting summary, much appreciated. I'm sure this'll come in handy. I knew a bit about how FlashRaiseMouseEvent() and OnMouseEvent() process stuff, but setting up everything is quite a different matter altogether :smile: As a general reminder, a good UI is also navigable using non-mouse inputs (i.e. keyboard, gamepad). From what I can see these types of input typically aren't funneled through the Flash movie like it's done for mouse events. Rather they're handled directly on the UnrealScript side in the corresponding UI class using OnMouseEvent()'s sister function OnUnrealCommand(), which usually contains a big old switch statement for determining the input command and then doing some further processing. This typically includes one or more ActionScript interface calls (either via the Invoke() method or via a special AS linker function [further reading]) to pass information to the Flash movie. A typical use case would be changing the currently focused interactive component in your menu (e.g. buttons, list items) using functions like SelectNext(), SelectPrevious(), SetSelectedIndex(), etc. in response to directional inputs (e.g. cursor keys, D-pad).
  5. I'll have to agree with Krazyguy here, saying new players wouldn't be interested in a campaign summary is bad attitude. If presented in an intuitively understandable fashion such a summary should appeal to all players alike, be it the seasoned veteran trying to min-max their strategy, the newbie trying to figure out what is happening to them or the casual player resuming an old game who wants to recall 'the story so far'. Therefore it is important to stick to a design that puts readability and ease-of-use at the forefront. It might seem tempting to cram as much information as possible into the limited space available, but you're doing so at the expense of at-a-glance understandability and will likely alienate the common player that way. After all there's a reason why the game's design is often more heavy on text than it is on icons. As for the discussion about colors, I typically don't mind color-coding information, but you need to be careful when doing so. Again, there's a reason the game sticks to its neutral cyan-on-black color scheme throughout most of its menus (mainly readability). As I see it a well-designed UI for the game should work fine using the neutral color scheme and should not depend on color-coding from the start. Again, color-coding isn't inherently bad, but it should only be used where it makes sense, i.e. when it provides additional and meaningful information. The game establishes precedents for that in several places, like the panic brick colors o the consistent use of purple for all things related psi. As such it would be wise to stick to established color schemes, for instance using the panic brick color series (which players are likely to have internalized already) as indicator of severity - the color defaults even have descriptive names that reflect this: So basically you need to ask yourself about your design 'What does color-coding bring to the table in this particular case? What would the menu look like without?'. The panic bricks are an example of good color-coding; upon opening the situation room menu you immediately see at a glance which countries are endangered due to eye-popping warning colors. If everything would be rainbow-colored all around there would be a lot of visual noise in which meaningful information would be drowned out. Also two more important things about UI design for the game that haven't been touched upon much are input schemes and localization support. When designing a new menu it's always tempting to, for instance, put buttons everywhere that perform various functions, but you need to keep in mind that the menu should be navigable via non-mouse controls, too, i.e. via keyboard or gamepad inputs. For this reason interactive components are usually grouped in close proximity to each other in the game's menus. This way directional inputs or primary and secondary buttons are contextualized as 'next', 'previous', 'accept', 'cancel' and so on. So it's always good practice to take a step back after laying out interactive components and asking yourself 'How would I activate this particular component without a mouse?'. As for localization, this has a similar impact on how components should be laid out. Basically we're limited to using what's provided in the localization files, which means strings like 'S-Africa' or 'UK' are out of the question as those aren't even defined in the basic English localization. Furthermore you need to keep in mind that different languages often feature different string lengths for the same terms. So if 'United States' turns into 'États-Unis' your layout may not be compromised, but when 'Germany' turns into 'Deutschland' you're suddenly presented with a string that's about a third wider (depending on the font used). For this reason using a two-column layout may not be a good idea as you cannot guarantee that to look balanced for all language versions. Okay, I think that's enough 'Design 101' for now, I didn't intend to rant this much again :sweat:
  6. That sounds pretty nifty. One noob question about getting the game to recognize custom classes though, what's the preferred method? Can I simply drop cooked script files (*.u) in the game folder or do they need to be neatly packaged in a *.upk? In the latter case the *.upk needs to be registered in an *.ini, could that also work for loose script files?
  7. Congratulations on figuring out a workaround, love the result :D Turns out the solution was rather more straightforward than anticipated, just adding a bit of translation on top of the scaling :)
  8. Hm, that's quite the setup you got there. I'm not sure the example you chose is a good one to demonstrate mutators with though. Since all XComStrategyAIMutator seems to be doing is spawning a strategy AI instance of a different type you could have simply done that right inside XGStrategy.NewGame(), e.g. if(m_kAI == none) { m_kAI = Spawn(class'XGStrategyAI_Mod'); } Also your XComMutator setup using a string parameter feels a bit forced, but I suppose you need a way to determine what mutator(s) to actually use when calling Mutate(). From my understanding mutators are daisy-chained, so calling Mutate() on the base mutator will in turn call Mutate() on its designated 'next' mutator and so on, thereby propagating mutation along all mutators. So as Mutate() is essentially called on all mutators and since you only want specific mutators to apply in any given situation, you need to pass some extra information on to mutators that specify whether or not they should actually 'fire'. I guess I'm with you on that front, but as a programmer I kinda disagree on how you structured XComMutator using a bunch of string checks passing implementation to a method stub that is supposed to be overridden with an actual implementation in a subclass. What you created is essentially an abstract type, but you're defining too many quasi-abstract methods for my taste. As I see it this makes the class very rigid as you'll have to add more cases as you need them, providing ever more cover methods. There's several ways to go about that. I'd suggest to embrace the abstract type concept and have sub-classes deal with only one or two generic methods to implement at a time. Unfortunately it seems UnrealScript only allows classes to be abstract and not methods, though at least this allows you to provide default implementations for your quasi-abstract methods. Suppose your XComMutator base class would look like this: Then you could provide XComMutator subclasses that only need to implement all of two methods and be done with it. Each mutator would deal with input checking on its own. This way it would also be possible to decouple input checking and implementation by putting those in different classes. So, for instance, if I would like to execute all mutators of a certain family of mutator types I could provide yet another abstract intermediate class that implements ShouldFire() using a type check and leave the implementation to the corresponding type instances, like so: The type-checking implementation given as an example here could also be used as the default implementation inside the base XComMutator class if you find it workable enough. But as I see you're also doing some other string processing on the inputs to extract additional parameters in XComMutator this might not be desired :smile: In this case I'd furthermore suggest to standardize input processing and relocate it to a separate method. A further modified XComMutator base class could then have the following alterations, for example: Again, this would allow parameter extraction to be separated from the other parts and could be handled in a unified fashion for specific type families, for example, or you could provide a default implementation that breaks apart the input string along a specific delimiter, for instance. Okay, I think that's enough rambling for now, hope you don't mind the criticism :smile:
  9. Can't say I can follow that. I, too, was curious about mutators a while ago and looked through what documentation you provided about the topic, but still couldn't figure out where to start. Your initial remarks back then about CheckReplacement looked promising initially, but then seemed to go nowhere and weren't mentioned later on, so that left me scratching my head. Looking at your example sources on GitHub didn't help much either. The scripts looked straightforward enough, but there was no indication how and where the MutateXYZ() methods need to be called. Documentation about the procedure is rather spotty currently, a more centralized how-to guide would be appreciated :)
  10. That's a native function, i.e. a function that is implemented in C++ instead of UnrealScript. You could probably remove the native modifier and turn it into a plain UnrealScript function, but you'd likely break it by severing its link to its C++ implementation that way. Theoretically you could re-implement the functionality in UnrealScript, but without knowing the C++ source this is rather futile.
  11. I don't use PatchUPK and wouldn't know about its pseudocode syntax. What I would do in case there is no precedence to using a specific variable is to grab a similar line of script code that is accessing a different instance variable and altering the value of the InstanceVariableToken (0x01) inside it to point to the desired variable instead. The InstanceVariableToken value seems to be a (typically negative) 4-byte integer, so most likely an index of sorts. I can't really make out how to determine the correct index for a specific instance variable (I suspected it to be related to the position in the Export table, but I don't see a correlation), but you could always just brute force it via trial and error, i.e. playing around with the value until you close in on the desired variable. Not really an elegant solution, I admit. Maybe someone else can shed some light on what the InstanceVariableToken value refers to.
  12. No idea about PatchUPK syntax, but I don't see why the LocalAtoms member variable of a SkeletalMeshComponent instance shouldn't be accessible. In what function are you trying to access the mesh component reference?
  13. Looking through some UnrealScript documentation I'm seeing a few hints that could be useful. Instances of the SkeletalMeshComponent class maintain lists named LocalAtoms that store AnimNode.BoneAtom structs. The LocalAtoms list is described as a and sure enough the BoneAtom struct contains members for rotation, translation and scale, i.e. struct BoneAtom { var quat Rotation; var float Scale; var vector Translation; }; I'm thinking it might be possible to look up the index of the desired bone by its name, grab the corresponding BoneAtom and modify its Scale property. Maybe something along the lines of this: local array<name> names; local int index; local BoneAtom atom; meshComp.GetBoneNames(names); index = names.Find("RigHead"); atom = meshComp.LocalAtoms[index]; atom.Scale = 2.0f; Could very well be that the BoneAtom structs are read-only and changing their member values has no effect, but it might be worth a shot.
  14. I can see where this is going, from the graphs point of view this is like presenting a vertical slice through all graphs. The side panels next to the map could then display the various values corresponding to the current point on the timeline, like current number of scientists/engineers, current research project, number of items manufactured and whatnot. This feels pretty much like option 1 to me, like you'd just skip to somewhere in the month-of-interest on the timeline and see the corresponding values displayed in the side panels. Maybe all that's needed is some form of toggle or setting that determines how far back the value aggregation is reaching, e.g. showing campaign totals so far or showing only differences accrued since the last council end-of-month report. I think the side panels are ill-suited to display data spanning multiple time points - the monthly breakdown mockups presented so far are really crowded and hard to parse, in my opinion.
  15. I suppose that depends, stubs can be rather detailed depending on your needs, e.g. Flash won't compile if you have a script accessing a variable in another class which hasn't been formally declared in it. So in the worst case a stub would have all variables and methods laid out, just without any actual logic, i.e. no variable assignments and empty methods. This may already be considered borderline intellectual property theft, but given Firaxis' rather lenient stance on sharing sources w.r.t. UnrealScript logic in XCOM2 I'd assume they'd turn a blind eye towards people extracting and sharing ActionScript sources. If push comes to shove there'd still be the option of creating a tool that creates stubs from your local game files, so no sharing of copyrighted assets required. Might as well automatically rip and decompile all the needed ActionScript byte code sources at that point though, no need for stubs if you can have (an approximation of) the real deal :smile: The downside to using decompiled sources is that they can be hard to read in many cases. This is mainly because the notion of local variables with distinct names typically gets lost in translation during the publishing procedure in Adobe Flash, i.e. variable names aren't part of the byte code and local variables are only referenced by pointing to a numbered memory register. Also I think for loops are transformed into while loops during the byte code compilation process, there's a number of things going on at the very least. So a bit of cleanup to reintroduce sensible variable names can help immensely to improve code readability, but that can't be automated easily.
×
×
  • Create New...