Jump to content


  • Content Count

  • Joined

  • Last visited

  • Medals

Community Reputation

179 Excellent

1 Follower

About Pennyworth

  • Rank
    Lance Corporal

Profile Information

  • Gender
    Not Telling

Recent Profile Visitors

The recent visitors block is disabled and is not being shown to other users.

  1. Preface I want to start by saying that my intention isn't to make a quick-and-dirty guide to getting clutter working in Buldozer. I think it's important to try and understand how the technology works, so I will explain in probably too much detail how I figured this out. While trying to determine if it was possible to update Buldozer lighting to look similar to the lighting in game, I stumbled upon something rather interesting. I noticed that Buldozer was reading "Arma 3 Steam Installation\dta\bin.pbo", or "P:\bin\config.cpp", if "Arma 3 Steam Installation\dta\bin.pbo" wasn't present. I had known that Buldozer loaded a config from somewhere, but never really looked into it in detail. It came as no surprise that there was an entry for "CfgWorlds >> DefaultWorld" in there, but I couldn't figure out if "DefaultWorld" was the terrain being used by Buldozer, so I ignored that for the time being. What was more interesting was that there were entries for CfgSurfaces and CfgSurfaceCharacters. Well, why is that useful? How CfgSurfaces, CfgSurfaceCharacters and Clutter work If you understand how surfaces and clutter work, then you can skip to the next section. To the best of my knowledge, the full process of how clutter appears on your terrain goes something like this: You define a material for a surface in your layers.cfg (e.g. material = "yourTag_yourMap\data\yourTag_someGrassSurface.rvmat";) Your RVMAT contains two "stages", //yourTag_yourMap\data\yourTag_someGrassSurface.rvmat /* ... stuff ... */ class Stage1 { texture = "yourTag_yourMap\data\yourTag_someGrassSurface_nopx.paa"; /* ... stuff ... */ }; class Stage2 { texture = "yourTag_yourMap\data\yourTag_someGrassSurface_co.paa"; /* .. .stuff ... */ }; When you generate layers in TB (Terrain Builder), it takes your original satellite, mask, and normal (if you are using normal map) images and splits them into "tiles". At this point it reads the RVMATs from your layers.cfg (e.g. yourTag_someGrassSurface.rvmat) and creates one, or more RVMATs for that specific tile (e.g. p_000-000_l00.rvmat). The generated tiles (e.g. p_000-000_l00.rvmat) use your yourTag_someGrassSurface_nopx and yourTag_someGrassSurface_co textures, instead of the original yourTag_someGrassSurface.rvmat. You define properties for that surface in "CfgSurfaces", for example: class CfgSurfaces { class Default; class yourTag_someGrassSurface: Default { files = "yourtag_somegrasssurface_*"; character = "yourTag_someGrassSurface_character"; soundEnviron = "grass"; soundHit = "soft_ground"; impact = "hitGroundSoft"; }; //more surfaces }; The important things to note here are "files" and "character". a) The "files" corresponds to the name of the texture used in your surfaces RVMAT (yourTag_someGrassSurface.rvmat), in this case yourTag_someGrassSurface_co, or yourTag_someGrassSurface_nopx. I couldn't tell you definitively which is used. This is why it's important you tag the name of your textures, if you don't you could easily mess with the vanilla or third party terrains if you are using the same texture or surface names. b) The "character" corresponds to an entry in your CfgSurfaceCharacters. You define properties for that surface in "CfgSurfaceCharacters" class CfgSurfaceCharacters { class yourTag_someGrassSurface_character { probability[] = {0.4, 0.4}; names[] = {"yourTag_GrassGreen", "yourTag_ThistleThornGreen"}; }; //more surface characters }; So now your character is defined, but now the game needs to know which models to actually place on your terrain. The entries from "names[]" point to things defined in "CfgWorlds >> yourTag_yourMap >> clutter". You define the actual clutter models that will be used in "CfgWorlds >> yourTag_yourMap >> clutter". class CfgWorlds { class someBaseTerrain; class yourTag_yourMap: someBaseTerrain { //lots of stuff before this class DefaultClutter; class clutter { class yourTag_GrassGreen: DefaultClutter {/* config entries here for your clutter */}; class yourTag_ThistleThornGreen: DefaultClutter {/* config entries here for your clutter */}; }; }; }; When your terrain is loaded in game, and you go to a specific location, it looks at which of the generated tiles RVMATs (e.g. p_000-000_l00.rvmat) corresponds to the location you're at. Using that, it applies the nopx and co textures for all the surfaces on that tile, and possibly surrounding tiles. Now you might ask, where does the clutter come into this? For each of those surface textures it loads, it looks at the "files" config property for ALL of "CfgSurfaces" for something that matches the pattern of the texture it's searching for. In the case of yourTag_someGrassSurface_co, it matches the surface with the "files" entry of "files = yourtag_somegrasssurface_*", which has a "CfgSurfaces" entry of "yourTag_someGrassSurface". Again, this is why it's important to tag your surfaces or surface texture names. At any given moment, every single terrain you have loaded has all of its CfgSurfaces loaded at the same time, so it's completely plausible surfaces and textures that aren't tagged can conflict. Now that the game knows what surface is being used, it can assign all of that surface's properties to it. For example, if you were to walk on that surface (yourTag_someGrassSurface), you'd get the "grass" sound, if you were to shoot that surface, you'd here the "soft_ground" hit sound and you'd see the "hitGroundSoft" particle effect, and most important for us, the "character", which is "yourTag_someGrassSurface_character". If you get the position of that command with scripting and pass it to the surfaceType command, it should return "#yourTag_someGrassSurface". If it returns "#Default", that likely means it didn't match the texture for that surface with any "files" from the various "CfgSurfaces" entries. Sweet, it found a match for the surface (yourTag_someGrassSurface), and now it knows the character (yourTag_someGrassSurface_character). As you might guess, it then looks at "CfgSurfaceCharacters >> yourTag_someGrassSurface_character" to see what character needs to be used. The "names[]" of the clutter used by "yourTag_someGrassSurface_character" are "yourTag_GrassGreen" and "yourTag_ThistleThornGreen". Similar to "CfgSurfaces", the "CfgSurfaceCharacters" for all terrains are loaded at the same time, so tagging is important. Finally, now that it knows the names of the clutter it's looking for (yourTag_GrassGreen and yourTag_ThistleThornGreen), it looks in "CfgWorlds >> yourTag_yourMap >> clutter" for matches. Now it can display the corresponding clutter models on that surface. From what I can tell, it only looks for the "clutter" entry on the terrain you're currently loaded on, but I'm not 100% sure on that. There you have it, from start to finish how clutter is added to a terrain (I think ). Testing and Experimentation From previous tests, I concluded that the surfaceType command returns "#Default" at a certain position if it didn't match the texture for a given surface with any "files" from the various "CfgSurfaces" entries. With some scripting, I was able to show what surface was at the middle of the screen at that time in Buldozer by adding the following to the initBuldozer.sqf [] spawn { while {true} do { sleep 1; private _pos = screenToWorld [0.5,0.5]; _surface = surfaceType _pos; systemChat format ["Surface: %1, at :%2", _surface, _pos]; }; }; As expected, it returned "#Default" for everywhere I went. Well, that makes sense, it's not finding any "CfgSurfaces" with a matching "files". So I wondered, what if I added my surfaces to the "CfgSurfaces" in "bin\config.cpp"? We already know that it's reading "bin\config.cpp", and "CfgSurfaces" is accessible across all terrains, so that means even if I don't know what "CfgWorlds" Buldozer is loading, I should still see what surfaces are being used. Lo and behold, it worked! With a test terrain, I was able to get it showing the corresponding "CfgSurfaces" entry for the surface that was below the cursor. As shown in the gif below, you can see it prints the name of the surface below the cursor as it moves. Alright, well that's fine and dandy, but we're still missing clutter. We know "CfgSurfaceCharacters" is also accessible no matter what terrain you're using, but that's useless without the clutter from "CfgWorlds" for that terrain. Here is where I got a bit lucky, I just guessed that it's loading "DefaultWorld", and I'll be damned, it is. So after adding some basic clutter to "CfgWorlds >> DefaultWorld >> clutter", I saw this. To confirm that it wasn't just a flook, I tried the same thing with Takistan and this was the result. Success! How-to As a warning, in its current state, this is something I'd only recommend for advanced users. To get it working initially I'd recommend experimenting on a smaller terrain so that you can quickly open and close Buldozer to test. For those not aware a "//" comments out everything on that line, and a "/*...*/" comments out everything between the asterisks, so those were used to provide more context. For the sake of length, I also snipped out parts of configs to allow things to be more readable. Open "P:\bin\config. cpp " Find "class CfgSurfaces", and add the "class CfgSurfaces" for your terrain. In my case, I split the "class CfgSurfaces" from my terrain's original config. So after modifying it, this how it looked: //P:\bin\config.cpp CfgSurfaces { class Default {/* default surface that I didn't touch */}; class Water {/* default surface that I didn't touch */}; #include "\path\to\your\CfgSurfaces.hpp" //could be a different file extension than hpp }; For example, my "CfgSurfaces.hpp" looked like this: //P:\path\to\your\CfgSurfaces.hpp class myTagSurface1: Default {/* various surface properties */}; class myTagSurface2: Default {/* various surface properties */}; //more surfaces, etc Find "class CfgSurfaceCharacters", and add the "CfgSurfaceCharacters" for your terrain. In my case I split the "class CfgSurfacesCharacters" from my terrain's original config. So after modifying it, this how it looked: class CfgSurfaceCharacters { class Empty {/* default empty character that I didn't touch */}; #include "\path\to\your\CfgSurfaceCharacters.hpp" }; For example, my "CfgSurfaceCharacters. hpp " looked like this: //P:\path\to\your\CfgSurfaceCharacters.hpp class myTagCharacter1 { names[] = {"myTag_someClutterName1", "myTag_someClutterName2", "myTag_someClutterName3"}; probability[] = {0.2, 0.2, 0.2}; }; //more surface characters, etc Find "DefaultWorld >> Clutter", and add the clutter from your terrain. In my case I split the "clutter" from my terrain's original config. So after modifying it, this how it looked: class CfgWorlds { /* didn't touch the config entries before this */ class DefaultWorld { /* didn't touch the config entries before this */ class clutter { #include "\path\to\your\clutter.hpp" }; /* didn't touch the config entries after this */ }; }; For example, my "clutter.hpp" looked like this: //P:\path\to\your\clutter.hpp class myTag_someClutterName1: DefaultClutter {/* various surface properties */}; class myTag_someClutterName2: DefaultClutter {/* various surface properties */}; //more clutter definitions, etc Check your Buldozer RPT to determine if "Arma 3 Steam Installation\dta\bin.pbo" is being loaded. You would only see it in the RPT if you removed "-noLogs" from your Buldozer parameters in TB. You'll see it about 40 lines down in the RPT in the "==== Loaded addons ====" section. If you don't see it loading "Arma 3 Steam Installation\dta\bin.pbo" 1) Launch Buldozer and see if your clutter is present. 2) If you do see clutter, celebrate! If you don't, then briefly mourn, check everything is done correctly, and try again. If you see it loading "Arma 3 Steam Installation\dta\bin.pbo", proceed to make a backup of that PBO. It's not the end of the world if you lose it, as you can always verify integrity of the game cache on Steam. Just don't forget to restore the original PBO if you actually want to play A3. Option 1, deleting the PBO: a) Delete "Arma 3 Steam Installation\dta\bin.pbo". If Buldozer doesn't see that PBO then it *should* default to using "P:\bin\config.cpp". b) Launch Buldozer and see if your clutter is present. c) If you do see clutter, cheer! If you don't, take a moment to shed a tear, verify you didn't make a mistake somewhere, and try again. Option 2, replacing the PBO (more tedious): a) Using a PBO packer of some kind (I'd recommend pboProject), pack "P:\bin\config.cpp". b) Copy your newly packed PBO and replace the existing one in "Arma 3 Steam Installation\dta\bin.pbo" c) Launch Buldozer and see if your clutter is present. d) If you do see clutter, scream with joy! If you don't, temporarily weep, make the necessary sacrifice, and try again. Conclusion Thanks for taking the time to read this. Hopefully it wasn't too dry or bloated, and people found it helpful. My goal with explaining some aspects in detail was in hopes that others might be inspired or have ideas on similar aspects. If you believe any of the information is incorrect, or have a better explanation for things, feel free to let me know. And thanks to Lappihuan for letting me bounce random things off him. I haven't had time to try and achieve my initial goal of changing the lighting in "DefaultWorld", but I think this was a good diversion. It seems like there is potential here for meeting that goal, and allowing for more as well.
  2. Pennyworth

    Problem with getting glass to break

    Config and model.cfg look fine, so my guess would be that there is something wrong with your named selections. Does the unbroken window texture disappear if you animate the Glass_1_source in buldozer? If the answer to that question is no, then the problem is with your model.cfg or the P3D itself, as buldozer doesn't look at your config.cpp.
  3. Pennyworth

    Audio Tweaking (dev branch)

    Good work! Always nice to see audio getting some love. Could this also be applied to things like destruction sound effects? An example:
  4. Pretty frustrated with myself for not spotting this during testing, but there is an issue with the furthest distant LOD on 11 objects being a white box/plane. There could be more, but I've already fixed the ones mentioned in this ticket. Here is an example image of the issue: This will be hotfixed, but I'd like to give it another day first to see if there are any other hotfix worthy issues that pop up. Sorry for the inconvenience.
  5. Building class names, paths to models, and positions should be the same. The only thing that should have changed is related to animations. The majority of JBAD buildings were for structures_e, which like Neo stated, are used on Takistan and Zargabad. However, all of the A2 terrains will have received upgraded buildings, in some cases it might only be one or two new buildings, but it's probably best to play it safe and reindex the maps. If needed I could put together a list of specific buildings that were updated, but I don't really have an easy method of telling you what maps use those specific buildings.
  6. It's fixed in the next update, which you can expect soon™. If you're on your death bed and your last dying wish is to have dust effects on the CUP Terrains and Tanoa, then I can give you a small PBO that fixes it.
  7. Pennyworth

    X-Cam-Taunus Version 1.1

    CUP Terrains has many faults, but causing Taunus to miss dust effects is not one of them. From the V2 Taunus config I have, even if you did correctly add "CUP_Worlds_DustEffects" to your requiredAddons, dust effects would not work. This is because the values you use in the "rightDustEffects" and "leftDustEffects" array are incorrect. These should be the names of entries in your CfgSurfaces. For example "xcam_grass_green_co", you have no CfgSurfaces entry to match that, and in addition it has an "_co" suffix. Secondly, the way you guys are defining your dust effects would actually cause dust effects to disappear on all terrains, even Stratis, Altis, and Tanoa. As I mentioned in the ticket linked above, this is only an issue because you can't inherit nested config arrays, so every map author is overwriting everyone else's dust effects when they define them, so it's just a game of whoever's config gets loaded last. Here is a PBO with a config fixing the missing dust effects, as well as including all of the A3 and CUP dust effects. I did this at 2 AM so I could easily missed some Taunus surfaces, but it worked in the quick testing I did. Hopefully this post didn't come across as hostile, I just don't want people to think CUP is breaking people's maps and ignoring the issue.
  8. It's been awhile since we've had an update, so I thought I would let people know that we're still active and working hard towards a release in the upcoming weeks. The changelog is long, but some of the more notable things are improved lighting on European terrains, roads, railways, and more available in the editor, implementation of JBAD directly into CUP, and performance improvements (geometric occluders). If time permits, maybe even some extra sound effects.
  9. I thought I would verify some information I read on the wiki regarding section counts. More specifically, For this test I created two objects, one with 16 proxies of a shelf model in the 1st LOD, ShadowVolume, and Geometry, and the other object had all of the shelves in the "base" object, instead of proxies. Images of the models and the video settings I used can be seen here. I then created numerous duplicates of the object and observed the FPS and draw call count from an Intel debugging tool. Here's a small spreadsheet with some of the data I found while testing. Though the model with proxies did have higher draw calls, the total number is so low in this testing that there was no adverse effect on FPS. With the object without proxies we only see the draw calls go up between the 500-550 range, but we see it go up for the object with proxies first between the 30-40 range. I was initially confused by this, but after some testing I determined that the draw calls went up for the object without proxies exactly on the 513th object, meaning that the first set of 512 objects shared draw calls. Now what about the object with proxies? Well if the draw calls are shared between 512 "instances" of an object, and there are 16 proxies in the object, then that should mean the first 32 objects of that type will share the same draw call (512 / 16 = 32), and the 33rd copy of this object will get a new draw call. I then tested this and did in fact see the draw call count go up every 33 objects. So my findings are that the information on the wiki regarding this is wrong, but I wanted to get opinions on my method of testing and any thoughts before I made any edits. I'll do some more testing with this later for things like weapon accessories and equipment, and post an update if I see anything interesting.
  10. Pennyworth

    RSO Buildings pack

    Your error probably occurs because you're inheriting from House, House_F, and Ruins_F, but you have no entry for your requiredAddons. Likely leading to your config loading before the A3 vanilla configs, and unintentionally messing with base classes. You can fix this error by simply adding: requiredAddons[] = {"A3_Structures_F"}; The fact that it doesn't happen with CUP Terrains loaded is slightly concerning to me, as it could mean that CUP Terrains is altering base classes. Hopefully that's not the case, and it's instead something silly like loading CUP Terrains and your addon leads to a longer startup time during which it loads the vanilla structures config before it's able to load your config. Either way, I'll look into a little further.
  11. Steam workshop should be updated. Previously, there were some requests for torrents as well, so links for those can be found below. CUP Units 1.8.0 CUP Vehicles 1.8.0 CUP Weapons 1.8.0 CUP Vehicles ACE Compat 1.8.0 CUP Weapons ACE Compat 1.8.0
  12. Pennyworth

    Vest Issue

    I'm going to tell you how to metaphorically fish, and then give you a fish. First, I would suggest is using something like Notepad++'s "Find in Files" option, and searching for a related term. For example, I see you are inheriting "Vest_Camo_Base", so I'm going to search for that with Notepad++. Alright cool, it found that 12 times in "a3\characters_f\config.cpp", now if I click one of the highlighted lines it will open that file and take me to that line. So I'll first look at where "Vest_Camo_Base" is defined, I see that in the "ItemInfo" it's inheriting "VestItem", just like you are. However, it defines a hiddenSelection of "camo" here. So then in your config you'll want to define that same hiddenSelection again for, but that hiddenSelection also needs an accompanying texture to go with it, so you'll want to define hiddenSelectionTexture for that vest as well. After you made those changes your "ItemInfo" would look something like this, I've obviously cut it short for the sake of space on this post. class TF2031_OCP_PlateCarrier1_rgr: Vest_Camo_Base { ...some stuff... class ItemInfo: VestItem { uniformModel = "\A3\Characters_F_EPA\BLUFOR\equip_b_vest_kerry"; hiddenSelections[] = {"camo"}; hiddenSelectionsTextures[] = {"\Projects\TF_2031_Mod\addons\TF_2031_Units\data\textures\plate_carriers\TF2031_PC_MCAM_co.paa"}; containerClass = "Supply200"; mass = 1; ...your HitpointsProtectionInfo here... }; };
  13. Pennyworth

    Mounting a mod to p: drive using Arma3P

    If you are using extractPBO try the following from batch file or command line, and you will need to include the letter to the drive: extractPBO "D:\path\to\@IFA" "P:\path\to\where\you\want\it\extracted"
  14. Another image he didn't share here.