#plugins-dev-chat
1 messages · Page 17 of 1
bingo
What do you mean?
pre: spawn players that need spawning, setup things for that snapshot
update: move players
post: do stuff after executing the snapshot, like idk despawning something, player hp etc
good luck!
Thanks
This is all very interesting, hopefully wont be a pain in the ass to figure out
You'll definitely bump into edge cases or special setups for certain entities
but I don't see why it wouldn't be feasible
I could create snapshot sets with record and playback functionality for each entity in SL right
I don't think I'll write this for LabAPI unfortunately because I'm more familiar with the Exiled wrappers and I don't want to dive too deep into unfamiliar territory.
You'd probably write different snapshot handlers for different entity types
I'd write it "event" based
Yea that
Pre: SpawnPlayerEvent(Name: SomePlayer, Id: SomeId), Update: MoveEntity(Type: Player, Entity: SomeId, Eventdata), Post: UpdatePlayerData(Id: SomeId, Data: {HP: Value, Role: SomeRole})
SpawnItem etc etc
Basically create as many events as you'd need to be able to replay a round
Is this an example for a spawn player snapshot?
When I say snapshot I mean a capture of everything that happened between last captured frame and current captured frame
Easiest would be to capture at server tickrate
If between the last captured frame and current captured frame a door opened/closed, record that
record the new state of players (position, rotation, hp, role, etc)
record items spawning, despawning
so on and so on
okay, I think I see, so the pre- in this case would be the player spawning if he didnt already exist, move entity being an update to transform if his data changed, and post being the player data changing
yep
hmm technically "update" wouldn't exist in the snapshot data
it'd be the steps you would take when replaying a recording
I don't even think you'd need pre/post in that case. It'd be like "pre" to setup stuff needed for this frame (spawning/despawning) and then comparing the data from the previous captured snapshot to the current snapshot to determine changes/interpolate
Okay, so an event would have the state of the relevant object saved, and when reading it runs the update code
You'd look for the entities in the current snapshot inside the previous one, and if they exist you interpolate to the current state from the previous one
yeah
Events for entity spawning/despawning and the rest is just a dump of the recorded state of all entities
That'll probably work fine, you can despawn entities in the next capture snapshot's setup phase
you'll have to think up a clever way to detect stuff like shooting, throwing items, picking up etc
that's probably gonna be one of the hardest parts
wdym by this, could you rephrase?
Basically your list of changes are determined on a per-entity basis.
if an entity just got spawned this snapshot, skip them.
If they exist in the previous snapshot, you interpolate between the state of the previous one to the state of the new snapshot.
As such, you only need to record the state of the entities you wish to replay (position, rotation, hp, etc)
My plan was to save the state of players, and then save any eventhandlers they trigger that tick, maybe find a way to detect the eventhandler last so i can see if nothing prevented it from running
I wouldn't try to record event handlers
In the end those event handlers are just going to change entity states
Which you're already recording
certain things I dont think can be saved as states, like firing a gun or using an item/interactible
okay, so if player respawns on tick 1, then i dont record him until tick 2?
You'll want to record them but you won't be able to interpolate
You'll spawn them, set their values
yeah that makes sense
Technically you can save that in the state
it's an event that happened in the snapshot
You could save their equipped gun, and the amount of bullets fired with that gun
Then when you interpolate you know how many shots to simulate
sounds about right
and I can simulate gunshots by telling the dummy to pull the trigger on a gun theyre holding, is that right? I probably have to come up with a special protocol for playbacking certain events anyways
Yep
You're gonna be recording the player's items in the snapshots anyway
So for guns you'll know how much ammo they have in the mag
You can set that, then simulate a shot when playing back
and for safety I should give the players godmode so they dont accidentally kill each other slightly earlier or later than theyre suoposed to right
I would make an abstract SnapshotHandler<T> class, and you make specializations for every type of entity you want to record. Could have a RecordData method, PlaybackData(Snapshot previous, Snapshot current)
Smart idea yeah
Then you can just simulate damage by changing their HP since it'll change in the next snapshot anyway
Ah yeah I was about to ask if it should be abstract
you definitely should
Will make maintaining and adding more supported entities a lot easier
So I would have like a PlayerSnapshotHandler : SnapshotHandler ?
probably something like PlayerSnapshotHandler : SnapshotHandler<Player>
bonus with this is you can make your replay plugin support other plugins
if you make it public
They just have to implement their own handlers
yeah i wanted to add a system to support other snapshots
ay, makes it easy that way
Should I compartmentalize snapshots, so have a different one for players base stats like hp, transform, role, and another one for item states within that player and etc
You have been a big help already
I have done a total of zero projects of this kind of scale
Oh I just remembered, it's not a bad idea it's just very low level and the work to do that from a plugin would be kinda huge.
However: it is how Unreal Engine's replay system works. It captures net events and replays them IIRC.
Thats essentially fully lying to the client
yeah it would require patching to work, last time i thought about it, my initial goal was to make it work well with other plugins
it would be nice as hell but also hard to make and maintain
on Unreal though you just download the recording and replay it locally
You don't have a server sending you as the data as a client
You're just replaying what the server did
matinance should be better i would hope as new stuff should "just work"
obv recordings would break between updates
You can definitely write your own binary format to handle updates
It's a lot of work ofc but Unreal has versioned saves for stuff like that
You'll need to like, save the version of the replay within it and "port" the data to the latest format before replaying it
i dont think mirror is so forgiving, if theres new data required in a packet it expects it, or the client soft locks immediately
oh right yeah if you go the net packet route
I meant the simpler state capturing on the server
ahh
i don't think Unreal handles that either for its demo net driver
I thought I could use NPC motor and mouselook but it might desync
I wonder if players being constantly teleported would be able to play walking animations and footsteps
I'd just interpolate towards the captured position/rotation
dunno about sounds though
sounds like footsteps are produced client side from player movement so should work without any extra code
think i can interpolate by using the dummy manipulator funcs
nvm Unreal does support different versions with its demo net driver
yeah, thats handled client
it just records the version of the recording and sets it when (de)serializing data
just gotta make sure you handle that in your game code if you have custom serialization
smart
This one is interesting, what if you just write the network messages into the binary stream along with timestamps?
I think the biggest concern would be netIDs but other than that it sounds simple in theory
You probably need to write the correct type too
So you know what to deser
I mean if you sniff the outgoing packets then you'd know exactly what type of message it is
It would work but it'd be a lot more work than just capturing entity states into snapshots directly and replaying them, because you're doing it from a plugin not with low level access
It's how Unreal does it and it has a custom net driver class (handles processing packets) just for it, directly in the engine
Not sure but it might be more work to set up the custom types to capture snapshots, you'd have to take care of roles' stuff, too
Replaying "raw" network messages would cover everything
Depends on how knowledgeable you are on that kind of thing
If you don't know how the net side works you'll probably spend more time trying to understand and learn it
compared to the other approach which is a little simpler to wrap your head around
Eh, really depends on the person who writing it
Let's make both implementations and see how many things do we break 
Million
Labillion
Grenade calculation would be that
Uh oh
If you managed to replay the net packets deterministically and properly, yeah you'll probably end up with a better result
But the other solution is probably going to look fine too with some tinkering
And it's certainly less error-prone if implemented right
The snapshot and replay one
The downside is that it'd be hard to replay demos of other versions with the net stuff
True
Ye no shit
It's feasible but like, from a plugin ehhhhhhh
In r6s it is exact same
you'll bash your head in
it's the simpler option 
Unreal supports it but only if you handle it in your game and well, nobody does that
You can't really upgrade or downgrade demos
You can but it's assuming you don't remove stuff from the game
and well, don't change behaviour either
which atp yeah nah
If you rewrite fully some things will
dunno why Unreal supports it tbh
I can't think of any game that implemented demos w/ versioning support
all of them just tell you to eat dirt if you want to watch a replay from an older version
Challenge: write custom network message serializers and deserializers with versioning and make deserialization backwards-compatible 
You can just ultimately write a version in header or smth and show error when try to replay
Hell nah

doesn't matter if you support different versions of net messages
the issue is if the functions those net messages call changed between versions, you'll end up with different results
best case scenario your players are now stuck walking in walls or something, or not doing the actions they should be doing
worst case scenario you just crash
That's why nobody doing it really
oh, reminds me
@teal junco you'll need to save the seed of the map in your replay data
ViaVersion but for SL
since you'll want the exact same map
Ofc
Would be funny going tru walls
You probably wouldnt
Assuming the dummy colliders will stop you from doing that
Idk
Would be funny though
Not if you give them noclip
would be the least of your problems if the seed is incorrect due to the relative positioning system people will just teleport between random rooms when they walk between them
Lmao
Relative positioning system?
Hold up
I'm in bed cant turn on the sound, can you give me a tldr?
I'll watch it fully tomorrow tho ty
Okay I think I got the gist of it
Now the real question: why though
Like why is it relative to a room and not just world coordinates
did you get to check it out?
main reason was to support elevators as elevators do move away and into position, second was the data reduction uses 7 bytes instead of 12 if you use a Vector3 instead
the reason for moving elevators i think was to make effects where you can see players through wall work with them i.e. you dont just see the players disapear when the elevator teleports them
I'd get having based movement for elevators but don't really get why the bandwidth reduction was needed that bad for the rest
bandwidth was a nice side effect i think and wasnt the main reason
ermm what the sigma
Relative positioning uses less than 60% bandwidth compared to floats
So it's a significant improvement for larger servers
im banning myself to test
I don't think it would matter tbh considering the game and the player counts you target
Did you register the event handler?
It also includes pickups
yeah, playerleft and playerjoin works fine
Unreal uses double precision floats for everything nowadays and it's not that bad bandwidth wise. Could just strip down the precision if required heh
I think SL's biggest issue is just processing for large player counts
Dies pretty fast
true
That's sort of what relative positioning does
3*float -> 3*short+byte
Players falling out of the map moment
Oh yeah it'd do that but ehhhh in all honesty does seem like it adds a lot of complexity for rather small benefits/results
Could just do parent-based relative movement in some scenarios, like elevators (p much the only scenario in SL)
And who did you test it on
new RelativePosition(original).Position
Easy touse
is this in offline mode?
Hey if it's all done and working nowadays that's cool, mostly meant when it was originally thought of and implemented heh
Moving platforms when
yeah setting the parent and sending local positions could of worked too
Wdym
Idk why moving platforms made me think of that
Being able to see yourself in the MTF heli
me
Or driving as CI
nop
The nanoseconds penalties caused by unity transform.SetParent calls (more efficient than TransformPoint every frame)
It's how
does it and atp Epic should pay me to be a shill
. If you're on a moving base it just networks the base and relative position to it.
Ohhh
That would be cool indeed
I guess you could use the ensnared effect and 0 gravity and position overrides
Doubt it'd look good at all unless NW did it themselves
Tyty I'll look into it
@worthy rune@unique crane it works on other people, thanks though 
Thats truly interesting
yeah it's not very smooth but i got it to work for CI
EPILEPSY WARNING
Lmao
release it
i wanna get ntf working too, for some reason the offset is improperly set on the server (or i'm using the wrong transform)
just think, if CI car and NTF helicopter were NI's, you could parent players to them 
if only
does anyone know how to reset someone's snake game score to 0?
i know you can send data for snake over, i just dont know about how to do it and how to reset the score
just to tip off those people who just camp spawn 😭
Use the reset message type I guess
In the new beta, does Specialist spawn with an E11 now?
did they change that or am I tripping and is a plugin changing this
always been like that
Specialist and Sergeant are the same really
Specialist is just given when you escape thats the only difference
i think ?
Yea only difference . Just an escaped scientist
If only there was a plugin that gave specialists extra loot as a reward for escaping 
But they have a cooler role colour
oh fr? I thought vector spawns were specialists not privates; for some reason my dumbass thought privates didn't spawn naturally anymore
anyways
@unique crane if there would be another round of events add microhid & jailbird ones
Yea detained Class-D escape as privates but privates also spawn naturally
Any way to get the client-logs? I'm trying to find the cause of a friend's crash
log,bat
There's a batch file in the game's directory that'll show you the logs
What slejm said
because their game keeps crashing after verifying
Are you trying to send them an hint while they are joining the Server?
Don't think so
how would one set door state?
ok, i was using this before but since its in onplayerinteractingdoor it doesnt do the animation so i didnt notice it
you can also trigger it with doorevents using the door's network target state
though door.IsOpen is easier to use
let players VC in this state and it will be peak
Can I begin a LabAPI project by just referencing everything in the Server dlls?
what who does switch on a boolean
could be decompiler
unless thats not decompiled
snake players hate this simple trick
[HarmonyPatch(typeof(ChaosKeycardItem), nameof(ChaosKeycardItem.ServerSendMessage))]
internal static class SnakePatch
{
private static void Postfix(ChaosKeycardItem __instance, SnakeNetworkMessage msg)
{
if (!PluginEntryPoint.Instance.Config.EnableSnakeExplosion)
return;
if (!msg.Flags.HasFlag(SnakeNetworkMessage.SyncFlags.HasNewFood))
return;
if (!ChaosKeycardItem.SnakeSessions.TryGetValue(__instance.ItemSerial, out SnakeEngine engine))
return;
if (engine.Score < 20)
return;
if (UnityEngine.Random.Range(0, 10) is not 0)
return;
Player player = Player.Get(__instance.Owner);
player.RemoveItem(__instance);
ExplosionUtils.ServerExplode(__instance.Owner, ExplosionType.PinkCandy);
Logger.Info($"Player {player.LogName} exploded. Reason: played SNAKE too much");
}
}
why the hell is this using a switch lmfao
DoorAction action = door.TargetState ? doorAction.Open : DoorAction.Closed;
DoorEvents.TriggerAction(door, action, ply);
U made it thats why
I don't know about labapi only custom roles, exiled has those.
And I also did make a custom items.
Logger.Debug has a second parameter as a bool, I use something like
Main.Instance.Config.Debug to can change to print or not
ÿÿÿÿ ADemoSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null !DemoSystem.Snapshots.TestSnapshot <Name>k__BackingField Firstnm Lastnm
@grand flower does this look like a proper serialized?
Damn
I'll just mute them 
Otherwise it would be
Let's say, a bit unpleasant for the ears
At least the mtf will get a good warning
True
that looks like binary although i don't know your schema obviously
if you haven't yet, make sure to write the version into the file first
Any firearm-specific events yall would like to see?
how about an ADS toggle event
no cancellation ofc
isnt that already a thing?
oh
Brainstorming time
i didn't think of "aiming" lol
jailbring swong? jailbirdcharged?
or with -ing too
i guess
My limitation is cancelling events which are triggered client-side no matter what
such as firing
maybe MicroHidChangeing state
inserting/removing magazine? kinda niche
it probably wouldn't be cancelable
Ax
whar

Reloading, Unloading
sadge? idk
why didn't i think of searching for that word
then
cocking weapon event
desync? probably
well, only thing I would appriciate is Jailbird Damage hander parse the "IsCharged" can yo do that? 
no!
ToggledParticleDisruptorFiringState
also 127-related events maybe
Hmmm
would 127 events be their own category?
like
- Scp127ReactingToSpawnWave
- Scp127SayingHello
- Scp127SayingGoodbye
- Scp127LosingFriend
why did i name the last one that 😭
He is sad when you die
I think its all gonna be 1 event Scp127Playing/ed voiceline
Each one has unique identifier enum for translations so you can tell which one it is
yeah i imagine people would want that
also events for MicroHID and Jailbird
what do I have to use
from the dedicated server files
LabApi.dll ?
and probably Assembly-CSharp. dll too
@unique crane hi buddyyyy
im here to complain
jk i want RAUtils.ProcessPlayerIdOrNamesList
Haiiii
whats the actual source for that
mines broken
idk what changed in 14.1 in it for it to break
public static List<ReferenceHub> ProcessPlayerIdOrNamesList(ArraySegment<string> args, int startindex, out string[] newargs, bool keepEmptyEntries = false)
{
try
{
string argString = FormatArguments(args, startindex);
List<ReferenceHub> players = ListPool<ReferenceHub>.Shared.Rent();
/*
* If the list starts with an "@" we will be looking for a list of player names rather than ID's
* Tab autocomplete will format names like: @Thomasjosif or @"Thomas josif"
*/
if (argString.StartsWith('@'))
{
Regex rg = new Regex(PlayerNameRegex);
MatchCollection mc = rg.Matches(argString);
foreach (Match match in mc)
{
// We need to remove the player from the arraysegment because if it contains spaces it ends up screwing up the segmentation
argString = ReplaceFirst(argString, match.Value, "");
// Remove our formatting
string name = match.Value.Substring(1).Replace("\"", "").Replace(".", "");
List<ReferenceHub> found = ReferenceHub.AllHubs.Where(ply => ply.nicknameSync.MyNick.Equals(name)).ToList();
if (found.Count == 1 && !players.Contains(found[0]))
players.Add(found[0]);
}
newargs = argString.Split(' ', (keepEmptyEntries ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries));
return players;
}
if (args.At(startindex).Length > 0)
{
// If the list of players to set nickname for is a set of ID's (i.e.: 1.2.3)
if (char.IsDigit(args.At(startindex)[0]))
{
//Regular playerID processing. See the Misc.ProcessRaPlayersList util.
string[] sar = args.At(startindex).Split('.');
// Go through all strings in the split arguments above
foreach (string s in sar)
{
if (!int.TryParse(s, out int i) || !ReferenceHub.TryGetHub(i, out ReferenceHub hub))
continue;
if (!players.Contains(hub))
players.Add(hub);
}
}
// If the list of players to set nickname for is a set of names (i.e.: SoNearSonar.Beryl.Masonic)
else if (char.IsLetter(args.At(startindex)[0]))
{
string[] sar = args.At(startindex).Split('.');
foreach (string s in sar)
{
foreach (ReferenceHub hub in ReferenceHub.AllHubs)
{
if (!hub.nicknameSync.MyNick.Equals(s))
continue;
if (!players.Contains(hub))
players.Add(hub);
}
}
}
}
newargs = args.Count > 1 ? FormatArguments(args, startindex + 1).Split(' ', keepEmptyEntries ? StringSplitOptions.None : StringSplitOptions.RemoveEmptyEntries) : null;
return players;
}
catch (Exception e)
{
Debug.LogException(e);
newargs = null;
return null;
}
}
than youuuu
oh yeah
that truly is special
me when
also
just realized ur code makes it so you cant have both player num + a player name
like 2.david.eve.5.6
wont work
only 2, 5, 6 will be processed 
Not that big of a deal
yeah just thought it was interesting
Make a pr eve

You can write the stuff and send it to david
good point h
If you make something better, just DM it to me.. ill make PR and take the money
however



A rare or very done steak?
something aint right here...
Is there an event for cycling a round? Like pumping a shotgun?
smh
is there an easy way to get the local offset of a room ur in ?

transform.InverseTransformPoint
yeah but
is there anything ingame currently
for it
otherwise i gotta make command 💔
Cant you just player.position - room.position?
That gives you vector with offset from room and the player
basegame should have a nice way of it
@upper vapor am i stupid
this should be fine right
Yup
coolll
You can save some nanoseconds by putting player.Room into a local variable
currenty you need to network spawn it yourself, this will probably change in future updates tho
yeah .Spawn()
it should have a bool spawn parameter
yeah
Hmm.. Ill see if that can be easily implemented
Unable to test so resorting to asking here: does damage applied by cardiac arrest have 049 as the attacker if it was the one to touch you and give it to you
it should have
The PocketCorroding effect has an AtrackerHub property
Use the _attacker field of the effect
Wasn't it Corroding that had it?
does the one where you die to the exits?
Yeah you're right
im 99% sure it doesnt
David go implement
also when you leave pd to know the 106 that sent them in
cuz like
solves all my problems
awesome ty
Scp173AddedObserverEventArgs: is Player 173 or is it Target?
(kinda wish this was a little more documented)
Is there any player event for when they shoot an obstacle? Other than OnPlayerPlacedBulletHole. That event does have the position but not the damage info of the shot.
there wont be any damage on anything that aint a player/npc
I know, but I still want to get the potential damage that would've been inflicted with the weapon
I suppose I could get the player's current weapon and use OnPlayerPlacedBulletHole though
there is Shooting event
that may give dmg
it does but no position
shooting doesnt give damage
oh
position of what?
then idk, there is 2 events that I know of, PlacedBulletHole and Hurt
make sure you check if Hurt is from a gun
Firearm._modules would have the hitreg module right
idk
youre probably not a network identity on your own machine so yeah
Why I cannot reload while having different size?
Is 096's head detection clientside or serverside
server side im 99% sure
i have a salt clip of myself looking down, and 096s face goes where i was looking 0.1 seconds ago and he aggros on me
maybe its also both,
yeah that explains it, a little disappointing if so
so the client catches whatever the server doesnt
why?
the false positives are annoying
Oh yeah
but i guess its like
an anti cheat measure
SL already bans for any form of game modification so i dont see that its necessary
and they already made tesla gates client side to avoid this exact problem
and tesla gates are way more common than 096
ehhhh
you don't have to make it fully clientside, just with a margin of error
cause rn any amount of server lag or ping from 096 or you and you'll end up "looking at it" without seeing it on your screen
if they gave you a grace margin where until the server disagrees on the fact you haven't seen 096 X times in a short period it forces it
would be a lot more enjoyable for players
so for like
0.5 seconds
if the client insists it doesnr see 096 face, server lets it slide
that or it could just accumulate error until it goes over a threshold
slowly reduce the accumulated error over time so for normal players it works fine
cheaters who don't tell the server they've seen 096 would have it be forced fast enough
each tick the client disagrees with the server it adds a point?
and every tick they agree it deducts a point?
each tick the server thinks the player saw 096's face without receiving the client's acknowledgement
I would make it deduct points slower than gaining them
bit of trial and error and they'd probably end up with thresholds that most players like
I get why it's not clientside/fully clientside but ouch
and the client can say it saw 096 face without the server agreeing?
well actually that might open up problems too
of players cheating to trigger 096
096 remote enragement hacks
yeah
can have the threshold go both ways, with some sanity checks
LOS, etc
that "hack" would be simpler to prevent
when youre playing 096 and a CI who just spawned triggers you
and again they have an AC so w/e on that part
what is LOS?
line of sight
oh
if the client tells the server they've seen 096 they can just do sanity checks to make sure it was possible
that's not as much of a problem as the server doing false positives, player enjoyment wise
so if theres like no good ray between 096 and player then it wont work
yeah with stuff that kills you false positives is 100% better
negativez*
and like, a player shooting 096 triggers it anyway so not like 096 would feel much of an issue that way
I don't think 096 would see the difference if something like this was implemented
Mostly players getting less false positives
when i played him i never say "omg that guy shouldve triggered me"
the interaction is a lot more intimate on the victims side than 096s side
the threshold stuff would very likely help with that
obviously in a perfect world we have instant transmission and theres 0ms ping
dunno if I can suggest that somewhere 
yeah but multiplayer's never perfect
unless you're doing a LAN party and even then
just build a backlog of these suggestions somewhere and pay 5 bucks for a month of tier 2
and then send a bunch peridoically to get feedback and get staff to read it
this implementatjon is probably a bit hard but its worth a shot asking nw to add it
We have a channel here for patreon supporters, or you can make a post on the Steam foums / Subreddit for free
!forums
SCP: Secret Laboratory - Deep within one of the SCP Foundation’s emergency containment sites, a catastrophic containment breach leads to multiple SCP subjects being released from their cells. With containment compromised, facility personnel rush to evacuate while waiting for Mobile Task Forces to arrive and restore order, but with the Class-D ...
Ehhh I don't wanna make a public post, if the devs see the idea here they're free to use it
networking seems really hard to me
i dont understand how people can understand that shit
made it my field for games, love it
it is complex but ever so satisfying when things end up working
if i wanted to ever work with netcode whats a good place to start learning it
Can you block a player from aiming a weapon?
there's no OnPlayerAimingWeapon that I can see
right, clientside
i feel like that was possible in the past but eh
Mostly wondering why that's a nono when stuff like OnPlayerReloadingWeapon exists. Unless that's not predicted?
LinearAdsModule but it all seems readonly
you can't cancel ads, that's client-side behavior
imagine having to wait 240ms for the server to approve your toggle request
Doesn't mean you can't predict it and get told off by the server
that would also be weird for players
i guess they could add a sync var or some other way to stop a specific firearm from adsing
I found some sync data so I'm just tapping into that
will find out if it works later
But "it looks weird" is a little silly imo
It'll look weirder for players with high latency which, i'll be honest, I'm not trying to make it look good for them. You play on a server with high latency, expect some breakage
For low latency, maybe a little but in my scenario they'll understand why they can't aim anyway
If the previous API had it, they already had that weirdness anyway
See? It has but not in current version
oh
okay that explains things
I forget it's not complete
scratch everything i've said then, i'll just put a todo
what if you send the ads rpc to the owner of the firearm 
probably won't work but maybe it's worth a try
I don't think I have access to it
Seems like they use SyncData for ADS not an RPC, so that's what I tinkered with in the meantime
OnPlayerAimingWeapon probably ends up doing the same thing anyway
LinearAdsModule.AdsData.AdsTarget
try the OnAdsChanged method
Event
that's not implemented yet
use Aimed
right
Left
Would being able to directly change weapon stats like damage and fire rate be implemented in the future?
Damage you can already do serverside with OnPlayerHurting
I think you can also current the ammo type but not entirely sure if works
What about penetration?
Also how would i account for things like burn damage and damage resistance
you can change penetration
it's in the base stats i believe
Burn dmg is inside the module
It's a field so you can edit it with publicized one
I thought it was protected
nothing's protected if you publicize 
... ngl i forgot publicising was a thing
use BepinEx.AssemblyPublicizer from NuGet
Is there a way to fix weapon reload as differently scaled player?
you'll have to wait for NW to fix it unfortunately
alternatively, don't scale the player 
one of the static fields in your EventsHandler class throws NRE
How can I install LabAPI dependecy?
In you server files under \SCPSL_Data\Managed you should see the LabAPI dll
you should also reference Assembly-CSharp.dll while your there
Yeah I know but how to setup Visual Studio
under the solution explorer tab right click dependencies and click add project reference
hmm, can you show a screen shot
Just a photo screenshots don't work for some reason
right click this
when you reference a dll you are creating a dependency if that what you were wondering
It shows
Add refernce
Add Service Refernce
Add Analyzer
Manage NuGet Package
Collapse All Dependencies
Scope to This
New Solution Explorer view
So it should work?
Where can I find that?
same folder as LabAPI.dll
It says that plugin could not be found
i added Assembly Csharp.dll but it is still there
because it is LabApi.Loader.Features.Plugins
what does the error say? also what happened to screenshots
Feature target type object creation IS not avalaible in C# 7.3. Please use language version 9.0 or greater
for this you need to modify your .csproj file to include <LangVersion>12</LangVersion> in a property group
you can use any C# version basically, as long as you have the SDK installed
Where Can i find csproj file?
in your project
Cant find the meme for the screenshot button
Looking for it as well
my new keyboard doesnt have a print screen button
😢
at least you have win+shift+s
i have to do fn + f7 to activate it
ive never used print screen button

so you don't have things to screenshot
must be an easy life
oh just tried it out and it does the exact same thing xD
i know 
hate it for how slow it is, even if you get to choose the area you want
windows moment
turns out you just don't send the spawn message to the server
use Player.ReadyList instead of Player.List
yes
i thought that was scaling related, weird
erm
so when you send a spawn msg to dedicated server
it fucks it all server sided
its how i fixed my skeleton being invisible
Skill issue
yeah trouble told me about it
(did the same)
thanks
i dont think ready list is good for that anyway, when theres a Player.AuthenticatedList option you should use that instead
yeah i kind forgor

should hopefully make it into the next build
also hopefully IEnumerable<Player> GetAll(bool includePlayers = true, bool? isPlayerReady = true, bool includeNpcs = true, bool? isNpcDummy = true, bool includeHost = false) will be there too
In what folder
should be the folder of your project
or the solution if you specified it too in the setup
Why nullable if you specify default true

by default it returns Player.ReadyList
I meant as bool?
yeah whys it nullable
/// <summary>
/// Gets a filtered set of players from the <see cref="List"/>.
/// </summary>
/// <param name="includePlayers">Whether to include real players, see <see cref="IsPlayer"/>.</param>
/// <param name="isPlayerReady">
/// Whether to filter real players by their authentication status, see <see cref="IsReady"/>.
/// Use <see langword="null"/> to get both unauthenticated and authenticated players.
/// </param>
/// <param name="includeNpcs">Whether to include non playable characters (NPCs), see <see cref="IsNpc"/>.</param>
/// <param name="isNpcDummy">
/// Whether to filter non playable characters (NPCs) by whether they are a <see cref="IsDummy"/> or not.
/// Use <see langword="null"/> to get both dummy NPCs and non dummy NPCs.
/// </param>
/// <param name="includeHost">Whether to include the host player or not, see <see cref="IsHost"/>.</param>
/// <returns>The set of all players that meet the criteria.</returns>
/// <remarks>
/// By default it returns the same set of players as <see cref="ReadyList"/>.
/// <para>
/// Filtering is done on 3 groups of players separately.
/// If a player meets the criteria for 1 of the 3 groups it is included in the list.
/// The 3 groups are <paramref name="includePlayers"/>, <paramref name="includeNpcs"/>, and <paramref name="includeHost"/>.
/// Further filtering per group is specified by <paramref name="isPlayerReady"/> and <paramref name="isNpcDummy"/> respectively.
/// If <see langword="null"/> the filter is not applied, thus includes all players for that group.
/// </para>
/// </remarks>
public static IEnumerable<Player> GetAll(bool includePlayers = true, bool? isPlayerReady = true, bool includeNpcs = true, bool? isNpcDummy = true, bool includeHost = false)
{
foreach(var player in List)
{
if ((includePlayers && player.IsPlayer && (!isPlayerReady.HasValue || isPlayerReady == player.IsReady)) ||
(includeNpcs && player.IsNpc && (!isNpcDummy.HasValue || isNpcDummy == player.IsDummy)) ||
(includeHost && player.IsHost))
yield return player;
}
}
null would be no filter
holy yap
Ah now i get it why
var 💔
oh lmao, i actually better change that they dont like it when im using var
ur blind
i dont either!!!
Ye i don't have glasses on
I do when the type is like 10+ character long
The compiler already knows what type will be there

.editorconfig?
i dont think its being used
Only valid reason to use var is when you are working with linq's IOrderedEnumerable with 5 billiion generic params, groupings and whatever you make up
in my opinion
So it now works
holy bad design
something wrong, its not merged yet so i can still make changes
yea
the existence of that method
rather than have a "do everything" player list method just have people use linq
Well, in my opinion Player.List is a beginner trap rn, cause' it does not contain players only
Better approach would be to return only real players, no dummies, no host and have separate properties for that
Then Player.List would be truly a List of Players
Like all the way from MP2 i had to have this defined (Of course it was constantly changing, it went through Exiled, NW API and now it's on LabAPI)
Is this what you were looking for https://github.com/northwood-studios/LabAPI/blob/3e4c654e2c7b356b9a4b9d9b0e7bc851fff1c527/LabApi/Features/Wrappers/Players/Player.cs#L67
well, this one has dummies in it
true, im going to add a Player.AuthenticatedList which is prety much just ready players
prefect for sending network messages too
some things didn't work with them so i always ignored them in code
yeah thats good you did that
awesome
I agree about the using linq methods over the "do everything" one and i expect experienced devs to do their own filtering when needed. The GetAll method is mostly targeted towards new devs as a nice catch all case that doesnt hide the nuances of getting all the players. This is why i decided to keep Player.List containing all the players including the host otherwise it would have to be made for a specific use case e.g. only real players or real players and dummies. The downside being that new devs are unlikely to understand that there are certain groups of players that must be treated differently. The consequences of which are pretty bad, usualy soft locking players and crashing servers. So Player.List remains as the option for experienced devs to do their own filtering and Player.GetAll() is a good option for beginners.
imo one of the main issues atm is that no one has docs so none of this is apparent, hopefully the situation improves once a nuget package has been made
What's possible usecase of processing host equally with real players?
what im trying to say is that i didnt want to hide very important details in the API by providing some "catch all" use case which is technically impossible todo. What mattered was new devs understanding that they shouldnt just be using a single set of players blindly.
we could remove host, and players would be able to use Player.List without issues about 90% of the time, the issue now is that the list contains unauthenticates players and NPCs, which usually causes players to become softlocked if interacted with incorrectly. i want to avoid this essentially as i remember it being one of the main issues plugin devs ran into, and an especially hard one for a new dev to figure out
From my experience touching dedicated server instance was only in some very specific circumstances, and Server.Host worked fine
thats true
Why even include unauthed players?
Will there be an event that allows modification of round end conditions?
i think theres an event like that already
RoundEnding
Set the IsAllowed
Isn't it only fired when round's about to end?
Yes?
yeah it might be by the looks
When else would you expect it to run?
If you set it to false, it wont end
And try again in 2,5 seconds
OH
I get it..
Writing while in a bus is kinda hard
Let me see its implementation
I think what you are looking for is Player.ReadyList or Player.AuthenticatedList
I just want to have some players excluded from round end conditions
Because i need to use an scp role for players as it allows them to see in the dark
But they interfere with those conditions and you can't easly (without making custom coroutine) modify them
definitely make a github issue about it so we dont forget
You wil have to do that as of right now and force end it, sorry. But yea make a git issue request
Something I would like to definitively look into in future
Like NV status effect
Okay, will do later
cant you patch the scp target getter at least
Just please don't blind players when the lights are on (or just have a synced boolean for that)
a fix i had for NV was spawning a light only one player could see and parenting it to the player
I think zombies are counted differently
But i can't look at code rn
Yeah, i tried that and it kind of was flickering for me (maybe i didn't set the smoothing)
qeird it didnt flicker for me
one seocnd
well actually mine is an exiled and barely works so
if the light is parented, smoothing doesnt do anything unless you move the light relative to the player its parented too
if youre interested in seeing here is the commit right before it got deleted
https://github.com/icedchai/omni-plugins-pub/commit/3acb471cf97e1fba2ef05a3e3cbddbe4f013e12b
wait how do i hide embed
surround it with <> or click the small x
thank you
i dont like posting links and then it makes a huge image in the convo
it feels like an interuption
you can click the x next to the embed to clear it for everyone
top right
i dont have such an X on mobile so the <> works fine
If you had to implement client side parent rpc in such a way that armature bones were supported how would you do it. Short of making the bones NIs.
Hello so I have two questions. First how can I make script execute at start of round and how to get player location.
onroundstart and player.transform.position
i recomend reading this https://github.com/northwood-studios/LabAPI/wiki
embed success
yeah but how can I know which using LabAPI.something to use?
Yeah, I switched all List in the project to ReadyList with IsPlayer check. AuthenticatedList 👀
Could you please check this one: https://discord.com/channels/330432627649544202/1366986892414816287
Player.Position
You mean namespace? Your IDE should help you with that
wdym
You can use Unity features by referencing the assembly but imnot sure thats what you want.
and u cant use the editor you have to interact with the scene thru code
By flickering i meant that the light didn't update in real time
Yeah.. that makes sense
i want you to look at my code. Its under Omni-CustomItems/Equipment/Goggles/NightVision or something. it shows how you can just do light.trans.parent = player.transform
wait did i maybe modify the light source
fuck one second
Yeah it miggt have to do with smoothing or some shit
Oh, i parented to a player using that new method
what new method
oh the RPC?
Yep
the rpc triggers no matter how you parent right
this plugin is for 14.0 and it still triggers the rpc
yeah that doesnt work as you would expect, what you want todo is parent it directly instead
yea but the problem is that
as you said
new devs probably won't know what all of this means
so it's just gonna be extremely confusing
secondly, new devs aren't gonna understand how to properly use the method. you're not supposed to do Player.GetAll(true, null, false, true) etc, you're supposed to do Player.GetAll(isReadyPlayer: false)
i dont doubt that, at least all the details are not hidden away and are given upfront through the docs
that's something i think will trip a lot of new devs up
maybe, im not sure how to solve that
don't have the method be like that?
when you have 5 optional parameters, three of which are bool?, i think it's clear that something is wrong
if you really want a "GetAll", make it take a SearchSetting struct or something
and extract the parameters out to the struct
it'll take up more lines, but then you don't need to worry about beginners using it wrog
with this you can also pre-define SearchSettings
no need for Player.AuthenticatedList, just Player.GetAll(SearchSetting.Authenticated)
public struct SearhFilter
{
public static SearhFilter Ready => new();
public static SearhFilter Authenticated => new() { IncludeNpcs = false };
public bool IncludePlayers = true;
public bool? IsPlayerReady = true;
public bool IncludeNpcs = true;
public bool? IsNpcDummy = true;
public bool IncludeHost = false;
public SearhFilter() { }
}
something like this?
SearhFilter

clos enough
if you dont put the c in i will cry 😭
Maybe search flags?
Nah, bad idea
Or, if you combine some search (flags )options and put them in a static class called SearchOptions then maybe it would make sense
maybe make it not nullable bool
have it be more clear
using System;
[Flags]
public enum PlayerSearchFlags
{
None = 0,
UnauthenticatedPlayers = 1,
AuthenticatedPlayers = 2,
Dummies = 4,
Host = 8
}
Yea i was already doing that, but i will try without parenting it to the client
Something like that
You can also make "presets" from these flags if you want
As i said
those could also be included in the enums
like AuthenticatedAndDummies = AuthenticatedPlayers | Dummies
yeah i believe thats the way to go, would be much easier to explain
yes
not actual docs, just showing how everything is divided up. still would like a better name for RegularNpcs currently no name is given anywhere else for non dummy NPCs
[Flags]
public enum PlayerSearhFlags
{
None = 0,
AuthenticatedPlayers = 1, // IsPlayer && IsReady
UnthenticatedPlayers = 2, // IsPlayer && !IsReady
DummyNpcs = 4, // IsNpc && IsDummy
RegularNpcs = 8, // IsNpc && !IsDummy
Host = 16, // IsHost
}
what would a non-dummy npc be
old exiled npcs
all dummies are NPCs, think of any NPC before dummies were added
dummies are primarily used testing so they are coded to act more like players which can be problematic let say if you want to hide them on the player list or RA
also dummies are expected to be visible to plugins like players would, while non dummy NPCs are not
Hello so I want to try example plugin HelloWorld but it doesn't load
I have it in LabAPI/plugins do i have to put it into global or 7777 folder?
should be explained here https://github.com/northwood-studios/LabAPI/wiki
I tried but it doesn't work
correct
the wiki may be outdated
So I should but it into global folder?
global will load it for all ports
[port (eg 7777)] will only load for that port
fuck, it is
In february last update of readme I saw
Thanks now it works
Gotta ask, (this is a repost from Exiled)
Why is the default gravity for a player 0, -19.60, 0? (The 0, -12.60, 0 is just me testing around with gravity)
Wouldn't it make more sense if it was 0, 1, 0 or 1, 1, 1?
Probably due 19.60 being twice the amount of 9.8 m/s^2 which is Earth's gravitational force
thats what i assume

what the fuck is that reaction board
although if its passed through an exponent shouldn't it be positive and not negative?
its probably negative becayse its pulling you downward
wait
which way does the gravity pull
What is the exponent for though
sorry, its negative because its processsed positive as the value, and then applied negatively as the gravity
I think.
I understand its downwards, but it doesnt make that much sense to me though since "negative gravity" would make it seem (at least to me) that you would be going upwards.
its not actually like gravity
imo
its like the vector3 added to your position when gravity is applied
since Y is up in the coordinate system, applying a negative force would make the object go down
sure, the naming isn't the best but it does mean upwards force
Probs the reason, except for still confused on why its doubled.
Eh, either way, not a big deal
Just a generalist question I had
When will SCP SL fix the jump
Double it 
So the d class weigh 60 lbs
hubert had to artificially make them fatter
Unity's units are interesting
Although this did come up with an idea for like an event. Reversed Gravity
I dont want to think about it too hard now or the implications of it on Surface
There are invisible nets
Otherwise I will try to make it a real thing lmao
Just like in australia
I think it depends on whether the developers choose to scale unity units to meters or to an arbitrary unit
so you dont fall into outter space
Im aware, but it wont stop them from just getting stuck on Surface because they cannot jump into the elevator 
Im not sure whether SL uses meters or what.
Meters I thought
It used to be not the case way back in the day but iirc now days 1 unity unit in game = 1 meter
I think so?
Thats simply that did the code use
back in the day before 12.0 SL used arbitrary scaling
then they slightly adjusted all scales
It could be scaled on LabAPI side yea but too late for that
Its not a big deal as I said, just a generalist question
Xml, ye not shipped with the game yet
@hearty shard you remember this?
Gravity being 1,1,1
guh
shh
Also if you like you can choose earths gravity i guess
If you want
latest version
Put it alongside your labapi dll where you reference it
Does the OnPlayerInteractedDoor event fire even if the player wasn't allowed to open/close it?
Pretty sure yea
its usually a postfix or something right
to be sure, I worded it weird, if I do ev.IsAllowed = false in OnPlayerInteractingDoor
Is ChaosKeycardItem not registered as KeycardItem in LabAPI?
A few days ago i had this code and after that check it swaps original keycard to a custom one, but it didn't swap for chaos keycard only
that's what i got from wrappers list ig
nvm no it doesn't
but I think I see how I can handle stuff so no biggie
Oh that
uhh
try it and seee
yeah no but there's an issue
I switched ev.IsAllowed to ev.CanOpen
if CanOpen is false it still doesn't fire OnPlayerInteractedDoor
Yep
and honestly it probably should?
I get stopping it for IsAllowed but the player still interacted with the door even if they couldn't open it
if that remains it kinda makes InteractedDoor useless for cases where I want a handler to potentially block the interaction in a certain scenario and another to blow it up if nothing blocked the interaction
I'd have to put both of these in InteractingDoor and pray one runs before the other so I can check ev.IsAllowed
Im having an issue really stupid with doors, im making my own editor and the doors for some reason aren't loading in the correct position
The door will always spawn in heavy all of the types in the position where they should be but on heavy and Relative positioning will be messed up so badly, i spawn them in surface for example and they will be in the void working fine but messing up everything else like movement etc...
PlayerInteractedDoorEventArgs has CanOpen so surely this is a bug right?
Hello so how can I print player position at start of round? I tried defining as a Vector3 position = Player.Position but it says that An object reference is required for non-static field,method, or property 'HelloWorldPlugin.Player'
@unique crane should I open an issue for the above or is that... normal? nvm was an issue with my IDE or binaries idk
ahh discord
can't have AV1 on discord too
i guess it still kinda flickers, but it's better than before
practically unnoticeable because of compression
It may be the compression yea
but I dont see any issue with that
Like if you parent it to the player
you cant get it smoother
Made one just to be sure since I feel like this is a pretty nasty issue to have https://github.com/northwood-studios/LabAPI/issues/106
the worst thing is, looking at LabAPI's code I feel like that's the case
so idk why it's not running the event
You need to spawn the door with global transform
So either don't parent it, or hack mirror like I did
only IsAllowed prevents it
can you be more specific on hack mirror
so if i just use a version of this i should be able to change their position
hmm sport and other don't
but for example lockers
don't spawn in the correct
nvm it works? Seems like my IDE fucked up compiling or copying the plugin DLL over -_-
Oh they uh
Have you tried joining after spawning them?
So yea by checking the code i probably understood what to do
no
honestly i didn't
best of luck or smth

