Leaderboard
Popular Content
Showing content with the highest reputation on 01/08/25 in all areas
-
3 points
-
This pinned thread's purpose is to collect links to all the discussion threads for new features to be added in 2.13: [2.13] AI Light Estimation Changes Experimental support of Parallax Mapping in 2.13 [2.13] Interaction Groups in Materials: new behavior [2.13] Environment Mapping + Bumpmap Tone mapping Lightgem improvement for leaning Support for GUI-based debrief Slowfall Potion Test r_lockview debug cvar EFX preset spawnarg for location entities Mission overrides for cvars Sound Parameter 0 overrides Inventory Grid Item Sorting [2.13] Main menu Mission name sorting As well as older feature collection threads: [2.12] Feature discussion threads [2.11] Feature discussion threads [2.10] Feature discussion threads2 points
-
Hi folks, and thanks so much to the devs & mappers for such a great game. After playing a bunch over Christmas week after many years gap, I got curious about how it all went together, and decided to learn by picking a challenge - specifically, when I looked at scripting, I wondered how hard it would be to add library calls, for functionality that would never be in core, in a not-completely-hacky-way. Attached is an example of a few rough scripts - one which runs a pluggable webserver, one which logs anything you pick up to a webpage, one which does text-to-speech and has a Phi2 LLM chatbot ("Borland, the angry archery instructor"). The last is gimmicky, and takes 20-90s to generate responses on my i7 CPU while TDM runs, but if you really wanted something like this, you could host it and just do API calls from the process. The Piper text-to-speech is much more potentially useful IMO. Thanks to snatcher whose Forward Lantern and Smart Objects mods helped me pull example scripts together. I had a few other ideas in mind, like custom AI path-finding algorithms that could not be fitted into scripts, math/data algorithms, statistical models, or video generation/processing, etc. but really interested if anyone has ideas for use-cases. TL;DR: the upshot was a proof-of-concept, where PK4s can load new DLLs at runtime, scripts can call them within and across PK4 using "header files", and TDM scripting was patched with some syntax to support discovery and making matching calls, with proper script-compile-time checking. Why? Mostly curiosity, but also because I wanted to see what would happen if scripts could use text-to-speech and dynamically-defined sound shaders. I also could see that simply hard-coding it into a fork would not be very constructive or enlightening, so tried to pick a paradigm that fits (mostly) with what is there. In short, I added a Library idClass (that definitely needs work) that will instantiate a child Library for each PK4-defined external lib, each holding an eventCallbacks function table of callbacks defined in the .so file. This almost follows the idClass::ProcessEventArgsPtr flow normally. As such, the so/DLL extensions mostly behave as sys event calls in scripting. Critically, while I have tried to limit function reference jumps and var copies to almost the same count as the comparable sys event calls, this is not intended for performance critical code - more things like text-to-speech that use third-party libraries and are slow enough to need their own (OS) thread. Why Rust? While I have coded for many years, I am not a gamedev or modder, so I am learning as I go on the subject in general - my assumption was that this is not already a supported approach due to stability and security. It seems clear that you could mod TDM in C++ by loading a DLL alongside and reaching into the vtable, and pulling strings, or do something like https://github.com/dhewm/dhewm3-sdk/ . However, while you can certainly kill a game with a script, it seems harder to compile something that will do bad things with pointers or accidentally shove a gigabyte of data into a string, corrupt disks, run bitcoin miners, etc. and if you want to do this in a modular way to load a bunch of such mods then that doesn't seem so great. So, I thought "what provides a lot of flexibility, but some protection against subtle memory bugs", and decided that a very basic Rust SDK would make it easy to define a library extension as something like: #[therustymod_lib(daemon=true)] mod mod_web_browser { use crate::http::launch; async fn __run() { print!("Launching rocket...\n"); launch().await } fn init_mod_web_browser() -> bool { log::add_to_log("init".to_string(), MODULE_NAME.to_string()).is_ok() } fn register_module(name: *const c_char, author: *const c_char, tags: *const c_char, link: *const c_char, description: *const c_char) -> c_int { ... and then Rust macros can handle mapping return types to ReturnFloat(...) calls, etc. at compile-time rather than having to add layers of function call indirection. Ironically, I did not take it as far as building in the unsafe wrapping/unwrapping of C/C++ types via the macro, so the addon-writer person then has to do write unsafe calls to take *const c_char to string and v.v.. However, once that's done, the events can then call out to methods on a singleton and do actual work in safe Rust. While these functions correspond to dynamically-generated TDM events, I do not let the idClass get explicitly leaked to Rust to avoid overexposing the C++ side, so they are class methods in the vtable only to fool the compiler and not break Callback.cpp. For the examples in Rust, I was moving fast to do a PoC, so they are not idiomatic Rust and there is little error handling, but like a script, when it fails, it fails explicitly, rather than (normally) in subtle user-defined C++ buffer overflow ways. Having an always-running async executor (tokio) lets actual computation get shipped off fast to a real system thread, and the TDM event calls return immediately, with the caller able to poll for results by calling a second Rust TDM event from an idThread. As an example of a (synchronous) Rust call in a script: extern mod_web_browser { void init_mod_web_browser(); boolean do_log_to_web_browser(int module_num, string log_line); int register_module(string name, string author, string tags, string link, string description); void register_page(int module_num, bytes page); void update_status(int module_num, string status_data); } void mod_grab_log_init() { boolean grabbed_check = false; entity grabbed_entity = $null_entity; float web_module_id = mod_web_browser::register_module( "mod_grab_log", "philtweir based on snatcher's work", "Event,Grab", "https://github.com/philtweir/therustymod/", "Logs to web every time the player grabs something." ); On the verifiability point, both as there are transpiled TDM headers and to mandate source code checkability, the SDK is AGPL. What state is it in? The code goes from early-stage but kinda (hopefully) logical - e.g. what's in my TDM fork - through to basic, what's in the SDK - through to rough - what's in the first couple examples - through to hacky - what's in the fun stretch-goal example, with an AI chatbot talking on a dynamically-loaded sound shader. (see below) The important bit is the first, the TDM approach, but I did not see much point in refining it too far without feedback or a proper demonstration of what this could enable. Note that the TDM approach does not assume Rust, I wanted that as a baseline neutral thing - it passes out a short set of allowed callbacks according to a .h file, so language than can produce dynamically-linkable objects should be able to hook in. What functionality would be essential but is missing? support for anything other than Linux x86 (but I use TDM's dlsym wrappers so should not be a huge issue, if the type sizes, etc. match up) ability to conditionally call an external library function (the dependencies can be loaded out of order and used from any script, but now every referenced callback needs to be in place with matching signatures by the time the main load sequence finishes or it will complain) packaging a .so+DLL into the PK4, with verification of source and checksum tidying up the Rust SDK to be less brittle and (optionally) transparently manage pre-Rustified input/output types some way of semantic-versioning the headers and (easily) maintaining backwards compatibility in the external libraries right now, a dedicated .script file has to be written to define the interface for each .so/DLL - this could be dynamic via an autogenerated SDK callback to avoid mistakes maintaining any non-disposable state in the library seems like an inherently bad idea, but perhaps Rust-side Save/Restore hooks any way to pass entities from a script, although I'm skeptical that this is desirable at all One of the most obvious architectural issues is that I added a bytes type (for uncopied char* pointers) in the scripting to be useful - not for the script to interact with directly but so, for instance, a lib can pass back a Decl definition (for example) that can be held in a variable until the script calls a subsequent (sys) event call to parse it straight from memory. That breaks a bunch of assumptions about event arguments, I think, and likely save/restore. Keen for suggestions - making indexed entries in a global event arg pointer lookup table, say, that the script can safely pass about? Adding CreateNewDeclFromMemory to the exposed ABI instead? While I know that there is no network play at the moment, I also saw somebody had experimented and did not want to make that harder, so also conscious that would need thought about. One maybe interesting idea for a two-player stealth mode could be a player-capturable companion to take across the map, like a capture-the-AI-flag, and pluggable libs might help with adding statistical models for logic and behaviour more easily than scripts, so I can see ways dynamic libraries and multiplayer would be complementary if the technical friction could be resolved. Why am I telling anybody? I know this would not remotely be mergeable, and everyone has bigger priorities, but I did wonder if the general direction was sensible. Then I thought, "hey, maybe I can get feedback from the core team if this concept is even desirable and, if so, see how long that journey would be". And here I am. [EDITED: for some reason I said "speech-to-text" instead of "text-to-speech" everywhere the first time, although tbh I thought both would be interesting]1 point
-
1 point
-
Let's wait until jivo is ready to resume his wonderful work. The Visible Player Hands Mod is the best use-case I can think of to get your project started. But we need jivo.1 point
-
Good show @ptw23, welcome! The Visible Player Hands Mod by @jivo could perhaps use some external support1 point
-
1 point
-
1 point
-
1 point
-
The mission count for 2024 is even more impressive when you realize that one of them was @JackFarmer's epic campaign Hidden Hands: Blood & Metal, which was really five missions in one!1 point
-
Thanks for compling the list, GW! 15 years of TDM with 189 missions means almost 13 missions per year. Let's think what it means in a rough comparison: Thief 1 had 13 missions. Thief 2 had 15 missions. Therefore, on average, this community has created a new thief game worth of content every year. For fifteen years! Every year! This is definitely something to be proud of, methinks! Congrats everyone! Thank big thanks for your hard work!1 point
-
I'm back! Happy new years, TDM folks! I brought with me a quick update for my first FM that fixes up a lot of small issues that didn't get caught in beta testing. I didn't exactly expect it to take me nearly 9 months to release a patch, but it's been a wild year to say the least. Teaching, finishing up my Master's of Education, and all manner of other events forced me to drop out of the anniversary FM contest and ate up all my time, but I'm back again in a comfortable position to start catching up on all the new FMs. I may even start work on another spooky project of greater length and difficulty in the coming year. Thanks again for the warm welcome to the community and have a happy new year!1 point
-
My stone-cold heart has been broken many times. Recently again, when I discovered this band from Holland on DLK (German Public Radio). Why isn't it played up and down on the radio? The EP is called “Holy Ground” and contains at least three other remarkable songs in the style of the New Romantics in addition to this track.1 point
-
Almost eight months ago I volunteer to do this: The response has been overwhelmingly non existent. I am surprised mappers aren't interested in enriching their stories through every day objects... Perhaps we are not yet ready for such radical innovations.1 point
-
1 point
-
1 point
-
1 point
-
Hey! How's everyone doing? Found this neat project in development by the dev on twitter, called Gloomwood. I'll let the screenshots speak for themselves: http://gloomwood.com/press/ The dev's twitter: https://twitter.com/Jollyrogers99 . I'm surprised there isn't a topic about it yet here, because he's most definitely part of the thief community! Anyway, I really like it. It's cool to see people embracing dated visuals as if it was by design. It wasn't, we know, but it has its merits besides nostalgia, in my opinion.1 point
-
=================================== i wonder how expensive is it to buy a multitrack isolated instrument recording of a band and how costly is it to obtain a rare demo tape of a band...1 point
-
EDIT - v1.1 can be found a few posts below ------------------------------------------------------------------ Nameless Objects Mod v1.0 Description: this mod adds names to almost all core objects players can grab and hold in their hands. ------------------------------------------------------------------- How to use: As of this moment the Mod only works if you have "Core Essentials", which is included in TDM Modpack v4.0. Make sure to have "Core Essentials" and then download the *.pk4 attached to this post and place it in your TDM folder. I try my best to provide stuff people can experience first hand to form an opinion. I suggest you try "Business as Usual" by Bikerdude since this mission includes quite a few items you can grab right at the beginning. ------------------------------------------------------------------- Technical: The mod consists in a couple of def files and a script. I had to include two defs because otherwise there can be issues related with inheritance. The script does most of the work and it will run in the background as soon as a mission starts. The script runs once but it takes its time (10 to 30 seconds) not to hinder performance. All this is transparent to you. ------------------------------------------------------------------ Future: I wouldn't like this to remain as a mod and I volunteer to add names to all core defs for 2.13. I would, of course, use the translation system so that names can be translated in the future to languages other than English. I can name all core defs in a couple of rainy mornings but the Development Team must guarantee this work won't go to waste. The idea is that we name all core objects today and we let it stay: nothing changes in the source code and nothing gets displayed on screen. We get stuff done in the background and someday perhaps, all or part of it sees the light in some form. ------------------------------------------------------------------ There are quite a few things that must be discussed and agreed before we get started but the first step is: yes or no. People that might be interested in supporting and helping with this initiative: @datiswous, @Geep. Cheers! z_nameless_objects_mod_v1.0.pk41 point