#plugins-dev-chat
1 messages Β· Page 25 of 1
Locker seems to be the normal lockers that spawn loot, at least from how the classes look like
thats basegame
labapi wrapper is PedestalLocker
Painkillers
literally did that api
guh
idk if i merge https://github.com/Misfiy/SecretAPI/pull/44/files
cuz its close to exiled
merge deez
no!
you...
haha gottem
- Custom Networking like mirror to learn how it works
- Waiting for ja** uni review time
smh
help me with custom tiems idk
Why you do that in a first place
which one
you mean have player prefab?
yea
its nicer to have ig
Transform playerEffectsStore = PrefabStore<ReferenceHub>.Prefab.playerEffectsController.effectsGameObject.transform;
Transform playerEffectsManager = PrefabManager.PlayerPrefab.playerEffectsController.effectsGameObject.transform;
Transform playerEffectsBaseGame = NetworkManager.singleton.playerPrefab.GetComponent<PlayerEffectsController>().effectsGameObject.transform.transform;
why
Like whats that for xd
oh thats the custom effect thing
but still
player prefab is used for stuff sometimes
so having it in a more obvious spot than NetworkManager.singleton might help some ppl
like npcs, what im doing and uhh
there was a third use case i forgot
which of these would you prefer tho
Is it possible to block specific keybinds from being used on a Keybind Setting?
want to make it so people can't set the keybinds to their mouse
fun police

just create your own keylogger that interops with SSSS

@icy knoll you..
idk if i like it
but you said smth about wanting this
i wanted it before labapi added their own speaker toy implementation :3
damn
labapi utilities
SSSS wrapper is actually goated
when nw ssss wrapper that isnt terrible
sss should really be reworked imo
saves you an arm and a leg when trying to deal with settings only being visible to certain people and stuff
atleast we now have SSKeybindHintParameter
im sorry hubert, but the way it works serverside is just annoying π
W
public class ExampleKeybindSetting : CustomKeybindSetting
{
/// <summary>
/// Initializes a new instance of the <see cref="ExampleKeybindSetting"/> class.
/// </summary>
public ExampleKeybindSetting()
: base(900, "Example Kill Button", KeyCode.G)
{
}
/// <inheritdoc />
public override CustomHeader Header { get; } = CustomHeader.Examples;
/// <inheritdoc />
protected override CustomSetting CreateDuplicate() => new ExampleKeybindSetting();
/// <inheritdoc />
protected override void HandleSettingUpdate(Player player)
{
player.Kill();
}
}
this is goated
kill keybind 
epic
me when reflection was better than CreateDuplicate method because it's ugly to see blegh
that eh
wont rly work
:c
public SettingThing(int)
now it doesnt work
and breaks
which is why it is how it is
its a duplicate of my private source
i aint dealing w allat for now
did emma infect you with brainrot
what
emma
how is this
modded mc player
everyone knows who modded is
i dont know anything other than the fact they annoying
LMFAO
(but they are also based too so i guess it cancels)
is it just me missing something or does RoundStarting not exist
wtf
tanks
tank it
i just woke up
nop
But you have reccomended keybind option. And if client puts your keybind to.. idk.. capslock
I think thats their problem
no they set it to mouse to make it easier for them to use
can i raise this as a feature request in the labapi issues or will it get declined?
What is it?
whats the use for not having it be easy
it's a cool keybind i setup which does smth the game should do but it's chill
because it means the user can spam so easily, but i want them to spam a button on their keyboard instead
Add cooldown to it
Done
also that
yeah idk how without a dictionary or smth
then do it with dictionary?
There are many ways to do it
ugly solution to me!
depending on how you handle the thingy
Do you have handler for the ability for each player?
well technically with my solution you can just
private DateTime time;
it
or is it all in one
also, sometimes as well people will click so fast that there isnt even enough time to add to the dictionary
you dont need a dictionary i dont think
all solutions are ugly
No thats not how it works
idk, @hearty shard does secretapi make it so the ssss classes are seperated for each person or no?
a new instance is created on receive
Game loop first processes all messages, dispatches then and then in next iteration it proceses the new messages that arrived meanwhile
Not in between
No matter how you do it, you need a way to have a cooldown for each player individually
Dictionary works just fine
private static void OnSettingsUpdated(ReferenceHub hub, ServerSpecificSettingBase settingBase)
{
if (hub.IsHost)
return;
Player player = Player.Get(hub);
CustomSetting? setting = CustomSettings.FirstOrDefault(s => s.Base.SettingId == settingBase.SettingId);
if (setting == null || !setting.CanView(player))
return;
CustomSetting newSettingPlayer = EnsurePlayerSpecificSetting(player, setting);
NetworkWriter entryWriter = new();
NetworkWriter valueWriter = new();
settingBase.SerializeEntry(entryWriter);
settingBase.SerializeValue(valueWriter);
newSettingPlayer.Base.DeserializeEntry(new NetworkReader(entryWriter.buffer));
newSettingPlayer.Base.DeserializeValue(new NetworkReader(valueWriter.buffer));
newSettingPlayer.HandleSettingUpdate(player);
}
new setting is per player
If you have handler object for eeach object then I suggest using either:
StaticUnityMethods.OnUpdate and decerase the timer every time.deltatime
orrr
Use Stopwatch
Thats how its done base game usually
then why is there a Player param added to the recieving setting method? lol
player can be null
this prevents it

public class ExampleKeybindSetting : CustomKeybindSetting
{
private AbilityCooldown cooldown = new();
/// <summary>
/// Initializes a new instance of the <see cref="ExampleKeybindSetting"/> class.
/// </summary>
public ExampleKeybindSetting()
: base(900, "Example Kill Button", KeyCode.G)
{
}
/// <inheritdoc />
public override CustomHeader Header { get; } = CustomHeader.Examples;
/// <inheritdoc />
protected override CustomSetting CreateDuplicate() => new ExampleKeybindSetting();
/// <inheritdoc />
protected override void HandleSettingUpdate(Player player)
{
if (!cooldown.IsReady)
return;
cooldown.Trigger(5);
player.Kill();
}
}
there is a class for the specific setting
should work
ok cool
ill bookmark this
thanks eve
its rly just this
basegame does the same
i believe
its required to have the settings be synced properly
also for TryGetSetting of a player
i could do breaking change to add Owner property
would be nullable tho
idk if thats the way for it
only run the functions that require it whenever owner isnβt null then :3
and make it so owner isnβt nullable lol
Owner has to be nullable π
grr
default base you register
Also people can just bind the keybind on their mouse, bypassing the "no mouse" solution
has to have null owner or Server.Host
null!
how do i impart force on a ragdoll or kill the player so their ragdoll goes flying? preferably in such a way as to avoid being hazardous to other players
I know the amount of damage done with atleast jailbirds will affect the ragdoll velocity
so jailbird damage handler maybe.
but what about direction?
I think it's the direction the attacker is facing
something like this should work
casting nah,
reflection, YEAH
ahh solution
This is a good solution too
but the code using this was creating a ragdoll and not modifying the damage handler from an event
isnt it because field is priv
π
not my code Β―_(γ)_/Β―
Since there will be an attacker to speak of
What is the jailbird death text again?
@hearty shard how would you guys modify a private field? I'm still learning stuff -v-
publicize assembly
its rly easy
and then itll work as if its public
and enable unsafe code in your project properties
ya
so it doesnt throw an error 
<PackageReference Include="BepInEx.AssemblyPublicizer.MSBuild" Version="0.4.2" PrivateAssets="all" />
<Reference Include="Assembly-CSharp" HintPath="$(SL_REFERENCES)\Assembly-CSharp.dll" Publicize="true" />

didnt know this was a thing
crazy
I just used Exileds publicizer Β―_(γ)_/Β―
And would this still work on servers by just uploading the plugin dll? Or would the server have to do additional things on their end?
No modifications needed for the server
You dont need to change the publicized dll on the server
only locally for your programming purposes
sweet
DAVIDDDDDD
hi!
do you know if it worked though
Yep, its part of code for a ragdoll launcher. I've used that line before, I just copied it from a friends code
Is reflection just tedious or is there something else bad about it?
well reflection is costly in runtime performance
other than that nothing truly bad about it
reflection has to look through metadata, etc to search for things
makes sense
i love yellow triangles!!!!
(nothing broken tho lol)
tldr if you can publicize you should
performance my beloved
/// <summary>
/// Patches the <see cref="ServerSpecificSettingsSync.ServerPrevalidateClientResponse"/> to allow our custom settings. This allows us to ignore DefinedSettings nonsense.
/// </summary>
[HarmonyPostfix]
[HarmonyPatch(typeof(ServerSpecificSettingsSync), nameof(ServerSpecificSettingsSync.ServerPrevalidateClientResponse))]
private static void ServerSpecificSettingsSync_ServerPrevalidateClientResponse(SSSClientResponse msg, ref bool __result)
{
if (__result)
return;
__result = _ourSettings.Contains((msg.Id, msg.SettingType));
}

gj
i hate defined settings!i hate defined settings!
/// <summary>
/// Fixes validation for <see cref="CustomSetting"/>.
/// </summary>
[HarmonyPatchCategory(nameof(CustomSetting))]
[HarmonyPatch(typeof(ServerSpecificSettingsSync), nameof(ServerSpecificSettingsSync.ServerPrevalidateClientResponse))]
internal static class SettingsSyncValidateFix
{
#pragma warning disable SA1313
private static void Postfix(SSSClientResponse msg, ref bool __result)
#pragma warning restore SA1313
{
if (__result)
return;
__result = CustomSetting.Get(msg.SettingType, msg.Id) != null;
}
}
mine is that
obviously
xd
Spawn
me when ruei & MER for me π
whyy
i barely touch on
made a plugin for someone
fair enough
decided to try ruei
it works well
but i never tried using it elsewhere
simply because im not making any crazy menus
if i end up doing that, then ill use it
yeah i think we had a plugin doin that
me when
crazy
i thought they added it
im not even using the nuget
i find it easier to download a branch
then reference it how i want
than switching versions n shit
i was only going to cuz of docs
but whats the one for one that returns a value
Func
thanksss
you two would probably be best friends if you lived near one another
how i can remove regeneration from painkiller?
patch it
isn't there an useditem handler for that?
maybe
private static Dictionary<RoleTypeId, Func<List<RoleTypeId>, float>> handlers = new()
{
{ RoleTypeId.Scp3114, roles => roles.IsEmpty() ? 0 : 0.5f },
};
private static bool Prefix(ref RoleTypeId __result)
{
float maxInclusive = 0.0f;
int length = ScpSpawner.SpawnableScps.Length;
for (int index = 0; index < length; ++index)
{
PlayerRoleBase spawnableScp = ScpSpawner.SpawnableScps[index];
if (ScpSpawner.EnqueuedScps.Contains(spawnableScp.RoleTypeId))
{
ScpSpawner._chancesArray[index] = 0.0f;
}
else
{
// consider that it might not be ISpawnableScp
float num = Mathf.Max(
ScpSpawner.SpawnableScps[index] is ISpawnableScp spawnScp
? spawnScp.GetSpawnChance(ScpSpawner.EnqueuedScps)
: handlers.TryGetValue(ScpSpawner.SpawnableScps[index].RoleTypeId, out Func<List<RoleTypeId>, float>? handler)
? handler.Invoke(ScpSpawner.EnqueuedScps) : 0,
0);
maxInclusive += num;
ScpSpawner._chancesArray[index] = num;
}
}
if (maxInclusive == 0.0)
{
__result = ScpSpawner.RandomLeastFrequentScp;
return false;
}
float num1 = Random.Range(0.0f, maxInclusive);
for (int index = 0; index < length; ++index)
{
num1 -= ScpSpawner._chancesArray[index];
if (num1 < 0.0)
{
__result = ScpSpawner.SpawnableScps[index].RoleTypeId;
return false;
}
}
}
me when i
this sucks ass
π
Another day thanking God for not spawning me near Eve
literally the only code i need to modify is
else
{
// consider that it might not be ISpawnableScp
float num = Mathf.Max(
ScpSpawner.SpawnableScps[index] is ISpawnableScp spawnScp
? spawnScp.GetSpawnChance(ScpSpawner.EnqueuedScps)
: Handlers.TryGetValue(ScpSpawner.SpawnableScps[index].RoleTypeId, out Func<List<RoleTypeId>, float>? handler)
? handler.Invoke(ScpSpawner.EnqueuedScps)
: 0,
0);
maxInclusive += num;
ScpSpawner._chancesArray[index] = num;
}
to consider ISpawnableScp can be gone
cuz 3114 doesnt have it
cuz
someone didnt add it
probably beause it doesnt spawn anymore
but yeah i guess thats kinda goofy
tell me what u need
i can make transpiler (trust)
public static RoleTypeId NextScp
{
[OriginalAttributes(MethodAttributes.Private)] get
{
float maxInclusive = 0.0f;
int length = ScpSpawner.SpawnableScps.Length;
for (int index = 0; index < length; ++index)
{
PlayerRoleBase spawnableScp = ScpSpawner.SpawnableScps[index];
if (ScpSpawner.EnqueuedScps.Contains(spawnableScp.RoleTypeId))
{
ScpSpawner._chancesArray[index] = 0.0f;
}
else
{
float num = Mathf.Max((ScpSpawner.SpawnableScps[index] as ISpawnableScp).GetSpawnChance(ScpSpawner.EnqueuedScps), 0.0f);
maxInclusive += num;
ScpSpawner._chancesArray[index] = num;
}
}
if ((double) maxInclusive == 0.0)
return ScpSpawner.RandomLeastFrequentScp;
float num1 = Random.Range(0.0f, maxInclusive);
for (int index = 0; index < length; ++index)
{
num1 -= ScpSpawner._chancesArray[index];
if ((double) num1 < 0.0)
return ScpSpawner.SpawnableScps[index].RoleTypeId;
}
return ScpSpawner.SpawnableScps[length - 1].RoleTypeId;
}
}
this is basegame
im changing the else for the chance getting
you could just replace the castclass code with a method call that returns ISpawnableScp
theres also this
ok actually genius
i didnt think of that
ISpawnableScp isnt guaranteed 
wdym

make one
that's why

damn
public sealed record CustomSpawnableScp(float Chance) : ISpawnableScp
{
public float GetSpawnChance(whatever) => Chance;
}
in the method you do a type check, and a dictionary lookup if the type check fails
why did you actually make it nullable bruh just call the functions when owner isnβt null π
saves the hassle of ?
oh wait it's isinst not castclass
It does???
gg
also gotta love
max i can set it as is 95
skill issue
otherwise cedmod ruins my day
cedmod changed his priority to high instead of medium
π
i need my patches before cedmod does
π
best code ever
Tf is this person's problem
π
i hate them too but i wont go batshit over them on github
Oh nevermind he doesnt actually care
Hes just trolling lol
can u send a link to this discussion
i wanna read the full original post
does label mean the arrow will have custom text underneath?
also, i dont recall whether the arrows are colored or just white
Yeah
They're red
That would be goated
you have feedback?
no
you don't
period
guys I have a question, how do setup the project correctly? The wiki doesn't tell anything about loading the labapi dll with visual studio (as I believe is what I'm supposed to do), and thus the plugin class doesn't exist for me.
?
install either through nuget or just from server files
Download the Northwood.LabAPI NuGet
or that
Right click project and click manage nuget packages
and look up LabAPI
this?
Northwood.LabAPI
got it
-# david
Northwood.LabApi
Ax
thanks guys
Northwood.LabApi
basically what they were commenting is "nooo you can't have feedback!!1!1"
imagine suggesting something to be added that can actually be useful for some people
Custom Scips and monetization are garbage but That doesnt mean we shouldnt add dev tools
All custom SCPs are garbage, terrible. They abuse their custom functions, such as having the appearance of SCP-049-2, but attaching human models, and being able to pick up weapons and shoot. Especially tutorial characters are abused by them for custom SCPs. Players cannot distinguish whether this character with a human model is an enemy or a friend. They even use this function to sell VIPs, widening the gap between ordinary players and VIP players. Now back to your problem, I don't think we can increase it at all
me when player.CustomPlayerInfo = <size=3em>CUSTOM SCP</size>
me when regex?
anyways I think that custom SCP player info distance should be like 1000
just to be fair
079 map getting custom markers would be nice tho
huh
i dont think u can <size> it
idk i didn't pay attention while writing that xd
last time i checked (in 13.x) you could
Would having an ability cooldown of 0.1 disconnect people from the server whilst spamming? lol
loads of my members have been spamming a server specific keybind and i put an ability cooldown to counter it and loads are crashing
errrr
check LA errors
ill have to check logs as console has no errors
I dont think it was ever possible, i tried in 13.x too
when a player action causes any exception, it silently kicks the player
you might need to add some null and index checks somewhere
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at SillySCP.API.Features.StruggleSetting.HandleSettingUpdate (LabApi.Features.Wrappers.Player player) [0x0002d] in <ac6d1520c08d4f2b8a5382060632f1a6>:0
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at SecretAPI.Features.UserSettings.CustomSetting.OnSettingsUpdated (ReferenceHub hub, UserSettings.ServerSpecific.ServerSpecificSettingBase settingBase) [0x000a5] in <f66e80861ab541ef806784a2419e5920>:0
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at (wrapper delegate-invoke) System.Action`2[ReferenceHub,UserSettings.ServerSpecific.ServerSpecificSettingBase].invoke_void_T1_T2(ReferenceHub,UserSettings.ServerSpecific.ServerSpecificSettingBase)
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at UserSettings.ServerSpecific.ServerSpecificSettingsSync.ServerDeserializeClientResponse (ReferenceHub sender, UserSettings.ServerSpecific.ServerSpecificSettingBase setting, Mirror.NetworkReaderPooled reader) [0x00018] in <8db1ca0fe9a6484084cda320b139932c>:0
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at UserSettings.ServerSpecific.ServerSpecificSettingsSync.ServerProcessClientResponseMsg (Mirror.NetworkConnection conn, UserSettings.ServerSpecific.SSSClientResponse msg) [0x00062] in <8db1ca0fe9a6484084cda320b139932c>:0
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at (wrapper delegate-invoke) System.Action`2[Mirror.NetworkConnectionToClient,UserSettings.ServerSpecific.SSSClientResponse].invoke_void_T1_T2(Mirror.NetworkConnectionToClient,UserSettings.ServerSpecific.SSSClientResponse)
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at Mirror.NetworkMessages+<>c__DisplayClass9_0`2[T,C].<WrapHandler>g__Wrapped|0 (C conn, T msg, System.Int32 _) [0x00000] in <1d7cfb83986b400084ab2287d18f3359>:0
[2025-05-20 16:45:32.493 +00:00] [STDOUT] at Mirror.NetworkMessages+<>c__DisplayClass8_0`2[T,C].<WrapHandler>b__0 (Mirror.NetworkConnection conn, Mirror.NetworkReader reader, System.Int32 channelId) [0x0007a] in <1d7cfb83986b400084ab2287d18f3359>:0```
Thoroughly contemplate every dict and list in your plugin
u should embed debug info so it tells you what line
the dict is static
i mean you prolly thought of that
yeah ima do that
how do i do it again in rider π
well i mean contemplate if the slot with the player has any reason to ever point to null
guys it's giving me this error, how can I switch the language version?
add a <LangVersion>13</LangVersion> in a PropertyGroup in the csproj file
ill see if the log helps first
does it matter if I'm on .Net framework v4.8
nope, some C# features are framework-agnostic
you need to have the new .NET SDK installed though
.NET 8 for C# 12, .NET 9 for 13
I do have that
alright then setting the language version should do the trick
net framework 4.8 and C# 9 or above is recommended
does it matter in which propertygroup I put it?
whichever you like
alr thnx
personal preference but i put it somewhere in the first block
Just look for usages of LabAPI's event args
I've seen it but couldn't tell you where
It'll show you
I've seen them multiple times, helps to know what's going on when debugging
find usages of PlayerEvents or ServerEvents or whatever using dnSpy
is there a way of spawning doors with custom buttons? (i want to use KeycardButtons for it)
unfortunately not rip
the buttons are included in their respective door prefab
not separate
How does the client determine which doors should have which buttons? Since the server needs to spawn the door, wouldn't you be able to spawn a door with "pre-determined" buttons and use that as your custom?
those permission thingies are placed in the scene and aren't part of the door prefab
i mean
primitives
why is LabAPI not a dependency?
I see that yet another rational solution was implemented here

lmao
LabAPI is a game assembly
in SCPSL_Data/Managed
dependencies would be ones that you copy to the labapi dependencies directory
Why do you need it like that?
The doors spawn with the buttons already there is what I mean.
but yeah its apart of the game files
You cant change them
i need the assembly for getting events
ig ill just use GetCallingAssembly
if that will work
typeof(PluginLoader).Assembly
fair enough
also, what would be your use-case of finding events from the LabAPI assembly?
register all to a debug method
maybe idk
hmm
a simpler scripting language for SL
connecting events to a script requires reflection from my assessment
i see
Could also just postfix them
wdym by that
to do all you still need reflection
does OnServerRoundStarting get executed before or after the players recieve their roles?
before
its when round tries to start
and Started prob after right?
RoundStarted is also before roles are received
Patch the functions that fire the event
ing is before something, ed is after
yeah
roles being given are done on the RoundStarted event (so itll be slightly after)
so i could get the roles from the player when the RoundStarted event gets executed?
no
i mean that roles are given slightly after round start
because it uses round start event to trigger role give
oh.
timing.calldelayed(0, yourfunchere) in roundstart event will work
run it next frame
isnt there one for next frame
idk you check
Yes
im pretty sure no
Atleast for coroutines
yield return Timing.WaitForOneFrame;
yeah coroutines only tho
if i knew how to write source generators i would do that
but yeah reflection is the easiest for this
dont learn it bro
trust me
(i made one and it works perfectly)
but its tedious
they very much are
i wanna obsolete my library that i took years to make xd
okay not really obsolete it but
source-generated commands
:3
i already got it to connect to non argumented events
i hate the boilerplate of ICommand
true...
i need to get the event name itself when its executed somehow
maybe i should try making a generator for it
probably stacktrace
idk what the specifics would be tho
you could use the event's type and remove "Args"
also, there are methods in the PlayerEvents, ServerEvents classes and such which contain the methods that invoke the events
stacktrace probably easiest
just use a different delegate for events without arguments
yeah thats what im doing
why though
you can use the event name
instead of the type
#1373707166988505228 took 3+ years cuz i love procrastinating
new StackFrame(2).GetMethod().Name.Substring("on".Length)
works fine
idk about the performance tho
when you're iterating through the events you can just capture the event's name
how exactly iterating?
do you manually declare all events?
nope
i get all events using reflection into a list of EventInfo, once i want to connect e.g. WaitingForPlayers, i just find it, get the subscribe method and generic type of that method
if generic is null, its non argumented
then i just use that subscribe method with the required delegate
the problem is when that method is called, i know that some event is attached to that method
i dont have a way to mark an event when its invoked
then in the delegate you might as well just use the name of the event info
but it must match the subscribe method
this should work am i right?
and you just provide the method itself
can you show your code?
idk how youd the name of that event there
i'm interested in the loop
loop to get the available events?
ye
how do you go through them
well the point is that i connect only to the events i need
right
or rather, the user needs
you null out the first argument here
why not pass it the event name and add a parameter to your handler method
oh wait
you can just create a LabEventHandler at runtime
(the non-generic one)
okay maybe the stacktrace thing is easier
how would I get the room a generator is active in after the ActivatedGenerator event fires?
ev.Generator.Room?
lol
@hearty shard why did you do Get(Type type, int id) and not Get<T>(int id) for CustomSetting?
wher
oh that one
CustomSetting.Get
LOL
i use it internally
<T> doesnt work for my use
then have 2 methods smh
then pr it
wtf do u need it for π
im making a patch which requires me to modify a property inside of the setting

im ngl i forgot to commit some things back when i made them π
like GetPlayerSetting
π
should I drag plugins to LabApi/plugins or LabApi/plugins/global?
make pr to the branch w it then
/global
Easier to manange
thnx
@hearty shard https://github.com/Misfiy/SecretAPI/pull/48
@icy knoll can see is checked before a new instance is created for a specific player
yeah thought so tbh
also just Get(typeof(T), id) as T
where can I find a list of all the methods and events?
on the github repo
where T : CustomSetting => CustomSettings.FirstOrDefault(s => s.Base.SettingId == id && s.GetType() == typeof(T) && s.Owner == player) as T;
btw
i think theres
is that not what my code is?
an easier way
public static IReadOnlyDictionary<Player, List<CustomSetting>> PlayerSettings => ReceivedPlayerSettings;
that gets the settings a player has
so PlayerSettings.TryGetValue(player, out List<>) ? list.FirstOrDefault() : null
your choice
itd make more sense if i reworked it so CanView would use Owner
but then it creates one for ppl without perms
which one
or can you not make static overrides
CanView
u cant
damn
i likely wont merge the owner property
yea
dev or master?
dev
is there any good introduction for labapi, the github wiki lacks and seems outdated?
edited the pr branch and fixed the code
build failed

me or us as a whole?
Whole
SpeakerToy::Play(AudioMessage)
SpeakerToy::Play(VoiceMessage) << also for this one make it so you can actually use the raw data though so that a voice message doesn't need to be made if you just have the data and stuff
This was done to prevent allocation as previously it was params method
microoptimalizations yea
Are there any events/possibilities related to getting the score of the snake minigame?
oh yeah we need this
also this too pls tyvm https://github.com/northwood-studios/LabAPI/issues/127
I just want to give players a flashlight when hitting 80 points :D
Isn't snake pretty much all client side?
the server recieves and sends data
I don't know, but I know that it is at least somehow broadcasted to the other clients, since you can watch the other players playing it in spectator and when looking over their shoulders
This micro-optimization isn't worth making the code unreadable...
so the server has to have at least some kind of information.
quick question. how can i "generate" and load configs from another folder in the plugin config folder via LoadConfigs() ? or is there any way?
I wouldnt call that unreadable
Okay, let's call it shit code
Idk, it's a weird decision to do it that way
method for sending a message on adminchat :3
I think you can do that with remote admin but the less remote admin executed from code the better
is there an scp 127 wrapper yet
it's just this
I'll check something real quick. Give me a sec king π
Ok so
Unless I'm stupid, there are no micro hid events
Yeah there arent
Things like Charging, Shooting, EnergyModified (or smth)
I would also like to see CustomHandlersManager.CheckEvent() as public method
because i have implemented CustomEventHandler with additional events
and i use that method for registering events
off topic but david do you know how I can check when a gun is racked (most specifically, when the shotgun is pumped)?
Wdym?
is there an enum firearmstate or something similar who i can watch
Like how can i detect when a shotgun is pumped (and therefore cocked)
π
Also, has anyone noticed a small problem with SpeakerToys? I have a lot of speakers and queue audio to them in a loop at the same time. In-game however, there seems to be a bit of desync (Unless I move away, since loaded speakers work fine apparently).
And loaded speakers aren't always in sync, just usually
If you want them in sync they have to share the same controller id
is that the case
Don't have any issues with multiple speakers keeping audio in sync here
^
No, it's just that they'll play the exact same audio if they have the same id
Id is just where to send the audio yea
Which is big π§ moment from NW
It works so well
You might have to manually encode and transmit audio data through AudioMessage, unsure if the game handles that otherwise for speakers having the same id?
Did that here, works with zero issues
Yes
and the parameter delays the pump by 0.5 seconds
Its for single shot and double shot pumps
as double shot pumps have bigger delay
new pipes room is listed as "unnamed"
Unnamed refers to generic hallways and stuff
Guess the new rooms don't have a unique name yet
its the only unnamed room a gen can spawn in afaik
shouldnt be
Waterfall & pipe rooms have no name
is there a way to disable the snake game on the chaos card?
wayyy too many people just camping and stalling to play some random snake game
@soft depot waiter waiter
one SN api please!
me when SNAPI mentioned
lmao
I made EXILED plugin exactly for this!
if you're in the EXILED discord, just look up SNAPI in TinybrainSanctum
feel free to port it :P
i mean ill take code and port it
how hard would that be scale 1-10
ill look it up ther
99% changing references and enablind code
lemme check it's transpiler for EXILED code
it's all using Call so you'll get errors for stuff needing to be changed
I'd do it, but I feel like I'd get the itch to make it #if #else based and uhh.... that sounds hellish
is it me or are voice messages quieter in the 14.1?
there's still some reverb though when you destroy the object making the audio tho lol
wait it's actually just far away stuff has hella reverb
that's kinda sick
gen can spawn in waterfall?
ive literally never seen that happen with like 230 hours ingame π
No just saying it has no name
It probably should
both doesn't work
no red underline text either way
are you sure player velocity is not zero?
negative time left
ez
to clarify, it prevents the damage handler from firing at all
anything in localadmin logs
where do i find that? in the scp secret laboratory under .config?
SCP Secret Laboratory\LocalAdminLogs
NRE
[2025-05-20 21:30:38.982 -05:00] [STDOUT] at CompoundV24.Powers.Superpowers.RobinKillComponent+<>c__DisplayClass10_0.<OnTriggerEnter>b__0 () [0x00045] in <9f21b4d243a544eb96e9d26da3a0b41a>:0
[2025-05-20 21:30:38.982 -05:00] [STDOUT] at MEC.Timing+<_DelayedCall>d__310.MoveNext () [0x00056] in <857a4408504f4deea6b81470f00f71dd>:0
[2025-05-20 21:30:38.982 -05:00] [STDOUT] at MEC.Timing.Update () [0x0043c] in <857a4408504f4deea6b81470f00f71dd>:0```
is CompoundV24.Powers.Superpowers.RobinKillComponent the enclosing namespace for this?
RobinKillComponent is the mono behavior that holds this code
do you have the current code for that
i can send the entire thing
it had minimum changes from an hour ago
public class RobinKillComponent : MonoBehaviour
{
/// <summary>
/// Gets or sets the <see cref="ControllableSuperspeed"/> instance to use.
/// </summary>
public ControllableSuperspeed SuperspeedInstance { get; set; }
public Player Player { get; set; }
internal void Init()
{
BoxCollider trigger = gameObject.GetComponent<BoxCollider>();
trigger.isTrigger = true;
Log.Debug($"initialized robinkillcomponent {trigger is null} && {trigger.isTrigger}");
}
private void OnDestroyed()
{
if (gameObject.TryGetComponent(out BoxCollider trigger))
{
Destroy(trigger);
}
}
private void OnTriggerEnter(Collider other)
{
Player victim = Player.Get(other);
if (victim is null || victim == Player || victim.IsGodModeEnabled || !SuperspeedInstance.PlayerHasPowerEnabled(Player) || Player.Velocity == Vector3.zero)
{
// Log.Debug($"Failed checks velocity: {Player.Velocity == Vector3.zero} player speed: {!SuperspeedInstance.PlayerHasSpeedEnabled(Player)}");
return;
}
Player.ShowHitMarker();
SoundHelper.PlaySound(victim.Position, "gore");
Timing.CallDelayed(0.01f, () =>
{
var h = new CustomReasonDamageHandler("Liquification suggests that subject was struck by high speed object.", 150);
// typeof(StandardDamageHandler).GetField("StartVelocity").SetValue(h, Player.Velocity * 10);
// h.StartVelocity = Player.Transform.forward * 50;
victim.ReferenceHub.playerStats.DealDamage(h);
});
/*Timing.CallDelayed(0.01f, () =>
{
victim.Hurt(150);
});*/
}
}```
not sure where the NRE came from
if i embed debug info will the local admin tell me the exact line it originates from
it might, although sometimes that doest work
also Player is null should prevent NREs originating from non existent players right
otherwise i may have just picked out a useless log
im pretty sure i know the exact line anyways, when i comment out some code and it starts working thats a good sign its the one...
i just dont know why it wont let me modify that field
hmm?
in your example its commented out
@unique crane why scps cant use keycards?
are you asking why its coded like that or what code blocks scps from using them?
both
it would be great if it is possible to allow scps using keycards
you are unlikely to get an answer for the first, since that was likely implemented by someone else
I want to modify the firing behavior of a weapon, for example making the ak shoot particle disruptor lazers, where would I start with that?
yeah, but both commented out codes cause nre
sorry i meant to clarify that at that time that code was not commented out
they should effectively be the same anyway
well both use Player which i dont see set anywhere
Player is set externally before RobinKillComponent is initialized
and again if i comment it out it works fine
also im not sure which code your referring too here, theres multiple part commented out
Sorry
In OnTriggerEnter
under the Timing.CallDelayed
Theres two codes commented out
I tried both but not at the same time
just
// typeof(StandardDamageHandler).GetField("StartVelocity").SetValue(h, Player.Velocity * 10);
// h.StartVelocity = Player.Transform.forward * 50;
and nothing else yeah
yep
they should do the same thing but actually cause issues
ok thats much clearer
Use BindingFlags
Sorry!
NonPublic and Instance
But why doesnt the publicized assembly allow me to set it anyway
thats your answer
That's uh
I'll try it
I didnt know the binding flags could be so important considering theres only one field named that.
Unless it's a readonly field, just set it directly
Also, if you publicize the assembly, that's for development only
Since you don't change it in the server's assemblies, the field is still private
does that mean the server cant handle it
i assumed that since i publicized it it just gave me access i wouldnt otherwise have
So I will consider using the binding flags, thank you
So when you publicize the assembly, you change the visibility for development. However, in the server assembly, the field is still private or protected. Therefore, using reflection with no binding flags. Will look for public fields, so you can't find them if you were to change the server. Assembly to make that field public. That and you could use reflection, but at that point you might as well just assign it with direct access.
Don't change the assembly to a publicized in the server , though because it will just not work
question how can i "create" an folder in the config folder of my plugin for extra configs?
anyone got an small example?
plugin.GetConfigDirectory().CreateSubdirectory()
how i can get room / roomType from BreakableWindow?
k thx
is that possible to change this base answer? Like i want to change color and other
Question to NW are data stores persisting when a player leaves or round restarts normal?
The amount of bugs I've just linked to this is staggering, writing my own logic to prevent that but the current logic seems a bit odd
does permissions always doing icomsender to player not cause issues
aka some cases not being handled properly
haven't done sl in a bit just wondering cause am updating something
someone know?
.Room?
position.TryGetRoom
how i can get room type or something?
You have that as a property of the Room
no
name
why enum named as name
why not type
um
just do if (position.TryGetRoom(out var room) && room.RoomName == RoomName.Whatever)
why didn't you also add [RoomNameEnum(RoomName.Type)] or smth smh
i tried to mirror the RoomName enums as much as possible

