Jump to content

Number Six

City Council
  • Posts

    716
  • Joined

  • Last visited

  • Days Won

    15

Posts posted by Number Six

  1. 9 hours ago, Shenanigunner said:

    I didn't look closely when he brought this one up. I think it's either obsolete or a synonym for getglobalnamesilent, which definitely is. I should remove it from the cross reference list, the only place it appears.

     

    Neither. get_global_name_silent isn't a command and doesn't exist.

     

    get_global_silent does the same thing as get_global_name except it doesn't print the results to the chat window. So it's not useful as a manually typed slash command.

     

    It's used internally by the player note system to retrieve the global name when you add a note to a character the client doesn't already know the global for.

    • Thanks 2
  2. Version 4772

     

    File Downloads

    • Add defensive timeouts and low transfer rate detection to automatically cancel downloads from servers that don't fail but are not transferring data or are downloading extremely slowly. This should prevent a flaky connection from being able to stall progress forever; after some time it will move on to another source.
    • Add more detail to log message about failures to create destination files.
    • Be faster about cancelling download tasks and immediately closing the files when a user cancels an install; this should resolve access denied errors when restarting the same install right away.

    Miscellaneous

    • Redesign how disk caching works to prevent the newsfeed from sometimes failing to detect an updated copy on the server if the files were updated in a certain order.

    Command Line Interface

    • Fix a race condition that caused launchercli to often crash when running the list command.
    • Rewrite old code that hadn't been updated to handle the new way package dependencies work; this caused the list of profiles to not always wait for the information to be fully populated and sometimes show "unknown" state in CLI mode even when the packages are installed.
    • Like 2
    • Thanks 4
  3. kScriptNotify is the correct attrib name, I know because I wrote it. 😛

     

    It doesn't execute anything, it sends a notification to a script that's already running and has registered to listen for the event. Notice how the param type is correctly shown as ScriptNotify. It should match the attrib name but it doesn't here.

     

    I can only assume "Execute_Script" was put in as a friendly name to describe the old attribute that used to occupy the same index number. There's never been an attribute with that exact name.

     

    -            case kSpecialAttrib_LuaExec:              return (friendly ? "(exec Lua)"
     : "SpecialAttrib_LuaExec");
    +            case kSpecialAttrib_ScriptNotify:         return (friendly ? "(script notify)"          : "SpecialAttrib_ScriptNotify");

     

    • Thumbs Up 1
  4. I think your attributes names may be a little out of date, what's showing up as "Execute_Script" in the json dump is actually ScriptNotify.

     

    kLuaExec was removed because it was unused and implemented badly. The replacement probably ended up in the same slot so you might not have noticed since the attribute numbers didn't shift around.

    • Thanks 1
  5. Yes, the Homecoming launcher and game client both support Windows 11 natively. A decent portion of our players are already running it.

     

    Over the last week, based on user agents hitting the web servers checking for updates, the player base looks like:

     

    18,588 unique users

     

    62% HC Launcher

    38% Manifest-based launcher (approx 94% Tequila or derivative, 4% Island Rum, 2% Other)

     

    8% Windows 11

    85% Windows 10

    1% Windows 8

    3% Windows 7

    3% Wine Is Not an Emulator (Mac or Linux)

    4 brave souls running Vista

    3 oddballs running Windows Server 2016/2019

    1 lonesome Windows XP user

    • Like 1
  6. That's a very odd place for it to stop. The next thing that should happen after that message is it determines if you have a 64-bit machine, and if the right C runtime library is installed, but that seems to be getting stuck somehow, neither succeeding or failing.

     

    If you do have a 64-bit OS (the vast majority these days), you could try running the appropriate binary directly and not depending on the handoff from the 32-bit installer. Look under bin\win64 and try running the launcher.exe there.

  7. Gamma is unfortunately broken due to a Windows API change after a certain Windows 10 patch a couple years ago — something to do with the nighttime color shift they added.

     

    It works on *some* graphics drivers for some reason but definitely not all, including mine.

     

    I have a possible workaround in the pipeline but multimonitor setups make it difficult to do right without the risk of the game closing and not resetting the gamma back to what it was. Also investigating doing it at the shader level instead, but that may reduce color quality so I’m not sure if it’s the best way to go.

  8. 10 hours ago, BillyMailman said:

    Okay, I know the answer is probably completely useless, but the power math nerd in my heart has to ask: Why 38 distance 7 - - 19 / dup dup * * and not 45 distance - 19 / dup dup * * ? Is there some magic where the - operator is removing non-negatives and resulting in distance 7 - being a minimum of zero, and that's what stops the magnitude from going off to infinity? Because if so, that's both terrible that it clamps out negatives that way, and also a fantastic hack to prevent infinite magnitudes, even though the inner radius 7 should do that anyway. And if not, that just seems like a really odd way to do the subtraction.

     

    Nothing quite so interesting. That expression is the result of several iterations of development to try out different rates of pull and find something that felt right. It started out with distance 7 -, using an assumption that the inner radius should be the starting point of the calculation, and everything was built up around that but left separate so it could be easily tweaked. By pure chance the final version of it ended up using a construct that made the outer radius be the starting point and ignored the inner entirely, but I didn't bother to simplify the expression.

     

    The CoD parser tries to reformat it, but it's partly hampered by not being written to handle things like exponents. I not sure if UberGuy even knew the dup keyword was a thing until this power went in.

     

    10 hours ago, BillyMailman said:

    I look forward to the day when you're hopefully able to have the KB-to-KD IOs just change the vector stuff, so a KD-ified power doesn't still knock Clockwork backwards. Because that would be amazing if you could eventually make it happen

     

    You might be interested to know that I speculated about this possibility when writing up the design for vectored knock. This is one of the extra notes or 'useful tricks':

     

    Quote

    KB -> KD enhancements like Overwhelming Force and Sudden Acceleration can be reimagined as zero-magnitude Knock procs that have a high priority. This has the advantage of always working regardless if other unehancable KB or KU procs apply on the same tick and cause magnitude stacking.
    Effect {
            Tag "Knock"
            AttribMod {
                    Attrib kKnock
                    Aspect kCur
                    Target kTarget
                    Table "Melee_Ones"
                    Scale 0
                    StackType kReplace
                    Flags IgnoreStrength IgnoreResistance
                    Params Knock {
                        VecEnd Down
                        Priority 10
                        Vel 0
                        VelMag 0
                        Height 0
                        HeightMag 0
                    }
            }
    }

     

    The way that works is by adding a proc to every activation of the power the enhancement is slotted in that does a mag 0 knock. That will normally do nothing at all, but because it has a Priority 10 downwards vector, the one thing it does is to override any other knock from that source entity on the same server tick and replace it with the higher priority down vector.

     

    After some thought I came to the conclusion that while it's a neat trick, that wouldn't actually work for every case because some powers deal the knockback on a delay timer rather than right when the power hits, so this trick would miss converting those. Doing it properly will require some mechanism to override effect parameters of another power at activation time.

    • Like 2
  9. Afterward - What about ForceMove?

     

    Some of you reading this may have dug around enough to be familiar with an unused special attribute in the code called kForceMove, and are thinking ‘Hey, wait a minute, why not just use that?’ For those who haven’t, ForceMove is a special attribute that does what it says on the tin and forces an entity to move to a specific location.

     

    After about 15 minutes of looking at the ForceMove implementation it was clear that it would be a bad idea to use it for anything, ever. It’s obviously a very early work in progress meant only to test the idea.

     

    How ForceMove works is:

    If the target is a critter (NPC), it instructs the AI to move to that location. The AI constructs a path and walks there. It doesn’t even use wire movement, it just walks along the path.

     

    Worse, if the target is a player - doesn’t matter if we’re talking PVP or a power you use on yourself - it sends a network packet to the client that tells the client to lock autofollow on the destination coordinates. Then the client tries to move there just like you had click-to-move turned on. The latency alone between the client and server’s view of the world makes this a bad idea, and I’m sure anyone who’s used autofollow while multiboxing is shuddering right now just because of how unreliable it can be.

     

    There’s also the issue of targeting the ForceMove. The test powers that use it make use of another new feature called kPosition targeting which is a good idea, but also was still fairly early in the design process and there are a number of issues with the implementation. The biggest one is that the target location is resolved not at power activation, but rather at the moment the power is queued. For NPCs that’s not really a problem, but players queue powers all the time while they’re out of range or out of endurance or otherwise in a situation where it won’t actually activate for a long time. In that case, the location used for the power would be relative to the place where the player queued the power rather than where they were when it became able to activate.

     

    TL;DR: The idea of ForceMove is interesting, and its best use case would probably be something like a “Charge” power that runs toward a target. However before that could happen the implementation needs to be scrapped and rethought.

    • Like 8
    • Thanks 8
    • Haha 1
    • Confused 1
    • Thumbs Up 2
  10. Part 4 - Pull in Practice

     

    The first player-facing application of the new tech was the Singularity change. This was chosen because it’s not an extremely common powerset and would let us evaluate it at a small scale. Being a pet power it would also be more difficult to take advantage of if there was some bug that allowed it to be use exploitatively or for griefing, etc. The power def for Singy’s new trick looks like:

     

        Effect
        {
            RadiusInner 7.0000
            RadiusOuter 45.0000
            Requires enttype target> critter eq
    
            AttribMod
            {
                Attrib kRepel
                Aspect kCur
                Type kExpression
                Target kTarget
                Table "Ones"
                Scale 1.0000
                Duration 0.6250
                MagnitudeExpr 38 distance 7 - - 19 / dup dup * *
                Magnitude 1.0000
                StackType kReplace
                CancelEvents Teleported
                Flags IgnoreCombatMods
                Params Knock
                {
                    VecStart                       Target
                    VecEnd                         Source
                    Vel                            0.0000
                    VelMag                         0.1000
                }
            }
        }

     

    That’s only the PvE version of the effect for brevity. It’s a fairly standard Repel attribmod but with the vector swapped from the normal direction, and the velocity calculation overridden. The magnitude expression here is to simulate a dense gravitational source and translates to 

    ((45-dist)/19)^3. In other words, the pull is very strong near the event horizon and quickly falls off to very weak for targets further away.

     

    We learned some valuable lessons from this, including finding out that players teleporting while under the effects of a Repel effect caused all sorts of terrible rubber banding. That particular bug in motion prediction predates the vectored implementation and has probably been around for as long as Repel has, but it was never noticed because teleporting while being repelled was such a rare occurrence. Once the pets of Family bosses had access to it that changed very quickly. The same bug affects Knockback, but since KB effects only last 1 server tick it’s even harder to trigger there.

     

    The same effect appears on a larger scale in Dr. Aeon’s Strike Force under conditions that I won’t reveal because it’s a spoiler, but it plays a role in a particular boss fight and draws all the players in to a big portal during one of the phases. The motion prediction problem with teleport turned out to be a blocking issue for that encounter, and so the bug is fixed in Page 3.

     

    There are a few more subtle uses of the tech in the upcoming update. Seismic blast has a knockdown patch that uses a down vector to avoid becoming knockback when effects get stacked. Scrapper/Stalker Stone Armor’s new Geode power uses reverse Repel internally for better control over the position of the pseudopet that it spawns. Given how flexible the system is, I think it’s fair to say we’ll be seeing it used more as the powers team gets more comfortable with it.

    • Like 9
    • Thanks 4
    • Thumbs Up 1
  11. Part 3 - Anatomy of a Power

     

    With all that history out of the way, I’ll jump straight into the design. Here’s a copy and paste from the documentation for how to use the new effects:

     

    Effect {

        AttribMod {

            Attrib kKnock

            Scale [num]

            Params Knock {

                VecStart [Anchor]

                VecEnd [Anchor]

                AdjustPYR [pitch] [yaw] [roll]

                Priority [integer]

                Vel [num]

                VelMag [num]

                Height [num]

                HeightMag [num]

            }

        }

    }

     

    A few bits of context here.

    1. kKnockback was renamed to kKnock, though the old name was retained so powers could be loaded without changing them immediately.

    2. kKnockUp was deprecated. Now that powers can specify what direction they want to knock something, having a separate attribute for it became wholly redundant. It still exists for compatibility reasons, but will eventually be fully replaced by kKnock effects and removed.

    3. The Knock parameters above also work for kRepel effects.

    The important part of that structure are the VecStart and VecEnd parameters, they put the vector in vectored KB. A ‘traditional’ knockback would use VecStart Source, VecEnd Target. A ‘get over here’ grappling hook power would use VecStart Target, VecEnd Source. VecEnd also accepts things like Up, Down, and Facing, which is where the KnockUp replacement comes in.

     

    The ‘Down’ vector is especially interesting, because it allows for the creation of powers that cause Knockdown but have a high magnitude and can punch through KB protection. This is something that was not possible before, since a high magnitude would normally mean a long knockback distance. Knockdown powers with a ‘down’ vector also cannot merge together into KB and will always stay as Knockdown.

     

    AdjustPYR is also quite a bit of fun and was used in the April Fool’s Day Brawl. After the knock vector is calculated, that setting can be used to rotate the vector along an axis and point almost any direction you can think of. Imagine a sweeping strike with a Titan Weapon that knocks the target left. Or a Whirlpool that uses vectored repel to actually drag things in a spiral.

     

    Priority is used to disambiguate effects that happen on the same tick. The new system is fairly smart about it and unlike the old one that could only remember a single source, it now merges multiple vectors together, so you end up with a final direction of everything averaged together. But if you wanted to make a power that takes precedence over everything else, a designer can do that by setting a higher priority.

     

    The last 4 are for fine-tuning the velocity of the effect and just how much of it is derived from the magnitude, as well as doing the simulated arc that traditional knockback effects have. Back to the design doc, the defaults that correspond to each type of effect are:

     

    kKnock (aka KB): Vel = 1.0, VelMag = 0.025, Height = 3.0, HeightMag = 0.25

    kKnockup: Vel = 0, VelMag = 0, Height = 6.0, HeightMag = 1.0

    kRepel: Vel = 0.5, VelMag = 0.2, Height = 0, HeightMag = 0
     

    Velocity is in world units per tick, being roughly feet per 1/30th of a second. Val is a fixed constant, while VelMag acts as a multiplier on the magnitude from the kKnock attribute. Height is a fun one, having a Height is what simulates being knocked in an arc. It’s also… complicated so I’ll just snip part of the design doc rather than try to break it down.

     

    kmRr30XOJkGTSbR07Zpjf8ON3nIT1nUzv4U2c56o6p1-0g0NXjX3ilP0y2stgSemXn0czNJzpeTBVuwuETCQ8VvKHw8PklXNkJ_74k2qXEfmSvGRCul2UClMQu8-FR8YsvDre_DQ

     

    A lot of math for something that we take for granted.

    • Like 9
    • Thanks 2
    • Thumbs Up 2
  12. Part 2 - Visualizing the Change You Want to Be

     

    When I first began thinking about how to do something along the lines of reverse knockback, I decided that we needed to plan something that would be flexible and future-proof.

     

    A very early proof-of-concept prototype was done that added two new attributes, called kKnockIn and kAttract, just to test the concept. Those attributes worked exactly like Knockback and Repel, but with the source and target entities swapped.

     

    Those attributes were never intended to be anything more than a proof of concept, and indeed never even made it out of a development branch. Somewhere gathering dust I have a copy of Assault Rifle with an M30 grenade that makes big groups hilariously get flung right on top of you. There were obvious problems with that approach, the least of which being the annoyance of having to fill out class tables for these new attributes for 10+ archetypes, add them to every KB protection power or enhancement in the game, etc.

     

    Ultimately though, I thought that we could do better. There weren’t any real tools for moving entities around from powers other than Teleport (and ForceMove but that’s terrible, see the afterward), and I could think of all sorts of interesting things that could be done if the designers had more control there. So then came the brainstorming.

     

    After a lot of design revisions and bouncing ideas off the team, we came up with the sketch for the Vectored Knock system. It would be built on Effect Parameters - an innovation from the Issue 25 power system revamp that lets different effects take any number of arbitrary parameters in an efficient way - and would let designers specify not just the direction of the knock, but also fine-tune exactly how the velocity is calculated, so that the strength of the effect would not necessarily have to be tied directly to the magnitude. A priority system was also devised to give us the ability to decide exactly what happens if multiple conflicting effects are applied on the same tick.

    • Like 10
    • Thanks 3
    • Thumbs Up 1
  13. Part 1 - A History Lesson

     

    Before going too deep into how vectored knock works, let’s take a moment to rehash the mechanics that were in place for many years. Historically there are 3 of what we call Attributes that are of interest here:

     

        kKnockback

        kKnockUp

        kRepel

     

    Since these are standard attributes, they have a numeric value associated with a character -- by default everybody’s attribute for these are ‘0’. KB effects increase the value of your Knockback attribute, KB protection effects are just a negative magnitude effect that keeps it from going above 0. Incidentally, that’s why the commonly suggested ‘negative knockback’ couldn’t work; because negative knockback is just KB protection that you already get from a number of sources.

     

    Knockback is the most common of these effects. If the magnitude of the Knockback attribute ever gets above 0, an entity is Knocked -- some velocity is added to them and they are put into a special animation. For NPC critters, that can include going into ragdoll mode.

     

    The direction of the knock comes from the game remembering the last entity who hit you with a knock effect, this happens because effects very frequently have some amount of delay on them to wait for animations to play. That can cause some rather amusing artifacts if one of both of those entities moved a long distance between when the power was activated and the effect actually hits. The distance of the knock is calculated based on the magnitude of the effect, and the game also adds a surprising amount of calculated upwards velocity to make the target sail in a visually satisfying arc.

     

    Knockback also comes with a special case built into it. kKnockback attribute values that are above 0 but below 0.75 instead result in Knockdown, which plays a different falling-over animation and does not add any velocity or ragdoll. One well-known quirk of this mechanic is that if two separate Knockdown effects hit on the same combat tick, the combined magnitude may well exceed 0.75 and get converted to Knockback instead.

     

    KnockUp -- go on, get your giggles out and then get your mind out of the gutter -- is an entirely different attribute that works very similarly, but handles only upward movement. You may notice that KB protection powers actually provide both KB and KU protection separately. There’s not much to say about KU other than that the moment of velocity it imparts is calculated based on a different formula, but still based directly on the final magnitude of the effect (after KU protection is subtracted).


    Repel may seem very different at first, but is mechanically quite similar. Most of the difference in Repel effects don’t come from the attribute itself, but instead from how powers conventionally use it. The primary mechanical difference is that Repel does not make the target play an animation, and it pushes in a straight line away from the source instead of doing math to try to curve the arc. From a powers perspective, Repel effects usually have a duration and apply continuously, while Knockback effects are typically a 1-tick impulse. However, there’s no reason Repel couldn’t be used to give a sizable brief shove instead.

    • Like 7
    • Thanks 2
    • Thumbs Up 2
  14. Hello, heroes and villains!

     

    Some of you know me already, but for those who don’t, I’m Number Six, Homecoming’s lead for what we call the ‘code’ side of the development team. So not the outwardly fun stuff like powers and missions - though I do have some involvement in those - but the boring and technical things like engine development, user interface, data processing, etc. Basically anything that involves actual compiled program code goes across my desk.

     

    Today I want to talk about something that is near and dear to many of your hearts, or in some cases, hated with a fiery passion: Knockback. While it may be sometimes controversial, this game mechanic is not only iconic in the super genre in general and COH/V in particular, it’s also the vehicle for one of the more fun new toys we’ve developed for the content developers - the ‘data’ side of the team - to play with.

     

    As some of you may have noticed, a while back we quietly and without much fanfare slipped in an effect that had never been seen in the City before: Gravity Control’s singularity pet was changed to pull enemies towards it. This kind of ‘reverse knockback’ or ‘negative repel’ is something that had long been asked and theorized about, often in the context of crazy ideas for how to implement it with various hacks like spawning dozens of carefully positioned invisible pets.

     

    Those with even sharper eyes may have noticed all the way back in April 2020 when, for a day, Brawl was sending its targets flying in all sort of random directions.

     

    Both of those were tests of a new engine feature that we developed in February of 2020 that has a lot of exciting potential, far beyond simply sucking stuff to a central point. It gives power designs a new level of flexibility they never had before, and quite literally changes the game. Far from being just a new feature, the vectored knock system replaced the existing knockback mechanics entirely, which is part of why we were extra cautious about rolling it out and wanted to make sure it didn’t change the ‘feel’ of knockback in any way.

     

    Now that it’s been well over a year since the system was in place and nobody noticed the difference, we’re starting to see content that takes advantage of it emerge from the development pipeline. I’ll cover it in more detail further down, but the new system is used quite a bit in the new Strike Force and powersets being rolled out in Page 3. In this series of posts, I'll do a deep dive into the development of this feature and some of the technical underpinnings of how it works.

    • Like 15
    • Thanks 9
    • Thumbs Up 6
  15. We changed the default order because far more people use Beta than Prerelease, so it made sense to put that in a more convenient spot.

     

    Hardly anyone ever logs into Prerelease other than developers doing a final quality check before go live. At some point in the future it may be hidden by default (you can toggle this in the options page) to avoid any possible confusion.

     

    The good news is that the default order is just that, a suggestion, and you can re-order them however you like by simply dragging the little cards around. The default only applies if you haven’t ever customized the order, so once you do that it will stick forever, or at least until you change it again.

    • Like 1
    • Thanks 1
    • Thumbs Up 1
×
×
  • Create New...