ebmar 893 Posted November 26, 2018 (edited) Greetings, fellow Jedi! Hope y'all doing fine. I am here to ask for an assistance: How to place a custom placeable(s) to a [custom] module? Many thanks for considering this! Edited November 26, 2018 by ebmar Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 26, 2018 Like most things in a module, it will need a GIT entry to actually spawn in the level, along with the UTP that defines it. For testing purposes you are probably better to start with spawning it via script so that you can quickly adjust the position as needs be. For this you will typically want to hijack the module's OnEnter script with a new script that spawns the placeable before loading the original OnEnter. Here is an example of one I used for the Nar Shaddaa landing zone module: void main() { if ((GetEnteringObject() == GetFirstPC())) { if( GetObjectByTag( "PLC_301SignPad" ) == OBJECT_INVALID ) { CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301SignPad", Location(Vector(-85.25,19.45,9.66545), 131.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301SignShp", Location(Vector(-55.5,-6.15,9.722), 90.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301DckEnt", Location(Vector(5.7,41.65,9.66551), 180.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301CanEnt", Location(Vector(38.25,0.00,9.66545), 180.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301RefEnt", Location(Vector(0.0,-44.25,10.0), 90.0)); } ExecuteScript("k_301_enter_ORIG", OBJECT_SELF); } } The important difference to note is that scripts specify rotation in degree, but the GIT specifies the bearing of placeables in radians. From memory they also use differing origins, so it can take some trial and error getting it right. As far as actually determining the position values goes, you can either run around in the level in-game and use one of the armband mods that will spit out your current position, or you can load the level up in Max/GMax and derive it that way. 1 Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 26, 2018 2 minutes ago, DarthParametric said: void main() { if ((GetEnteringObject() == GetFirstPC())) { if( GetObjectByTag( "PLC_301SignPad" ) == OBJECT_INVALID ) { CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301SignPad", Location(Vector(-85.25,19.45,9.66545), 131.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301SignShp", Location(Vector(-55.5,-6.15,9.722), 90.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301DckEnt", Location(Vector(5.7,41.65,9.66551), 180.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301CanEnt", Location(Vector(38.25,0.00,9.66545), 180.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_301RefEnt", Location(Vector(0.0,-44.25,10.0), 90.0)); } ExecuteScript("k_301_enter_ORIG", OBJECT_SELF); } } So before going on with the attempt though I have to ask things: Is the "PLC_301" refers to the particular PLC that I want to put into the module? Does all the things you mentioned above [UTP, GIT] are packed inside the particular module? Thanks! Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 26, 2018 In KOTOR Tool, the GIT (dynamic area info) is in the XYZ.rim along with the ARE (static area info) and IFO (module info). A UTP is the GFF template for a placeable, equivalent to a UTC for a creature or UTI for an item. You'll find them in the XYZ_s.rim under Blueprint, Placeables. Regarding the script, yes, PLC_301RefEnt etc are the individual placeable tags (as opposed to the resref - i.e. filename - an important distinction) . Basically what the script is doing is firing when the PC enters the module, checking for the existence of the placeable with the tag PLC_301SignPad. If that placeable exists, it then jumps straight to the ExecuteScript command, which fires the original OnEnter, renamed with the "_ORIG" epithet (this new script is given the original OnEnter name so the module loads it). If the placeable is not found (i.e. the engine returns OBJECT_INVALID) then it will proceed to spawn each of the listed placeables at the specified locations (assuming UTPs exist for them). 1 Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 26, 2018 1 minute ago, DarthParametric said: In KOTOR Tool, the GIT (dynamic area info) is in the XYZ.rim along with the ARE (static area info) and IFO (module info). A UTP is the GFF template for a placeable, equivalent to a UTC for a creature or UTI for an item. You'll find them in the XYZ_s.rim under Blueprint, Placeables. Okay, I have got the particular GIT file [m02ac.git] file and have it opened with GFFEditor. Perhaps the most important thing I have to understand at this point is; where can I get the OnEnter script of the particular module? Apologize for the laborious explanation because I'm zero with scripting. 😂 Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 26, 2018 The module's ARE will specify the OnEnter script (although I think there may be a couple where this isn't the case, stunt modules and the like). You can find the script itself in the XYZ_s.rim under Scripts, Compiled. As the category name suggests, these are compiled scripts - NCS. You don't actually need to alter the OnEnter script itself, so you don't need to decompile it. You just need to extract it and rename it. As far the GIT goes. you'll want to save editing that until last. If you are modifying an existing module, changes will typically be inject into a MOD during installation. Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 26, 2018 (edited) Okay, if the tag of the PLC is: PLC_TSLCpnl, and the coordinate that I want it to be placed is: (179.16, 65.40, 0.00) Did I walk the right path with this? void main() { if ((GetEnteringObject() == GetFirstPC())) { if( GetObjectByTag( "PLC_TSLCpnl" ) == OBJECT_INVALID ) { CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_TSLCpnl", Location(Vector(179.16.25,65.40,0.00), 180.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_TSLCpnlShp", Location(Vector179.16.25,65.40,0.00), 90.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_TSLCpnlDckEnt", Location(Vector(179.16.25,65.40,0.00), 180.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_TSLCpnlCanEnt", Location(Vector(179.16.25,65.40,0.00), 180.0)); CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_TSLCpnlRefEnt", Location(Vector(179.16.25,65.40,0.00), 90.0)); } ExecuteScript("k_PLC_TSLCpnl_enter_ORIG", OBJECT_SELF); } } and should I name the file as k_PLC_TSLCpnl_enter_ORIG.nss [to be later compiled to .ncs]? Edit: I must be breaking the game with those setups lol. 😂 Edited November 26, 2018 by ebmar Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 26, 2018 You only specify the exact placeables you want to spawn. If you just have that one, then your script would be: void main() { if ((GetEnteringObject() == GetFirstPC())) { if( GetObjectByTag( "PLC_TSLCpnl" ) == OBJECT_INVALID ) { CreateObject(OBJECT_TYPE_PLACEABLE, "PLC_TSLCpnl", Location(Vector(179.16,65.40,0.00), 180.0)); } ExecuteScript("k_ptar_02aa_ORIG", OBJECT_SELF); } } Note that the "180.0" is the rotation, so you will need to set that appropriately. I would start with 0.0 (it's a float, so it must always have a decimal) and adjust as needed. Your new script must be the exact name of the original OnEnter script. If you are editing M02AA then it would be k_ptar_02aa_en and the original would need to be renamed something else, remembering that you do not want to exceed 16 characters in a filename. I have provided a suitable example in the script above. Once your new script is compiled, put it, the renamed original OnEnter script, and your UTP in the Override folder and test it in-game. 1 Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 26, 2018 (edited) Finally, after hours [overnight; to be exact lol ] looking back-and-forth between your instructions- @DarthParametric, and this tutorial written by the Legends; I got the PLC spawned at the exact location: Spoiler In the end it was DP's instructions that gets the job pretty much done; but what takes me forever with the attempt was I didn't thought that I still need to do entry with placeables.2da, and create a particular UTP for the PLC [RIP brain]. To place the PLC wasn't too difficult as we can actually get an exact location using "whereami" cheat but, to knowing what-to-do with those assets that is right in the face was the overkill. And I thought at first using script method was to bypass the 255's placeables.2da rows limit lol RIP. Anyway; as the PLC is walk-through-able it seems the work is not finished yet. Is it something to do with the walkmeshes? 🤔 Edited November 26, 2018 by ebmar Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 27, 2018 I assumed you were using an existing placeable, hence why I didn't cover that part. I would advise against adding new placeables to K1 unless absolutely necessary, at least for public releases. As far as collision goes, most placeables already include it. Is that a TSL placeable? Did you recompile the model for K1? You should have got a PWK, which, as the letters suggest, is the Placeable Walkmesh. That needs to go in the Override folder along with the MDL/MDX. 1 Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 27, 2018 50 minutes ago, DarthParametric said: I would advise against adding new placeables to K1 unless absolutely necessary, at least for public releases. More likely; as only with this PLC installed I already have 251 rows used in placeables.2da [not including BoS:SR]. And thanks for the advice! Quote Is that a TSL placeable? Yes, it was originally a placeables [PLC_commPanel] in TSL. Quote You should have got a PWK, which, as the letters suggest, is the Placeable Walkmesh. That needs to go in the Override folder along with the MDL/MDX. Hell- how did I missed that?! Yes, many thanks for the heads-up! I totally forgot about its existence to tell truth [as I rarely used it in the 'Override' folder]. Again, thanks! Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 27, 2018 If you want to add stuff to K1, I would suggest considering adding them directly to the room model where possible. That will require lightmapping the placeable meshes (or at least faking it) and possibly room animation, but it will cause less grief for end-users. Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 27, 2018 (edited) 1 hour ago, DarthParametric said: If you want to add stuff to K1, I would suggest considering adding them directly to the room model where possible. Yup; I believe that's what you do with "Diversified Wounded Republic Soldiers on Taris" as I don't see any sign of placeables.2da or UTP inside the package. 😁 Quote That will require lightmapping the placeable meshes (or at least faking it) and possibly room animation, but it will cause less grief for end-users. We'll see- with my current skill I could hardly see any end-result to that lol. Anyways; out of topic but still talking about the particular placeables: I have just recompile its MDL/MDX along with its PWK and when I test it in-game, I see something odd with the texture [I couldn't generate an actual screenshot as I have deleted the odd model, but I try to illustrate what's happening with the drawed line]: Spoiler When I recompile the binary to ASCII and back to binary again with MDLOps v1.0.0 [couple of times just to make sure that the issue is in the recompiling process], I get a black line that is stretched similar as seen in the screenshot. And then I repeat but this time using MDLedit v1.0.3, I got the proper result at the first try; as there is no black line which make it seems to be a stretched texture. Would you mind explaining what that is? Is that what they called seam? 🤔 Edited November 27, 2018 by ebmar Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 27, 2018 5 minutes ago, ebmar said: I believe that's what you do with "Diversified Wounded Republic Soldiers on Taris" as I don't see any sign of placeables.2da or UTP inside the package. Yes, I changed it when the placeables limit bug came to light after the initial release. 5 minutes ago, ebmar said: Would you mind explaining what that is? Is that what they called seam? Looks to be an issue with the UVs being mangled. You'll need to decompile the affected model and then load it up in Max/GMax and look at the UVs. Or just attach the model and I'll have a look at it. 1 Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 27, 2018 (edited) On 11/27/2018 at 1:40 PM, DarthParametric said: ....attach the model and I'll have a look at it. Sure! Here it is to be inspected: [attachment_removed] And as I do a retest; it is confirmed that the issue only occurred when recompile the model with MDLOps v1.0.0: Spoiler Could very well be with your mangled Taris' arena glass, perhaps? 🤔 Edited January 6, 2019 by ebmar Attachment removed as troubleshooting had officially done Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 27, 2018 Is that the source model? I need the binary model decompiled. There's no issue with that ASCII in Max at any rate. You'd have to ask @bead-v to have a look at the binary model perhaps. 11 minutes ago, ebmar said: Could very well be with your mangled Taris' arena glass, perhaps? No, otherwise the diffuse texture would be mangled. Quote Share this post Link to post Share on other sites
ebmar 893 Posted November 27, 2018 (edited) On 11/27/2018 at 2:26 PM, DarthParametric said: Is that the source model? I need the binary model decompiled. Yeah that was the source model- here it is; the decompiled binary models: [attachment_removed] Quote No, otherwise the diffuse texture would be mangled. Ah I see. 🤔 Edited January 13, 2019 by ebmar Attachment removed as no further troubleshotting required Quote Share this post Link to post Share on other sites
DarthParametric 3,782 Posted November 27, 2018 I don't see any problems with the ASCII. UVs are the same as vanilla and the texture issue doesn't show up in Max. Must be something going on in the binary. Quote Share this post Link to post Share on other sites