Author Topic: Technical side discussion  (Read 164661 times)

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #460 on: September 30, 2018, 07:16:30 PM »
@Spectre1989 - I learned something today from @Leandro that you'll want to know: When a model name has a suffix that begins with a double-underscore, that suffix is a trick from tricks.bin. That info helps me reconcile some of the issues I was having with model names not matching up with def names in the scene graph. For instance, a def named AP_crack_decal_01_sml where the corresponding model is named AP_crack_decal_01_sml__Graflg (and every other model in that .GEO likewise suffixed "__Graflg"). "Graflg" is a trick that sets level of detail and collision flags. In this case, it's a decal of a crack in a sidewalk, so it's flagged as "no collide" via the suffix.

So, if you're checking a def name or some other string against the model names in a .GEO, you need to do a substring match or trim the suffix or something similar. The actual model name might not be what you're expecting.


spectre1989

  • Minion
  • **
  • Posts: 38
Re: Technical side discussion
« Reply #461 on: September 30, 2018, 08:08:44 PM »
@Spectre1989 - I learned something today from @Leandro that you'll want to know: When a model name has a suffix that begins with a double-underscore, that suffix is a trick from tricks.bin. That info helps me reconcile some of the issues I was having with model names not matching up with def names in the scene graph. For instance, a def named AP_crack_decal_01_sml where the corresponding model is named AP_crack_decal_01_sml__Graflg (and every other model in that .GEO likewise suffixed "__Graflg"). "Graflg" is a trick that sets level of detail and collision flags. In this case, it's a decal of a crack in a sidewalk, so it's flagged as "no collide" via the suffix.

So, if you're checking a def name or some other string against the model names in a .GEO, you need to do a substring match or trim the suffix or something similar. The actual model name might not be what you're expecting.

Very useful! Thanks for sharing

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #462 on: October 01, 2018, 01:17:16 AM »
I'll apologize again for appearing to use this thread as my running development blog but I'm treading in waters that nobody anywhere has documented, as far as I can tell, and when Codewalker eventually drops by again, I want him to be able to say right then, "Yeah, you're on the right track" or "No, you're completely off there."

Anyway - after spending some quality time with defnames.bin today and making a kaitai parser for it (the kaitai parsers aren't necessarily the most efficient but the web IDE is handy for visually analyzing data and structure of a file) I realized that defnames.bin is, in fact, organized just like one would expect it to be organized. The weird thing that's going on with the indexes is that some of them are having their high-bit set for some reason that is not intuitively obvious (to me, anyway). If I mask off those high bits then the indices work out just like they should. This is probably yet another shortcut by the Cryptic/Paragon Studio devs to incorporate flags into records without explicitly making space to store them, like the instance I mentioned earlier of trick names being tacked onto model names.

Anyway, I think when I pick this back up tomorrow that I may stand a reasonable chance of realizing an entire scene graph now that I have some clues to these mysteries. Famous last words, yeah.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #463 on: October 01, 2018, 04:20:28 AM »
What I need to know - How is the Paragon Chat "server" building the list of object library bin files that it sends to the client? I'm asking because processing the map geobin is leading me to all kinds of loose ends that APPEAR to be irreconcilable with either the virtual filesystem in the .piggs or the index in defnames.bin. It looks like an object path in the map geobin is a reference to a scene graph branch rather than some kind of absolute file path. How are you finding the absolute file paths to load from?

Loading defnames, loading geobins for library objects, and parsing geos. I'll try to drive in deeper where I can but there's a lot going in in the thread to try and keep up with.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #464 on: October 01, 2018, 04:30:16 AM »
PVPro tells me that all of those textures in the texture library are stored in the piggs as .texture files. However, all of the references in the databases refer to Targa .tga files and that's the one option that PVPro does NOT export them as. PVPro lists "original" as .dds. It's easy enough to work around that, but I want to make sure that I'm not missing something or losing some functionality by dealing with the textures as .dds or some other format compared to whatever raw format a .texture file is. Of course, it would make some sense if the Textparser turned the original .tga files into .dds files in the process of compiling them into the .pigg files.

Textparser doesn't have anything to do with textures. That's all handled completely separately.

Ignore the file extensions you see for textures. They're meaningless. Completely meaningless - the client strips them out and ignores them. You can put any junk you want there and it'll work fine. Assume you're looking for a '.texture' file with that base name.

Many of the files reference tga, but I've seen no evidence that tga was used as a file format during development for many years - it's just something devs threw in there because they copied it from elsewhere.

A texture file is an extra header that wraps around one of two formats. It can either be:

* A dds file. The whole thing, header and all. I've only seen uncompressed RGBA, DXT3 and DXT5 used; I don't think other compression algorithms are supported.
* A jpeg file. (this only works for loading screens, you can't use jpeg textures ingame)

Since the generation of dds used by COH only supports power of 2 sizes, the texture header includes the "real" size of the texture. Badge images are a great example of this in use.

I don't think targa is natively supported for textures. It might have been in older builds, but not anymore. Those would probably need to be converted to a lossless (RGBA) dds first and wrapped in a texture header.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #465 on: October 01, 2018, 04:33:00 AM »
So, now it's textured, but I'm doing this all by hand right now. What I still don't see is how "x_H_Shuttle" in the .GEO file turns into "/texture_library/World/Space/Shuttle/H_Shuttle.dds". I expect this goes along with all of the defnames.bin entries that are numbers that don't have a corresponding path they index to. There's some part of the index that is either "missing" or that needs to be built up by the client.

tricks.bin

Code: [Select]
    -------- Texture 10421 --------
    Name = x_H_Shuttle
    FileName = TRICKS/SPACE/SHUTTLE.TXT
    FileAge = 1152634253
    u002 = x_H_Shuttle
    Gloss = 1
    Surface =
    Fade1 = 0
    Fade2 = 0
    ScaleST0 =
        X = 1
        Y = 1
    ScaleST1 =
        X = 1
        Y = 1
    Base =
    BumpMap = H_Shuttle_bump.tga
    ObjFlags1 = 0
    ObjFlags2 = 0
    ObjFlags3 = 0
    DF_ObjName =
    Base1 = H_Shuttle.tga
    Base1Scale =
        X = 1
        Y = 1
    Base1Scroll =
        X = 0
        Y = 0
    Base1ScrollType = 0
    Base1Swappable = 0
    Multiply1 = None
    Multiply1Scale =
        X = 1
        Y = 1
    Multiply1Scroll =
        X = 0
        Y = 0
    Multiply1ScrollType = 0
    Multiply1Swappable = 0
    DualColor1 = none
    DualColor1Scale =
        X = 1
        Y = 1
    DualColor1Scroll =
        X = 0
        Y = 0
    DualColor1ScrollType = 0
    DualColor1Swappable = 0
    AddGlow1 = none
    AddGlow1Scale =
        X = 1
        Y = 1
    AddGlow1Scroll =
        X = 0
        Y = 0
    AddGlow1ScrollType = 0
    AddGlow1Swappable = 0
    BumpMap1 = H_Shuttle_bump.tga
    BumpMap1Scale =
        X = 1
        Y = 1
    BumpMap1Scroll =
        X = 0
        Y = 0
    BumpMap1ScrollType = 0
    BumpMap1Swappable = 0
    Mask = H_Shuttle.tga
    MaskScale =
        X = 1
        Y = 1
    MaskScroll =
        X = 0
        Y = 0
    MaskScrollType = 0
    MaskSwappable = 0
    Base2 = H_Shuttle.tga
    Base2Scale =
        X = 1
        Y = 1
    Base2Scroll =
        X = 0
        Y = 0
    Base2ScrollType = 0
    Base2Swappable = 0
    Multiply2 = Shader_Reflect_chrome_09.tga
    Multiply2Scale =
        X = 1
        Y = 1
    Multiply2Scroll =
        X = 0
        Y = 0
    Multiply2ScrollType = 0
    Multiply2Swappable = 0
    DualColor2 = none
    DualColor2Scale =
        X = 1
        Y = 1
    DualColor2Scroll =
        X = 0
        Y = 0
    DualColor2ScrollType = 0
    DualColor2Swappable = 0
    BumpMap2 = H_Shuttle_bump.tga
    BumpMap2Scale =
        X = 1
        Y = 1
    BumpMap2Scroll =
        X = 0
        Y = 0
    BumpMap2ScrollType = 0
    BumpMap2Swappable = 0
    CubeMap =
    CubeMapScale =
        X = 1
        Y = 1
    CubeMapScroll =
        X = 0
        Y = 0
    CubeMapScrollType = 0
    CubeMapSwappable = 0
    Color3 =
        Red = 0
        Green = 0
        Blue = 0
        u300 = 1
    Color4 =
        Red = 0
        Green = 0
        Blue = 0
    SpecularColor1 =
        Red = 250
        Green = 230
        Blue = 255
    SpecularColor2 =
        Red = 200
        Green = 200
        Blue = 230
    SpecularExponent1 = 20
    SpecularExponent2 = 1
    Reflectivity = 0
    ReflectivityBase = -1
    ReflectivityScale = -1
    ReflectivityPower = -1
    AlphaMask = 1
    MaskWeight = 1
    Multiply1Reflect = 0
    Multiply2Reflect = 1
    BaseAddGlow = 0
    MinAddGlow = 1
    MaxAddGlow = 120
    AddGlowMat2 = 0
    AddGlowTint = 0
    ReflectionTint = 0
    ReflectionDesaturate = 0
    AlphaWater = 0
    DiffuseScale =
        Scale = 0.35
        u901 = 1
        u902 = 1
    AmbientScale =
        Scale = 2
        u901 = 1
        u902 = 1
    u425 = 0
    u426 = 0
    u427 = 0
    Fallback =
        ScaleST0 =
            X = 1
            Y = 1
        ScaleST1 =
            X = 1
            Y = 1
        Base = H_Shuttle.tga
        Blend =
        BumpMap = H_Shuttle_bump.tga
        BlendType = 0
        UseFallback = 1
        DiffuseScale =
            Scale = 0.75
            u901 = 1
            u902 = 1
        AmbientScale =
            Scale = 5
            u901 = 1
            u902 = 1
        u507 = 0
        u508 = 0
        u509 = 0

EDIT: To clarify, the texture namespace is flat -- each texture is identified by the unique file name and the subdirectory path doesn't matter.

When the trick references H_Shuttle.tga and H_Shuttle_bump.tga, those are looked up in an internal index built at client startup time. You have to scan all of the texture files - the name is included in the header rather than using the actual file name - and index the names to the file locations. That's why the pigg header cache is so critical for startup time.

As mentioned earlier, the extension is stripped off before building the index. So you could reference H_Shuttle.texture, H_Shuttle.dds, H_Shuttle.exe, or just plain H_Shuttle and you'd get the texture.
« Last Edit: October 01, 2018, 05:14:34 AM by Codewalker »

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #466 on: October 01, 2018, 04:38:51 AM »
@Spectre1989 - I learned something today from @Leandro that you'll want to know: When a model name has a suffix that begins with a double-underscore, that suffix is a trick from tricks.bin. That info helps me reconcile some of the issues I was having with model names not matching up with def names in the scene graph. For instance, a def named AP_crack_decal_01_sml where the corresponding model is named AP_crack_decal_01_sml__Graflg (and every other model in that .GEO likewise suffixed "__Graflg"). "Graflg" is a trick that sets level of detail and collision flags. In this case, it's a decal of a crack in a sidewalk, so it's flagged as "no collide" via the suffix.

So, if you're checking a def name or some other string against the model names in a .GEO, you need to do a substring match or trim the suffix or something similar. The actual model name might not be what you're expecting.

Ok, so you already got object trick overrides (bindump erroneously calls the field LOD but it's more than that). Good.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #467 on: October 01, 2018, 04:41:16 AM »
The weird thing that's going on with the indexes is that some of them are having their high-bit set for some reason that is not intuitively obvious (to me, anyway). If I mask off those high bits then the indices work out just like they should. This is probably yet another shortcut by the Cryptic/Paragon Studio devs to incorporate flags into records without explicitly making space to store them, like the instance I mentioned earlier of trick names being tacked onto model names.

It's probably a union. A number of the in-memory structures use things that are obviously C unions.

The index is a 16-bit integer. The low bit of the next field is a flag that indicates if the defnames entry is a rootname -- a model in a geo file rather than a Group from a geobin.

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #468 on: October 01, 2018, 05:06:48 AM »
That all makes me curious, though - Does the textparser still look for those original text files when the client launches? If someone was able to recreate a developer working directory, could you load your own versions of those text files?

It's complicated. I'll try to answer this as well as the follow-up question about Paragon Chat that I remember seeing, but I think got lost in your edits.

The client has a fully functional textparser. It can load any file from either text or binary form, *if* the functions are called with the right parameters. It can even *save* any file back into text form, though for things like powers.bin, a lot of the enums get screwed up because there's a giant shared table for them. You end up with nonsensical names for certain values in the Scale field, for instance.

You can't just go overriding files from the piggs with text files willy-nilly. The way it's supposed to work in development mode is this:

  • No pigg files at all
  • All of the data in text form
  • If a bin file is missing or the text version is newer (per the filelist), data is loaded from the text version and persisted in the bin file
  • Otherwise, load the bin

The release client doesn't have all of the code paths for this. Some of it is there, but is 'dead code' and unreachable in normal execution. The client is locked in 'production mode', likely by a compile-time flag or preprocessor definition, and there's no simple way to modify that.

Production mode looks like this (I'm simplifying a bit since the first two are handled by the VFS system and the last one is handled by textparser):

  • If the bin file exists in data/, and isn't in the 'overrides prohibited' list, load it from there.
  • If the bin file exists in a pigg, load it from there.
  • Nothing else worked, if there's a text version in data/, might as well try and load it.

So the only way to get the production client to load text files -- aside from calling the functions directly with the aid of a debugger or the dynamic code rewriting engine that I use for ParagonChatClient -- is if no corresponding .bin file exists. That's why people are able to load custom maps in text format, because of course new maps have no .bin in data/geobin/.

That means if you want to load text files for bins that already exist, you have to:

  • Extract *everything* from the pigg files into data/.
  • DELETE all pigg files.
  • Patch the client to remove the override list (see the forum thread about map editing)
  • DELETE the bin file corresponding to what you want load from a text version.

I honestly don't remember if the automatic bin-generation code will work in that circumstance. It might be completely disabled in production mode, or it might recompile a bin which you have to delete if you want to change the text file(s) again. The code *exists* and I can call it manually (and have done that to generate some of the bin data for PChat), I just don't remember if it's in the normal execution path or not.

As for Paragon Chat's imitation textparser -- unfortunately none of this will work for that. The 'server' piece knows enough to read bin files, but for most of the parse formats it doesn't know the field names for the text form, or even what file to try to load it from. Costume files are the obvious exception since it needs to be able to read those in both text and binary format, but it can't even load maps in text format. I compiled the modified Pocket D to bin format in order to bundle it.

spectre1989

  • Minion
  • **
  • Posts: 38
Re: Technical side discussion
« Reply #469 on: October 01, 2018, 07:58:38 AM »
Also the SEGS map viewer may help you with the scene graph, though it's using I1 data.

https://github.com/Segs/Segs/tree/develop/Projects/CoX/Utilities/MapViewer

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #470 on: October 01, 2018, 01:31:13 PM »
Thanks for all of that, Codewalker. I need to start following @Spectre1989's example and start documenting all of this stuff as I do it, for posterity.

Since you touched on the custom maps question - I ran an experiment this past weekend around that. I patched the client with your patch and installed @GuyPerfect's "Atlas Park Echo" mod into Paragon Chat's client/data folder along with a zones.cfg entry to reference it.

It actually worked, as far as displaying the map. Something was wrong with the collision detection, though. If my char wasn't flying, it fell through the geometry after a bit of bouncing around.

Maybe you can try it one of these days and see if there's a way to correct that in such a mod.

On a separate note, seeing that map got me right in the feels. I was a closed beta tester for CoH. Seeing old City Hall and Atlas and even, weirdly, the skylights on the corner a few blocks away, reminded me what it felt like to experience CoH for the first time. I hadn't felt that in a long time.
« Last Edit: October 01, 2018, 01:53:09 PM by slickriptide »

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #471 on: October 01, 2018, 03:57:39 PM »
It actually worked, as far as displaying the map. Something was wrong with the collision detection, though. If my char wasn't flying, it fell through the geometry after a bit of bouncing around.

That's what I would expect. Classic desync.

The client is loading the map, so you're able to see it (top-level refs get instanced in the client's scene graph even if the server fails to send them; this is necessary for demo playback, etc). The server sends the map name from the cfg, but is unable to load the map itself, resulting in an empty scene.

As a result, the client tries to do motion prediction based on the geometry that it has, but on the server you're just falling through empty space. That causes rubber banding when the client gets entity updates and corrects its 'wrong' prediction.

In order to make it work, you'll need to put a copy of the geobin for the map into the appropriate path under ParagonChat\data as well as the client's data folder.

PChat itself gets around having to duplicate it (and having to bother to patch the client's foldercache) by creating a pigg file with what it wants to load and stacking that on top of the VFS on both the client and the server.

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #472 on: October 01, 2018, 04:27:02 PM »
PChat itself gets around having to duplicate it (and having to bother to patch the client's foldercache) by creating a pigg file with what it wants to load and stacking that on top of the VFS on both the client and the server.

I'm not sure why, but that explanation of the desync strikes me as being a cool look inside of PChat.

So, let's say that I wrote a map editor. Does the above mean that if I exported the mod data (bin files, custom geos/textures, modified defnames.bin, etc...) as a .pigg file that was installed under the Paragon Chat /data folder, that the included overrides would work for both the "client" and the "server" side of things?
 

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #473 on: October 01, 2018, 04:36:16 PM »
Currently, no. Only the ParagonChat.pigg file gets special treatment that way, and you can't really modify that because it'll get overwritten by PChat itself after updates.

You could fool it by creating a pigg and putting it under the *I24* pigg directory, which both PChat and the client load *.pigg from. You'd probably want to call it Z-something.pigg, so that it's last in alphabetical order. That would result in it being loaded after all of the regular piggs, and just before ParagonChat.pigg.

My long term plans involve creating an add-on system for Paragon Chat which would remove a lot of the guesswork. The idea is to package assets up in a zip file or similar format with a manifest, then PChat would take care of the details of getting the files for all enabled add-ons to the proper place for both the server & client components to use. Whether that means repacking them into a pigg, or using some other method to inject them into the client's VFS is a implementation detail that shouldn't matter to the addon developer.

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #474 on: October 03, 2018, 07:45:30 PM »
Do we know what all of the extra data means in the .texture files?

The first part of the header seems to be pretty well mapped out. However, there's an additional section that appears after the filepath IF the texture is not a "flat" texture;  that is, it's associated with geometry and not a loading screen or city map or some such.

The extra bit is 64-bytes long. The first 16-bytes seem to be flag fields. They typically look like this:

Flag-1: 16
Flag-2: 8 or 4
Flag-2: 8 or 4
Flag-3: 33777 or 33779

The rest is a block of binary data.

Strictly speaking, I get what I want by just ignoring it and extracting the .dds file into memory and attaching that to the model in the scene graph. I'm curious, though, if it's known what that 64 bytes of additional header means, and if any of it is information that I might potentially want to know about as far as creating a visual of the object the texture is attached to.




Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #475 on: October 03, 2018, 08:13:35 PM »
Cached copy of the lowest resolution mipmap. It gets used as the placeholder texture while a background thread loads the actual textures from disk.

Header Size
Width
Height
Texture Format
  (33777 = 0x83F1 = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
  (33779 = 0x83F3 = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)
  (https://www.khronos.org/registry/OpenGL/api/GLSC2/glsc2ext.h)
Padding
Texture Data

UI stuff and RGBA textures don't have mipmaps, so it's omitted for them.

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #476 on: October 03, 2018, 09:41:45 PM »
Thanks, Codewalker. You da man!

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #477 on: October 07, 2018, 05:09:14 AM »
The index is a 16-bit integer. The low bit of the next field is a flag that indicates if the defnames entry is a rootname -- a model in a geo file rather than a Group from a geobin.

It seems to be even weirder than that. I finally figured out why the indices seemed to be going pear-shaped on me.

Bindump prints the index as a Uint32. However, making it a Uint16 also didn't work out right.

What I finally figured out is that it works like this:

idx1 = Uint16
idx2 = Uint16
idx1 = idx1 & 0X7F (Mask off low bit of idx1 where idx1 is little-endian)
IndexVal = idx1 + idx2

It looks weird but it indexes to the correct objectlibrary value every time. There must be a reason for doing it this way instead of just making it a Uint32 in the first place, but I'll be hanged if I can imagine what that reason is.

slickriptide

  • Elite Boss
  • *****
  • Posts: 356
Re: Technical side discussion
« Reply #478 on: October 11, 2018, 10:09:16 PM »
Hey, Codewalker - A couple of times in the past, you've mentioned the clientsave ability in Icon without explicitly describing how to use it.

Care to elucidate? Custom map-making aside, it would give me the ability to generate a reference I could use to judge how well my geobin parser is working since, theoretically, my parser should be able to spit out a similar "mymap.txt" file. In fact, I've done that and loaded it up as a demo and in Icon, with mixed results, which either indicates that I need to finish getting all of the object library bins parsed or I've got an error someplace. Either way, it would be useful for me to be able to save out a text copy of the client's scene graph to compare to my parser's version of the same data.

« Last Edit: October 11, 2018, 10:15:21 PM by slickriptide »

Codewalker

  • Hero of the City
  • Titan Network Admin
  • Elite Boss
  • *****
  • Posts: 2,740
  • Moar Dots!
Re: Technical side discussion
« Reply #479 on: October 14, 2018, 03:46:40 AM »
I don't think you can in Icon, at least not without making some code changes and recompiling. Icon steals the coordinate box from the map editor to use as its own coordinate entry UI, and stomps on some of the map editor code in order to do it, so it would probably crash if you tried to enter it in Icon.

When I've done it before, it's been in demo playback mode. The steps go something like this:

  • Acquire client accesslevel 9 or higher (10 is the effective max). I used a forged dev_access.key file to do this that I had lying around from back when the game was live -- one that I was careful not to use while connected to live servers, or at least never got caught using. 8)

    Note to game developers: Don't use symmetric encryption to "protect" clientside features that you don't want players to have access to. The keys can be easily extracted from the code. Use something more like an EC or RSA signature. Still can be bypassed but at least isn't completely trivial.

    Found a copy if you want to try it: https://www.dropbox.com/s/2e3h3pbn89rwivp/dev_access.key?dl=1

    Another way to get accesslevel is by modifying memory with a debugging tool, but you have to find the right offset within the player structure.

  • /can_edit 1 (in demo playback, open the console with tilde and use "can_edit 1" instead)

  • /edit 1

Icon has an /accesslevel command that makes this kind of cheating easy, but you'd need to compile a modified version that doesn't touch the editor code.



I have some ideas for an Icon 2.0 built on top of the Paragon Chat engine that is kind of a COH development swiss army knife. For that I want to try to go a step further and get the actual editor working, but that's purely hypothetical at this point.
« Last Edit: October 14, 2018, 04:33:14 AM by Codewalker »