Looks like a great addition, I'll install Pluto IW5 to try this out.
I didn't notice any issues or development plan on GitHub. Looking forward to contributing to it.
Looks like a great addition, I'll install Pluto IW5 to try this out.
I didn't notice any issues or development plan on GitHub. Looking forward to contributing to it.
I recall xensik's Plutoscript framework being able to respond to chat message events. For some reason, it doesn't seem to be supported anymore - maybe due to some "memory permission" issues he mentioned after a Pluto IW5 update.
Pluto IW5 is a great idea with an impressive application - the developers certainly did wonders with the anti cheat and networking code. With that in mind, I don't want this thread to sound like a demand, simply an invite to a more open conversation.
I believe the Plutonium modding community understands how hard the challenge to bring proper managed scripting to Pluto IW5 is - it sucks that we can't take advantage of GSC like we can with Pluto T6. As a result, we saw a spike of modders hyped up and developing awesome scripts to Pluto IW5, but lately this productive community is slowly dying.
However, I do not think this challenge by itself is responsible for the modding community shrink but rather the little dialogue between the modding community and the Plutonium IW5 developers.
Little things like explaining what the developers think is going on behind those uncallable functions and weird property accessing. This may be too much, but pre-release progress updates on such matters would go a long way on reminding the modding community that the developer team is actively working on the issue.
Again, this is not a demand but rather a suggestion. Thank you all for the work you've done on this so far.
Yes, they are aware.
I'm not sure if they're working on this right now, but I haven't touched Plutonium IW5 for about three months so I can't tell you what's going on exactlly. homura might be able to answer this in more detail.
To the best of my knowledge, they very nature of ChaiScript makes solving these problems rather difficult, so the staff's current approach to solving this problem is pretty much changing the scripting language. JS and Lua have been the most suggested languages by the community.
All in all, the problem is not trivial and so the fix is going to take a while to be fixed (hopefully) or not be fixed at all.
S3VDITO I second everything S3VITO said. There is no point on trying to make mods to Plutonium IW5 for now because of the current ChaiScript limitations. Once the developers get proper array/object returns working and the issue with entities' properties fixed, there will be a lot of potential for such mod and others.
As of now, we've got to wait.
I assume you asked the original authors for permission to create this bundle, but it would be cool to credit their work in the post.
Nice release.
The current state of Pluto IW5 modding is very different from Pluto T6 and other managed modding environments. Currently, storing player data the way you would store it in those other environments is unstable or non-functional.
ChaScript Player Data Management is a simple library that provides a simple and idiomatic way of storing and managing player data purely in managed code.
There are two classes in the library: PlayerStore
and PlayerData
.
PlayerData
stores data of a single player. Pretty straight forward, right?
Internally it's just a a class that provides safe access to a dictionary.
PlayerStore
indexes all PlayerData
you feed to it. Again, just a simple dictionary access API.
Here.
This topic will teach you to implement this library on your code. If you don't want to follow a step by step guide, you can scroll down to the documentation and figure it out yourself.
Before starting, copy the library code to your .chai
file.
PlayerStore
On the top-level scope of you script, you can create a players
object that will hold all your players' data.
var players = PlayerStore()
When any player connects, we want to register it to our PlayerStore
. First, you need to create a PlayerData
object with that player
and then you can set default data, if you want.
level.onNotify("connected", fun(arguments)
{
// create the `PlayerData`
var data = PlayerData(player);
// set some default data
data.Set("welcomed", false);
data.Set("is_vip", true);
// add it to our `PlayerStore`
players.Add(data);
player.onNotify("spawned_player", fun[player](arguments)
{
welcomePlayer(player);
}
}
PlayerData
inside a functionTo find PlayerData
on any player that exists within our PlayerStore
, you can use the Find
function. If the player
you give exists inside our store, it will return the PlayerData
object on it.
From then on, you can can get specific values of this PlayerData
with the Get
function.
def welcomePlayer(player)
{
var data := players.Find(player);
if(!data.Get("welcomed"))
{
player.iPrintLnBold("Welcome!");
if(data.Get("is_vip"))
{
player.iPrintlnBold("You're VIP. Cool, huh?");
}
data.Set("welcomed", true);
}
}
And that's it.
A lot of things can be implemented to make this library more robust.
The library doesn't handle players disconnecting. In big servers, this may be a problem because the PlayerStore
can get massive. A simple PlayerData.Remove(playerObject)
function would do the trick.
The PlayerStore
is not persistent between games. Using tom's Plutonium Filesystem and a JSON C++ plugin would be a good approach to this problem.
Stores data on a specific player.
PlayerData(player)
- Creates data on a player.entity
(Object): the player entity objectFind(key)
- Finds a data value given a key.key
(string): the key to be foundSet(key, value)
- Sets the value of a key. Creates a new key if the given key is not found.key
(string): the key to be setvalue
(any): the valueExists(key)
- Checks if a key exists.key
(string): the key to be checkedManages all players' PlayerData.
PlayerStore()
- creates an empty PlayerStore
Find(playerObject)
- Finds a PlayerData given the player object.playerObject
(Object)Get(index)
- Gets the player at the given index. This function does not check bounds.Add(playerData)
- Adds a new PlayerData to the store.playerData
(PlayerData): the data to be addedFirst(function)
- Gets the first PlayerData that matches the function.function
(fun): a boolean function that takes a PlayerData.Filter(function)
- Gets all PlayerData that match the function.function
(fun): a boolean function that takes a PlayerData.Empty()
- Returns true if this PlayerStore is empty.Exists(playerObject)
- Returns true if PlayerData of the given player exists, else false.I just wrote a little library to aid with this problem. You can check it here.
As far as I know, some kill streaks aren't supposed to work on Rust due to how MW3 handles entities.
I think the underlying problem with BulletTrace
and obj.setOrigin
is different.
When calling gsc.BulletTrace
, I get an Chai function dispatch exception. From what I've observed, this also happens when you improperly call a function inside a struct. For example:
class MyClass
{
var x;
def SetX(value)
{
this.x = value;
}
def CalculateX()
{
var newX = 2.0;
SetX(newX);
}
}
Can't really test right now, but this gave me a function dispatch exception just like BulletTrace. Changing SetX(newX)
to this.SetX(newX)
fixed it. This may be because ChaiScript get's confused when handling complex function calls because most of it security comes from arity checking (i.e counting if you have the correct number of arguments). In more complex function calls calculating arity is tricky - but that's just a theory.
On the other hand, obj.setOrigin
yields a plain access violation, pointing to some ownership issue rather than a faulty function argument stack. Also, calling setOrigin
on player works, so probably not the same issue as BulletTrace
.
def avFunction(player)
{
var obj = gsc.spawn("script_model", player.getOrigin());
var interval = setInterval(fun[player, obj]()
{
var newPosition = player.getOrigin();
newPosition[2] += 10;
obj.setOrigin(newPosition);
player.setOrigin(newPosition);
}, 1);
}
On private match, this code will make the client crash with an access violation exception (0xC00005). It appears the AV occurs only when handling the obj
entity. I'm not sure if the anticheat would allow me to use CheatEngine to investigate what is on the address associated with the exception, so I'm posting it here.
Edit #1: creating obj
as a global
doesn't help. Also function that only read obj
properties (i.e obj.getOrigin()
) work, but functions that write to them yield an AV.
Maybe Chai threads don't have write permission to some of the game entities?
There are currently two ways of modding Pluto. One is using unmanaged C++ code - that's what you have in Visual Studio. The other, and more limited, is using managed ChaiScript code - that's the one you have in the tutorial post.
To load the code from the tutorial, simply save it as a .chai
file in %localappdata%\Plutonium\storage\iw5\scripts
folder.
Fixed!
Apparently the server is looking for scripts in the game folder (game/storage/iw5/scripts
), not in the Local folder.
When I start my LAN server, most of the times my Chai scripts don't load - the script itself doesn't run in the client neither does the server output "Loading script blabla.chai". I have to restart the map (using map mp_MAPNAME
) several times until it loads.
My scripts are located at %appdata%\Local\Plutonium\storage\iw5\scripts
.
My StartServer.bat
: .\bin\plutonium-bootstrapper-win32.exe iw5mp "C:\Program Files (x86)\Steam\steamapps\common\Call of Duty Modern Warfare 3" +start_map_rotate +name "testing" -dedicated -lan
The server config file is the default one provided.
Any clues?
Yes, he links two great references for ChaiScript itself. I'm trying to find what is exposed to it, which he doesn't mention
Maybe if you know where the MW3-ChaiScript interface is done, I can use the ChaiScript source code as reference.
Hmm, is there any documentation I can read to know the functions and entities exposed to Chai?
Are managed functions/entities acessible in ChaiScript?
By managed functions I mean functions like GSC's getCurrentWeapon
, spawn
waittill
. And by entities I mean those like player
and self
.