diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 4d67329a6..000000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-# To get started with Dependabot version updates, you'll need to specify which
-# package ecosystems to update and where the package manifests are located.
-# Please see the documentation for all configuration options:
-# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
-
-version: 2
-updates:
- - package-ecosystem: "nuget" # See documentation for possible values
- directory: "./EXILED" # Location of package manifests
- schedule:
- interval: "weekly"
diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml
index 16ff4dafa..7ee77d48a 100644
--- a/.github/workflows/dev.yml
+++ b/.github/workflows/dev.yml
@@ -4,9 +4,11 @@ on:
push:
branches:
- dev
+ - scpsl14
pull_request:
branches:
- dev
+ - scpsl14
workflow_dispatch:
defaults:
diff --git a/.github/workflows/pull_request_opened.yml b/.github/workflows/pull_request_opened.yml
index a54bed971..6e2248852 100644
--- a/.github/workflows/pull_request_opened.yml
+++ b/.github/workflows/pull_request_opened.yml
@@ -1,7 +1,9 @@
-name: Labeler
+name: Pull Request CI
on:
- - pull_request_target
+ pull_request_target:
+ branches:
+ - '**'
defaults:
run:
@@ -9,21 +11,28 @@ defaults:
jobs:
set-labels:
+ name: Set Labels
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- - name: Labeler
- uses: actions/labeler@v5.0.0
+ - uses: actions/labeler@v5.0.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/labeler.yml
sync-labels: true
assign-author:
+ name: Assign Author
runs-on: ubuntu-latest
permissions:
pull-requests: write
-
steps:
- uses: toshimaru/auto-author-assign@v2.1.1
+ validate-pr-title:
+ name: Validate PR title
+ runs-on: ubuntu-latest
+ steps:
+ - uses: amannn/action-semantic-pull-request@v5
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/push_nuget.yml b/.github/workflows/push_nuget.yml
index 87acc59b8..5150b0c7e 100644
--- a/.github/workflows/push_nuget.yml
+++ b/.github/workflows/push_nuget.yml
@@ -10,7 +10,7 @@ defaults:
working-directory: ./EXILED
env:
- EXILED_REFERENCES_URL: https://ExMod-Team.github.io/SL-References/Master.zip
+ EXILED_REFERENCES_URL: https://ExMod-Team.github.io/SL-References/Dev.zip
EXILED_REFERENCES_PATH: ${{ github.workspace }}/EXILED/References
jobs:
diff --git a/.gitignore b/.gitignore
index ecdece2bb..958e3428c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -373,4 +373,7 @@ NuGet.config
_site/
# JSON Schemas
-JSON/
\ No newline at end of file
+JSON/
+
+# Mac DS_Store
+.DS_Store
\ No newline at end of file
diff --git a/EXILED/EXILED.props b/EXILED/EXILED.props
index 62d6e57cd..c9b421e84 100644
--- a/EXILED/EXILED.props
+++ b/EXILED/EXILED.props
@@ -2,7 +2,7 @@
- Exiled Official
+ ExMod Team
@@ -15,7 +15,7 @@
- 8.14.1
+ 9.0.0false
diff --git a/EXILED/Exiled.API/Enums/AdminToyType.cs b/EXILED/Exiled.API/Enums/AdminToyType.cs
index 181c62552..c7f937721 100644
--- a/EXILED/Exiled.API/Enums/AdminToyType.cs
+++ b/EXILED/Exiled.API/Enums/AdminToyType.cs
@@ -27,5 +27,10 @@ public enum AdminToyType
/// ShootingTarget toy.
///
ShootingTarget,
+
+ ///
+ /// Speaker toy.
+ ///
+ Speaker,
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/CameraType.cs b/EXILED/Exiled.API/Enums/CameraType.cs
index 26685fa8e..6248d2a24 100644
--- a/EXILED/Exiled.API/Enums/CameraType.cs
+++ b/EXILED/Exiled.API/Enums/CameraType.cs
@@ -68,9 +68,6 @@ public enum CameraType
HczElevSysB,
HczHallway,
HczThreeWay,
- HczServersBottom,
- HczServersStairs,
- HczServersTop,
HczTeslaGate,
HczTestroomBridge,
HczTestroomMain,
@@ -124,6 +121,19 @@ public enum CameraType
Hcz173ContChamber,
Hcz173Hallway,
HczCurve,
+ HczJunkMain,
+ HczJunkHallway,
+ HczCornerDeep,
+ HczDSS08,
+ HczMicroHIDStairs,
+ HczPipesHallway,
+ HczWarheadStarboardElevator,
+ HczMicroHIDMain,
+ HczWarheadTopElevators,
+ HczWarheadConnector,
+ HczWarheadPortElevator,
+ HczMicroHIDLab,
+ HczPipesMain,
#endregion
}
}
diff --git a/EXILED/Exiled.API/Enums/DamageType.cs b/EXILED/Exiled.API/Enums/DamageType.cs
index f9d1617f6..add8d86ca 100644
--- a/EXILED/Exiled.API/Enums/DamageType.cs
+++ b/EXILED/Exiled.API/Enums/DamageType.cs
@@ -120,6 +120,11 @@ public enum DamageType
///
SeveredHands,
+ ///
+ /// Damage caused by severed eyes.
+ ///
+ SeveredEyes,
+
///
/// Damage caused by a custom source.
///
@@ -250,4 +255,4 @@ public enum DamageType
///
Marshmallow,
}
-}
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/DisruptorMode.cs b/EXILED/Exiled.API/Enums/DisruptorMode.cs
new file mode 100644
index 000000000..643ed0c30
--- /dev/null
+++ b/EXILED/Exiled.API/Enums/DisruptorMode.cs
@@ -0,0 +1,30 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Enums
+{
+ ///
+ /// Represents disruptor's fire modes.
+ ///
+ public enum DisruptorMode
+ {
+ ///
+ /// Unknown mode.
+ ///
+ None,
+
+ ///
+ /// Single shot mode.
+ ///
+ Disintegrator,
+
+ ///
+ /// Triple shot mode.
+ ///
+ BurstFire,
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/DoorType.cs b/EXILED/Exiled.API/Enums/DoorType.cs
index 04f38c19d..36bb9b853 100644
--- a/EXILED/Exiled.API/Enums/DoorType.cs
+++ b/EXILED/Exiled.API/Enums/DoorType.cs
@@ -8,8 +8,7 @@
namespace Exiled.API.Enums
{
using Exiled.API.Features.Doors;
-
- using static Interactables.Interobjects.ElevatorManager;
+ using Interactables.Interobjects;
///
/// Unique identifier for the different types of doors.
@@ -133,11 +132,6 @@ public enum DoorType
///
EscapeSecondary,
- ///
- /// Represents the SERVERS_BOTTOM door.
- ///
- ServersBottom,
-
///
/// Represents the GATE_A door.
///
@@ -159,19 +153,24 @@ public enum DoorType
HeavyContainmentDoor,
///
- /// Represents the HID door.
+ /// Represents any heavy containment styled door.
+ ///
+ HeavyBulkDoor,
+
+ ///
+ /// Represents the HID_CHAMBER door.
///
- HID,
+ HIDChamber,
///
- /// Represents the HID_LEFT door.
+ /// Represents the HID_UPPER door.
///
- HIDLeft,
+ HIDUpper,
///
- /// Represents the HID_RIGHT door.
+ /// Represents the HID_LOWER door.
///
- HIDRight,
+ HIDLower,
///
/// Represents the INTERCOM door.
@@ -231,7 +230,12 @@ public enum DoorType
///
/// Represents the Gate in the Checkpoint between EZ and HCZ.
///
- CheckpointGate,
+ CheckpointGateA,
+
+ ///
+ /// Represents the Gate in the Checkpoint between EZ and HCZ.
+ ///
+ CheckpointGateB,
///
/// Represents the Gate in the Checkpoint between EZ and HCZ.
@@ -269,7 +273,7 @@ public enum DoorType
ElevatorGateB,
///
- /// Represents the Elevator door for .
+ /// Represents the Elevator door for .
///
ElevatorNuke,
@@ -307,5 +311,10 @@ public enum DoorType
/// Represents the New Gate where Scp173 spawn in the .
///
Scp173NewGate,
+
+ ///
+ /// Represents the ESCAPE_FINAL door.
+ ///
+ EscapeFinal,
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/EffectType.cs b/EXILED/Exiled.API/Enums/EffectType.cs
index 2ba874dd8..b2894486e 100644
--- a/EXILED/Exiled.API/Enums/EffectType.cs
+++ b/EXILED/Exiled.API/Enums/EffectType.cs
@@ -21,7 +21,7 @@ public enum EffectType
///
/// This EffectType do not exist it's only use when not found or error.
///
- None = -1, // TODO: remove = -1
+ None,
///
/// The player isn't able to open their inventory or reload a weapon.
@@ -239,5 +239,25 @@ public enum EffectType
/// .
///
Slowness,
+
+ ///
+ /// .
+ ///
+ Scp1344,
+
+ ///
+ /// .
+ ///
+ SeveredEyes,
+
+ ///
+ /// .
+ ///
+ PitDeath,
+
+ ///
+ /// .
+ ///
+ Blurred,
}
}
diff --git a/EXILED/Exiled.API/Enums/PrefabType.cs b/EXILED/Exiled.API/Enums/PrefabType.cs
index a11f6aff6..7ec8a851c 100644
--- a/EXILED/Exiled.API/Enums/PrefabType.cs
+++ b/EXILED/Exiled.API/Enums/PrefabType.cs
@@ -16,10 +16,10 @@ public enum PrefabType
{
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
#pragma warning disable SA1602 // Enumeration items should be documented
- [Prefab(1883254029, "Player")]
+ [Prefab(3816198336, "Player")]
Player,
- [Prefab(2295511789, "EZ BreakableDoor")]
+ [Prefab(1883254029, "EZ BreakableDoor")]
EZBreakableDoor,
[Prefab(2295511789, "HCZ BreakableDoor")]
@@ -28,6 +28,42 @@ public enum PrefabType
[Prefab(3038351124, "LCZ BreakableDoor")]
LCZBreakableDoor,
+ [Prefab(400539138, "HCZ OneSided")]
+ HCZOneSided,
+
+ [Prefab(2060920286, "HCZ TwoSided")]
+ HCZTwoSided,
+
+ [Prefab(3343949480, "OpenHallway")]
+ HCZOpenHallway,
+
+ [Prefab(3999209566, "OpenHallway Construct A")]
+ HCZOpenHallway_Construct_A,
+
+ [Prefab(38976586, "OpenHallway Clutter A")]
+ HCZOpenHallway_Clutter_A,
+
+ [Prefab(1687661105, "OpenHallway Clutter B")]
+ HCZOpenHallway_Clutter_B,
+
+ [Prefab(147203050, "OpenHallway Clutter C")]
+ HCZOpenHallway_Clutter_C,
+
+ [Prefab(1102032353, "OpenHallway Clutter D")]
+ HCZOpenHallway_Clutter_D,
+
+ [Prefab(2490430134, "OpenHallway Clutter E")]
+ HCZOpenHallway_Clutter_E,
+
+ [Prefab(2673083832, "OpenHallway Clutter F")]
+ HCZOpenHallway_Clutter_F,
+
+ [Prefab(2536312960, "OpenHallway Clutter G")]
+ HCZOpenHallway_Clutter_G,
+
+ [Prefab(2176035362, "HCZ BulkDoor")]
+ HCZBulkDoor,
+
[Prefab(1704345398, "sportTargetPrefab")]
SportTarget,
@@ -46,6 +82,9 @@ public enum PrefabType
[Prefab(3956448839, "LightSourceToy")]
LightSourceToy,
+ [Prefab(712426663, "SpeakerToy")]
+ SpeakerToy,
+
[Prefab(2672653014, "RegularKeycardPickup")]
RegularKeycardPickup,
@@ -55,6 +94,9 @@ public enum PrefabType
[Prefab(248357067, "RadioPickup")]
RadioPickup,
+ [Prefab(1925130715, "FirearmPickup")]
+ FirearmPickup,
+
[Prefab(1925130715, "Com15Pickup")]
Com15Pickup,
@@ -181,6 +223,9 @@ public enum PrefabType
[Prefab(3532394942, "LanternPickup")]
LanternPickup,
+ [Prefab(4143962266, "SCP1344Pickup")]
+ Scp1344Pickup,
+
[Prefab(825024811, "Amnestic Cloud Hazard")]
AmnesticCloudHazard,
@@ -208,9 +253,18 @@ public enum PrefabType
[Prefab(3372339835, "Scp1576PedestalStructure Variant")]
Scp1576PedestalStructure,
+ [Prefab(2399831573, "AntiScp207PedestalStructure Variant")]
+ AntiScp207PedestalStructure,
+
+ [Prefab(1763950070, "Scp1344PedestalStructure Variant")]
+ Scp1344PedestalStructure,
+
[Prefab(2830750618, "LargeGunLockerStructure")]
LargeGunLockerStructure,
+ [Prefab(2372810204, "Experimental Weapon Locker")]
+ ExperimentalLockerStructure,
+
[Prefab(3352879624, "RifleRackStructure")]
RifleRackStructure,
@@ -273,5 +327,14 @@ public enum PrefabType
[Prefab(3721192489, "Scp3114_Ragdoll")]
Scp3114Ragdoll,
+
+ [Prefab(2588580243, "ElevatorChamber")]
+ ElevatorChamber,
+
+ [Prefab(1757973841, "ElevatorChamber_Gates")]
+ ElevatorChamber_Gates,
+
+ [Prefab(912031041, "ElevatorChamberNuke")]
+ ElevatorChamberNuke,
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/RespawnEffectType.cs b/EXILED/Exiled.API/Enums/RespawnEffectType.cs
index 672f26d40..672abb197 100644
--- a/EXILED/Exiled.API/Enums/RespawnEffectType.cs
+++ b/EXILED/Exiled.API/Enums/RespawnEffectType.cs
@@ -14,23 +14,16 @@ namespace Exiled.API.Enums
///
/// Layers game respawn effects.
///
- ///
- ///
- public enum RespawnEffectType : byte
+ public enum RespawnEffectType
{
- ///
- /// Plays the music to alive and .
- ///
- PlayChaosInsurgencyMusic = 0,
-
///
/// Summons the van.
///
- SummonChaosInsurgencyVan = 128,
+ SummonChaosInsurgencyVan,
///
/// Summons the NTF chopper.
///
- SummonNtfChopper = 129,
+ SummonNtfChopper,
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/RevolverChamberState.cs b/EXILED/Exiled.API/Enums/RevolverChamberState.cs
new file mode 100644
index 000000000..421f18587
--- /dev/null
+++ b/EXILED/Exiled.API/Enums/RevolverChamberState.cs
@@ -0,0 +1,33 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Enums
+{
+ using Exiled.API.Features.Items.FirearmModules.Primary;
+
+ ///
+ /// States for chamber in revolver cylindric magazine.
+ ///
+ ///
+ public enum RevolverChamberState
+ {
+ ///
+ /// State for empty chamber.
+ ///
+ Empty,
+
+ ///
+ /// State for chamber with a bullet.
+ ///
+ Live,
+
+ ///
+ /// State for discharged chamber.
+ ///
+ Discharged,
+ }
+}
diff --git a/EXILED/Exiled.API/Enums/RoomType.cs b/EXILED/Exiled.API/Enums/RoomType.cs
index 370bac2af..054029601 100644
--- a/EXILED/Exiled.API/Enums/RoomType.cs
+++ b/EXILED/Exiled.API/Enums/RoomType.cs
@@ -149,16 +149,6 @@ public enum RoomType
///
HczTesla,
- ///
- /// Heavy Containment Zone's Servers room.
- ///
- HczServers,
-
- ///
- /// Heavy Containment Zone's 3-way intersection.
- ///
- HczTCross,
-
///
/// Heavy Containment Zone's cruved hall.
///
@@ -210,15 +200,25 @@ public enum RoomType
EzCollapsedTunnel,
///
- /// Entrance Zone's straight hall with Dr.L's locked room.
+ /// Entrance Zone's straight hall with Dr.L's or Dr. Gear's locked room.
///
EzConference,
///
- /// Entrance Zone's straight hall
+ /// Entrance Zone's straight hall with Chef's locked room.
+ ///
+ EzChef,
+
+ ///
+ /// Entrance Zone's straight hall.
///
EzStraight,
+ ///
+ /// Entrance Zone's straight hall with a different placement of seasonal objects.
+ ///
+ EzStraightColumn,
+
///
/// Entrance Zone's Cafeteria Room.
///
@@ -250,7 +250,7 @@ public enum RoomType
Surface,
///
- /// Heavy Containment Zone's straight hall.
+ /// Heavy Containment Zone's straight hall with ceiling fan.
///
HczStraight,
@@ -260,14 +260,19 @@ public enum RoomType
EzTCross,
///
- /// Light Containment ZOne's SCP-330 room.
+ /// Light Containment Zone's SCP-330 room.
///
Lcz330,
///
/// Entrance Zone's straight hall before the entrance/heavy checkpoint.
///
- EzCheckpointHallway,
+ EzCheckpointHallwayA,
+
+ ///
+ /// Entrance Zone's straight hall before the entrance/heavy checkpoint.
+ ///
+ EzCheckpointHallwayB,
///
/// Heavy Containment Zone's test room's straight hall.
@@ -283,5 +288,45 @@ public enum RoomType
/// Heavy Containment Elevator Zone's System B room.
///
HczElevatorB,
+
+ ///
+ /// Heavy Containment Zone's cross room with waterfall.
+ ///
+ HczCrossRoomWater,
+
+ ///
+ /// Heavy Containment Zone's corner.
+ ///
+ HczCornerDeep,
+
+ ///
+ /// Heavy Containment Zone's 3-way intersection with storage crates obstructing the passage.
+ ///
+ HczIntersectionJunk,
+
+ ///
+ /// Heavy Containment Zone's 3-way intersection.
+ ///
+ HczIntersection,
+
+ ///
+ /// Heavy Containment Zone's straight hall with pipelines and sanitary door.
+ ///
+ HczStraightC,
+
+ ///
+ /// Heavy Containment Zone's straight hall with pipelines obstructing the passage.
+ ///
+ HczStraightPipeRoom,
+
+ ///
+ /// Heavy Containment Zone's straight hall.
+ ///
+ HczStraightVariant,
+
+ ///
+ /// Entrance Zone's straight hall with Dr.L's and conference room 9b locked room.
+ ///
+ EzSmallrooms,
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/SpawnLocationType.cs b/EXILED/Exiled.API/Enums/SpawnLocationType.cs
index 927542ffe..0cd2c6dde 100644
--- a/EXILED/Exiled.API/Enums/SpawnLocationType.cs
+++ b/EXILED/Exiled.API/Enums/SpawnLocationType.cs
@@ -142,16 +142,5 @@ public enum SpawnLocationType
/// Just inside the LCZ WC door.
///
InsideLczWc,
-
- ///
- /// Just inside the door at the bottom of the server's room.
- ///
- InsideServersBottom,
-
- ///
- /// Inside a random locker on the map.
- ///
- [Obsolete("Use LockerSpawnPoint instead")]
- InsideLocker,
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/SpawnableFaction.cs b/EXILED/Exiled.API/Enums/SpawnableFaction.cs
new file mode 100644
index 000000000..0903253fc
--- /dev/null
+++ b/EXILED/Exiled.API/Enums/SpawnableFaction.cs
@@ -0,0 +1,40 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Enums
+{
+ ///
+ /// All spawnable factions.
+ ///
+ public enum SpawnableFaction
+ {
+ ///
+ /// Represents no wave.
+ ///
+ None,
+
+ ///
+ /// Normal NTF wave.
+ ///
+ NtfWave,
+
+ ///
+ /// Normal Chaos wave.
+ ///
+ ChaosWave,
+
+ ///
+ /// Mini NTF wave.
+ ///
+ NtfMiniWave,
+
+ ///
+ /// Mini Chaos wave.
+ ///
+ ChaosMiniWave,
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Enums/ZoneType.cs b/EXILED/Exiled.API/Enums/ZoneType.cs
index 7e80190ba..382833528 100644
--- a/EXILED/Exiled.API/Enums/ZoneType.cs
+++ b/EXILED/Exiled.API/Enums/ZoneType.cs
@@ -51,9 +51,14 @@ public enum ZoneType
///
Surface = 8,
+ ///
+ /// The Pocket Dimension.
+ ///
+ Pocket = 16,
+
///
/// An unknown type of zone.
///
- Other = 16,
+ Other = 32,
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Exiled.API.csproj b/EXILED/Exiled.API/Exiled.API.csproj
index e0949b7ff..988d63157 100644
--- a/EXILED/Exiled.API/Exiled.API.csproj
+++ b/EXILED/Exiled.API/Exiled.API.csproj
@@ -32,11 +32,10 @@
+
-
- $(EXILED_REFERENCES)\UnityEngine.ParticleSystemModule.dll
-
+
diff --git a/EXILED/Exiled.API/Extensions/DamageTypeExtensions.cs b/EXILED/Exiled.API/Extensions/DamageTypeExtensions.cs
index aba321a8d..bb2a246f1 100644
--- a/EXILED/Exiled.API/Extensions/DamageTypeExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/DamageTypeExtensions.cs
@@ -49,6 +49,7 @@ public static class DamageTypeExtensions
{ DeathTranslations.MicroHID.Id, DamageType.MicroHid },
{ DeathTranslations.Hypothermia.Id, DamageType.Hypothermia },
{ DeathTranslations.MarshmallowMan.Id, DamageType.Marshmallow },
+ { DeathTranslations.Scp1344.Id, DamageType.SeveredEyes },
};
private static readonly Dictionary TranslationConversionInternal = new()
@@ -80,6 +81,7 @@ public static class DamageTypeExtensions
{ DeathTranslations.MicroHID, DamageType.MicroHid },
{ DeathTranslations.Hypothermia, DamageType.Hypothermia },
{ DeathTranslations.MarshmallowMan, DamageType.Marshmallow },
+ { DeathTranslations.Scp1344, DamageType.SeveredEyes },
};
private static readonly Dictionary ItemConversionInternal = new()
diff --git a/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs b/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs
index f602bcdae..0b977356e 100644
--- a/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs
+++ b/EXILED/Exiled.API/Extensions/EffectTypeExtension.cs
@@ -33,7 +33,7 @@ public static class EffectTypeExtension
{ EffectType.AmnesiaVision, typeof(AmnesiaVision) },
{ EffectType.Asphyxiated, typeof(Asphyxiated) },
{ EffectType.Bleeding, typeof(Bleeding) },
- { EffectType.Blinded, typeof(Blinded) },
+ { EffectType.Blinded, typeof(Blindness) },
{ EffectType.BodyshotReduction, typeof(BodyshotReduction) },
{ EffectType.Burned, typeof(Burned) },
{ EffectType.CardiacArrest, typeof(CardiacArrest) },
@@ -74,6 +74,10 @@ public static class EffectTypeExtension
{ EffectType.Ghostly, typeof(Ghostly) },
{ EffectType.FogControl, typeof(FogControl) },
{ EffectType.Slowness, typeof(Slowness) },
+ { EffectType.Scp1344, typeof(Scp1344) },
+ { EffectType.SeveredEyes, typeof(SeveredEyes) },
+ { EffectType.PitDeath, typeof(PitDeath) },
+ { EffectType.Blurred, typeof(Blurred) },
});
///
@@ -146,7 +150,7 @@ or EffectType.Corroding or EffectType.Decontaminating or EffectType.Hemorrhage o
/// The .
/// Whether the effect heals.
///
- public static bool IsHealing(this EffectType effect) => effect.TryGetType(out Type type) && typeof(IHealablePlayerEffect).IsAssignableFrom(type);
+ public static bool IsHealing(this EffectType effect) => effect.TryGetType(out Type type) && typeof(IHealableEffect).IsAssignableFrom(type);
///
/// Returns whether the provided is a negative effect.
diff --git a/EXILED/Exiled.API/Extensions/ItemExtensions.cs b/EXILED/Exiled.API/Extensions/ItemExtensions.cs
index c0fda94b1..3fc97516f 100644
--- a/EXILED/Exiled.API/Extensions/ItemExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/ItemExtensions.cs
@@ -18,6 +18,7 @@ namespace Exiled.API.Extensions
using InventorySystem;
using InventorySystem.Items;
using InventorySystem.Items.Firearms.Attachments;
+ using InventorySystem.Items.Firearms.Modules;
using InventorySystem.Items.Pickups;
using Structs;
@@ -123,12 +124,12 @@ public static T GetItemBase(this ItemType type)
///
/// The weapon that you want to get maximum of.
/// Returns the maximum.
- public static byte GetMaxAmmo(this FirearmType item)
+ public static int GetMaxAmmo(this FirearmType item)
{
if (!InventoryItemLoader.AvailableItems.TryGetValue(item.GetItemType(), out ItemBase itemBase) || itemBase is not InventorySystem.Items.Firearms.Firearm firearm)
return 0;
- return firearm.AmmoManagerModule.MaxAmmo;
+ return (firearm.Modules.FirstOrDefault(x => x is IAmmoContainerModule) as IAmmoContainerModule).AmmoMax;
}
///
@@ -323,5 +324,13 @@ public static uint GetBaseCode(this FirearmType type)
/// The to check.
/// of the specified .
public static ItemCategory GetCategory(this ItemType type) => GetItemBase(type).Category;
+
+ ///
+ /// Checks if the specified has the specified .
+ ///
+ /// Weapon to check.
+ /// Attachment to check.
+ /// true if weapon has the specified attachment. Otherwise, false.
+ public static bool HasAttachment(this Firearm firearm, AttachmentName attachment) => firearm.Attachments.FirstOrDefault(x => x.Name == attachment)?.IsEnabled ?? false;
}
}
diff --git a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
index f8c49599f..1e8187c09 100644
--- a/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/MirrorExtensions.cs
@@ -19,8 +19,6 @@ namespace Exiled.API.Extensions
using Features;
using Features.Pools;
- using InventorySystem.Items.Firearms;
-
using Mirror;
using PlayerRoles;
@@ -151,7 +149,7 @@ public static ReadOnlyDictionary RpcFullNames
/// Plays a beep sound that only the target can hear.
///
/// Target to play sound to.
- public static void PlayBeepSound(this Player player) => SendFakeTargetRpc(player, ReferenceHub.HostHub.networkIdentity, typeof(AmbientSoundPlayer), nameof(AmbientSoundPlayer.RpcPlaySound), 7);
+ public static void PlayBeepSound(this Player player) => SendFakeTargetRpc(player, ReferenceHub._hostHub.networkIdentity, typeof(AmbientSoundPlayer), nameof(AmbientSoundPlayer.RpcPlaySound), 7);
///
/// Set on the player that only the can see.
@@ -171,6 +169,8 @@ public static ReadOnlyDictionary RpcFullNames
/// GunAudioMessage's audioClipId to set (default = 0).
public static void PlayGunSound(this Player player, Vector3 position, ItemType itemType, byte volume, byte audioClipId = 0)
{
+ // TODO: Not finish
+ /*
GunAudioMessage message = new()
{
Weapon = itemType,
@@ -180,7 +180,7 @@ public static void PlayGunSound(this Player player, Vector3 position, ItemType i
ShooterPosition = new RelativePosition(position),
};
- player.Connection.Send(message);
+ player.Connection.Send(message);*/
}
///
@@ -222,17 +222,6 @@ public static void SetName(this Player target, Player player, string name)
target.SendFakeSyncVar(player.NetworkIdentity, typeof(NicknameSync), nameof(NicknameSync.Network_displayName), name);
}
- ///
- /// Sets of a that only the player can see.
- ///
- /// Room to modify.
- /// Only this player can see room color.
- /// Light intensity multiplier to set.
- [Obsolete("This features has been remove by NW", true)]
- public static void SetRoomLightIntensityForTargetOnly(this Room room, Player target, float multiplier)
- {
- }
-
///
/// Change character model for appearance.
/// It will continue until 's changes.
@@ -462,38 +451,6 @@ public static void ScaleNetworkIdentityObject(this NetworkIdentity identity, Vec
}
}
- ///
- /// Send fake values to client's .
- ///
- /// Target to send.
- /// of object that owns .
- /// 's type.
- /// Property name starting with Network.
- /// Value of send to target.
- [Obsolete("Use overload with type-template instead.")]
- public static void SendFakeSyncVar(this Player target, NetworkIdentity behaviorOwner, Type targetType, string propertyName, object value)
- {
- if (!target.IsConnected)
- return;
-
- NetworkWriterPooled writer = NetworkWriterPool.Get();
- NetworkWriterPooled writer2 = NetworkWriterPool.Get();
- MakeCustomSyncWriter(behaviorOwner, targetType, null, CustomSyncVarGenerator, writer, writer2);
- target.Connection.Send(new EntityStateMessage
- {
- netId = behaviorOwner.netId,
- payload = writer.ToArraySegment(),
- });
-
- NetworkWriterPool.Return(writer);
- NetworkWriterPool.Return(writer2);
- void CustomSyncVarGenerator(NetworkWriter targetWriter)
- {
- targetWriter.WriteULong(SyncVarDirtyBits[$"{targetType.Name}.{propertyName}"]);
- WriterExtensions[value.GetType()]?.Invoke(null, new object[2] { targetWriter, value });
- }
- }
-
///
/// Send fake values to client's .
///
diff --git a/EXILED/Exiled.API/Extensions/RoleExtensions.cs b/EXILED/Exiled.API/Extensions/RoleExtensions.cs
index c36592500..369910654 100644
--- a/EXILED/Exiled.API/Extensions/RoleExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/RoleExtensions.cs
@@ -12,12 +12,14 @@ namespace Exiled.API.Extensions
using System.Linq;
using Enums;
- using Exiled.API.Features.Spawn;
+ using Features.Spawn;
+ using Footprinting;
using InventorySystem;
using InventorySystem.Configs;
using PlayerRoles;
using PlayerRoles.FirstPersonControl;
-
+ using Respawning;
+ using Respawning.Waves;
using UnityEngine;
using Team = PlayerRoles.Team;
@@ -27,6 +29,22 @@ namespace Exiled.API.Extensions
///
public static class RoleExtensions
{
+ ///
+ /// Compares LifeIdentifier.
+ ///
+ /// The footprint to compare.
+ /// The other footprint.
+ /// If LifeIdentifier is the same (same role).
+ public static bool CompareLife(this Footprint footprint, Footprint other) => footprint.LifeIdentifier == other.LifeIdentifier;
+
+ ///
+ /// Compares LifeIdentifier.
+ ///
+ /// The footprint to compare.
+ /// The hub to compare to.
+ /// If LifeIdentifier is the same (same role).
+ public static bool CompareLife(this Footprint footprint, ReferenceHub other) => footprint.LifeIdentifier == other.roleManager.CurrentRole.UniqueLifeIdentifier;
+
///
/// Gets a role's.
///
@@ -210,5 +228,56 @@ public static Dictionary GetStartingAmmo(this RoleTypeId roleT
return info.Ammo.ToDictionary(kvp => kvp.Key.GetAmmoType(), kvp => kvp.Value);
}
+
+ ///
+ /// Gets the of a .
+ ///
+ /// A instance.
+ /// associated with the wave.
+ public static SpawnableFaction GetSpawnableFaction(this SpawnableWaveBase waveBase) => waveBase switch
+ {
+ NtfSpawnWave => SpawnableFaction.NtfWave,
+ NtfMiniWave => SpawnableFaction.NtfMiniWave,
+ ChaosSpawnWave => SpawnableFaction.ChaosWave,
+ ChaosMiniWave => SpawnableFaction.ChaosMiniWave,
+ _ => SpawnableFaction.None
+ };
+
+ ///
+ /// Gets the associated with the provided .
+ ///
+ /// A member of the enum.
+ /// associated with the provided .
+ public static Faction GetFaction(this SpawnableFaction spawnableFaction) => spawnableFaction switch
+ {
+ SpawnableFaction.ChaosWave or SpawnableFaction.ChaosMiniWave => Faction.FoundationEnemy,
+ SpawnableFaction.NtfWave or SpawnableFaction.NtfMiniWave => Faction.FoundationStaff,
+ _ => Faction.Unclassified,
+ };
+
+ ///
+ /// Tries to get the associated with the provided and .
+ ///
+ /// A member of the enum.
+ /// The to return.
+ /// A determining whether to get a normal spawn wave or a mini one.
+ /// associated with the provided influenced by .
+ public static bool TryGetSpawnableFaction(this Faction faction, out SpawnableFaction spawnableFaction, bool mini = false)
+ {
+ switch (faction)
+ {
+ case Faction.FoundationStaff:
+ spawnableFaction = mini ? SpawnableFaction.NtfMiniWave : SpawnableFaction.NtfWave;
+ break;
+ case Faction.FoundationEnemy:
+ spawnableFaction = mini ? SpawnableFaction.ChaosMiniWave : SpawnableFaction.ChaosWave;
+ break;
+ default:
+ spawnableFaction = SpawnableFaction.None;
+ return false;
+ }
+
+ return true;
+ }
}
}
diff --git a/EXILED/Exiled.API/Extensions/SpawnExtensions.cs b/EXILED/Exiled.API/Extensions/SpawnExtensions.cs
index 2eed0d7ea..5c1c31f89 100644
--- a/EXILED/Exiled.API/Extensions/SpawnExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/SpawnExtensions.cs
@@ -23,7 +23,6 @@ public static class SpawnExtensions
///
public static readonly SpawnLocationType[] ReversedLocations =
{
- SpawnLocationType.InsideServersBottom,
SpawnLocationType.InsideHczArmory,
SpawnLocationType.Inside079First,
SpawnLocationType.InsideHidRight,
@@ -103,7 +102,6 @@ public static Vector3 GetPosition(this SpawnLocationType location)
SpawnLocationType.InsideSurfaceNuke => "SURFACE_NUKE",
SpawnLocationType.Inside079Secondary => "079_SECOND",
SpawnLocationType.Inside173Connector => "173_CONNECTOR",
- SpawnLocationType.InsideServersBottom => "SERVERS_BOTTOM",
SpawnLocationType.InsideEscapePrimary => "ESCAPE_PRIMARY",
SpawnLocationType.InsideEscapeSecondary => "ESCAPE_SECONDARY",
_ => default,
diff --git a/EXILED/Exiled.API/Extensions/StringExtensions.cs b/EXILED/Exiled.API/Extensions/StringExtensions.cs
index 2d0f9a0d7..1cc8dc7c3 100644
--- a/EXILED/Exiled.API/Extensions/StringExtensions.cs
+++ b/EXILED/Exiled.API/Extensions/StringExtensions.cs
@@ -119,10 +119,10 @@ public static string ToString(this IEnumerable enumerable, bool showIndex
/// Name without brackets.
public static string RemoveBracketsOnEndOfName(this string name)
{
- int bracketStart = name.IndexOf('(') - 1;
+ int bracketStart = name.IndexOf('(');
if (bracketStart > 0)
- name = name.Remove(bracketStart, name.Length - bracketStart);
+ name = name.Remove(bracketStart, name.Length - bracketStart).TrimEnd();
return name;
}
diff --git a/EXILED/Exiled.API/Features/BanManager.cs b/EXILED/Exiled.API/Features/BanManager.cs
new file mode 100644
index 000000000..219c272eb
--- /dev/null
+++ b/EXILED/Exiled.API/Features/BanManager.cs
@@ -0,0 +1,58 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features
+{
+ using System;
+
+ ///
+ /// Useful class to manage player bans.
+ ///
+ public static class BanManager
+ {
+ ///
+ /// Bans an offline player.
+ ///
+ /// Type of the ban (UserID/IP).
+ /// The UserID or IP address to ban.
+ /// The ban reason.
+ /// A representing the duration.
+ /// The Nickname of the ban issuer.
+ /// Whether the ban was successful.
+ public static bool OfflineBanPlayer(BanHandler.BanType banType, string id, string reason, TimeSpan duration, string issuer = "SERVER CONSOLE") => OfflineBanPlayer(banType, id, reason, duration.TotalSeconds, issuer);
+
+ ///
+ /// Bans an offline player.
+ ///
+ /// Type of the ban (UserID/IP).
+ /// The UserID or IP address to ban.
+ /// The ban reason.
+ /// Duration in seconds.
+ /// The Nickname of the ban issuer.
+ /// Whether the ban was successful.
+ public static bool OfflineBanPlayer(BanHandler.BanType banType, string id, string reason, double duration, string issuer = "SERVER CONSOLE")
+ {
+ BanDetails details = new()
+ {
+ OriginalName = "Unknown - offline ban",
+ Id = id,
+ IssuanceTime = DateTime.UtcNow.Ticks,
+ Expires = DateTime.UtcNow.AddSeconds(duration).Ticks,
+ Reason = reason,
+ Issuer = issuer,
+ };
+ return BanHandler.IssueBan(details, banType);
+ }
+
+ ///
+ /// Unbans a player.
+ ///
+ /// Type of the ban (UserID/IP).
+ /// The UserID or IP address to ban.\
+ public static void UnbanPlayer(BanHandler.BanType banType, string id) => BanHandler.RemoveBan(id, banType);
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Camera.cs b/EXILED/Exiled.API/Features/Camera.cs
index 5db5dd28f..6c7248573 100644
--- a/EXILED/Exiled.API/Features/Camera.cs
+++ b/EXILED/Exiled.API/Features/Camera.cs
@@ -77,9 +77,6 @@ public class Camera : IWrapper, IWorldSpace
["HCZ ELEV SYS B"] = CameraType.HczElevSysB,
["HCZ HALLWAY"] = CameraType.HczHallway,
["HCZ THREE-WAY"] = CameraType.HczThreeWay,
- ["SERVERS BOTTOM"] = CameraType.HczServersBottom,
- ["SERVERS STAIRS"] = CameraType.HczServersStairs,
- ["SERVERS TOP"] = CameraType.HczServersTop,
["TESLA GATE"] = CameraType.HczTeslaGate,
["TESTROOM BRIDGE"] = CameraType.HczTestroomBridge,
["TESTROOM MAIN"] = CameraType.HczTestroomMain,
@@ -124,6 +121,21 @@ public class Camera : IWrapper, IWorldSpace
["SURFACE AIRLOCK"] = CameraType.SurfaceAirlock,
["SURFACE BRIDGE"] = CameraType.SurfaceBridge,
["TUNNEL ENTRANCE"] = CameraType.TunnelEntrance,
+
+ // new
+ ["JUNK MAIN"] = CameraType.HczJunkMain,
+ ["JUNK HALLWAY"] = CameraType.HczJunkHallway,
+ ["CORNER DEEP"] = CameraType.HczCornerDeep,
+ ["DSS-08"] = CameraType.HczDSS08,
+ ["MICROHID STAIRS"] = CameraType.HczMicroHIDStairs,
+ ["PIPES HALLWAY"] = CameraType.HczPipesHallway,
+ ["PIPES MAIN"] = CameraType.HczPipesMain,
+ ["WARHEAD STARBOARD ELEVATOR"] = CameraType.HczWarheadStarboardElevator,
+ ["MICROHID MAIN"] = CameraType.HczMicroHIDMain,
+ ["MICROHID LAB"] = CameraType.HczMicroHIDLab,
+ ["WARHEAD TOP ELEVATORS"] = CameraType.HczWarheadTopElevators,
+ ["WARHEAD CONNECTOR"] = CameraType.HczWarheadConnector,
+ ["WARHEAD PORT ELEVATOR"] = CameraType.HczWarheadPortElevator,
};
private Room room;
@@ -137,9 +149,9 @@ internal Camera(Scp079Camera camera079)
Base = camera079;
Camera079ToCamera.Add(camera079, this);
Type = GetCameraType();
-#if Debug
+#if DEBUG
if (Type is CameraType.Unknown)
- Log.Error($"[CAMERATYPE UNKNOWN] {this}");
+ Log.Error($"[CAMERATYPE UNKNOWN] {this} BASE = {Base}");
#endif
}
diff --git a/EXILED/Exiled.API/Features/Components/CollisionHandler.cs b/EXILED/Exiled.API/Features/Components/CollisionHandler.cs
index b98e7bb5a..54d117fe4 100644
--- a/EXILED/Exiled.API/Features/Components/CollisionHandler.cs
+++ b/EXILED/Exiled.API/Features/Components/CollisionHandler.cs
@@ -56,9 +56,11 @@ private void OnCollisionEnter(Collision collision)
Log.Error("Grenade is null!");
if (collision is null)
Log.Error("wat");
- if (collision.gameObject == null)
+ if (!collision.collider)
+ Log.Error("water");
+ if (collision.collider.gameObject == null)
Log.Error("pepehm");
- if (collision.gameObject == Owner || collision.gameObject.TryGetComponent(out _))
+ if (collision.collider.gameObject == Owner || collision.collider.gameObject.TryGetComponent(out _))
return;
Grenade.TargetTime = 0.1f;
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/ButtonSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/ButtonSetting.cs
new file mode 100644
index 000000000..5144f81ff
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/ButtonSetting.cs
@@ -0,0 +1,88 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Core.UserSettings
+{
+ using System;
+ using System.Diagnostics;
+
+ using Exiled.API.Interfaces;
+ using global::UserSettings.ServerSpecific;
+
+ ///
+ /// Represents a button setting.
+ ///
+ public class ButtonSetting : SettingBase, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ButtonSetting(int id, string label, string buttonText, float holdTime = 0.0f, string hintDescription = null, HeaderSetting header = null, Action onChanged = null)
+ : base(new SSButton(id, label, buttonText, holdTime, hintDescription), header, onChanged)
+ {
+ Base = (SSButton)base.Base;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A instance.
+ internal ButtonSetting(SSButton settingBase)
+ : base(settingBase)
+ {
+ Base = settingBase;
+
+ if (OriginalDefinition.Is(out ButtonSetting setting))
+ {
+ Text = setting.Text;
+ HoldTime = setting.HoldTime;
+ }
+ }
+
+ ///
+ public new SSButton Base { get; }
+
+ ///
+ /// Gets the last press time.
+ ///
+ public Stopwatch LastPress => Base.SyncLastPress;
+
+ ///
+ /// Gets or sets the button text.
+ ///
+ public string Text
+ {
+ get => Base.ButtonText;
+ set => Base.ButtonText = value;
+ }
+
+ ///
+ /// Gets or sets the hold time in seconds.
+ ///
+ public float HoldTime
+ {
+ get => Base.HoldTimeSeconds;
+ set => Base.HoldTimeSeconds = value;
+ }
+
+ ///
+ /// Returns a representation of this .
+ ///
+ /// A string in human-readable format.
+ public override string ToString()
+ {
+ return base.ToString() + $" ={Text}= -{HoldTime}- /{LastPress}/";
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/DropdownSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/DropdownSetting.cs
new file mode 100644
index 000000000..f03e6c070
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/DropdownSetting.cs
@@ -0,0 +1,128 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Core.UserSettings
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ using Exiled.API.Interfaces;
+ using global::UserSettings.ServerSpecific;
+
+ ///
+ /// Represents a dropdown setting.
+ ///
+ public class DropdownSetting : SettingBase, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public DropdownSetting(
+ int id,
+ string label,
+ IEnumerable options,
+ int defaultOptionIndex = 0,
+ SSDropdownSetting.DropdownEntryType dropdownEntryType = SSDropdownSetting.DropdownEntryType.Regular,
+ string hintDescription = null,
+ HeaderSetting header = null,
+ Action onChanged = null)
+ : base(new SSDropdownSetting(id, label, options.ToArray(), defaultOptionIndex, dropdownEntryType, hintDescription), header, onChanged)
+ {
+ Base = (SSDropdownSetting)base.Base;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A instance.
+ internal DropdownSetting(SSDropdownSetting settingBase)
+ : base(settingBase)
+ {
+ Base = settingBase;
+
+ if (OriginalDefinition.Is(out DropdownSetting dropdown))
+ {
+ Options = dropdown.Options;
+ }
+ }
+
+ ///
+ public new SSDropdownSetting Base { get; }
+
+ ///
+ /// Gets or sets a collection of all options in dropdown.
+ ///
+ public IEnumerable Options
+ {
+ get => Base.Options;
+ set => Base.Options = value.ToArray();
+ }
+
+ ///
+ /// Gets or sets an index of default option.
+ ///
+ public int DefaultOptionIndex
+ {
+ get => Base.DefaultOptionIndex;
+ set => Base.DefaultOptionIndex = value;
+ }
+
+ ///
+ /// Gets or sets a default option.
+ ///
+ public string DefaultOption
+ {
+ get => Base.Options[DefaultOptionIndex];
+ set => DefaultOptionIndex = Array.IndexOf(Base.Options, value);
+ }
+
+ ///
+ /// Gets or sets a type of dropdown.
+ ///
+ public SSDropdownSetting.DropdownEntryType DropdownType
+ {
+ get => Base.EntryType;
+ set => Base.EntryType = value;
+ }
+
+ ///
+ /// Gets or sets an index of selected option.
+ ///
+ public int SelectedIndex
+ {
+ get => Base.SyncSelectionIndexRaw;
+ set => Base.SyncSelectionIndexRaw = value;
+ }
+
+ ///
+ /// Gets or sets a selected option.
+ ///
+ public string SelectedOption
+ {
+ get => Base.SyncSelectionText;
+ set => SelectedIndex = Array.IndexOf(Base.Options, value);
+ }
+
+ ///
+ /// Gets a string representation of this .
+ ///
+ /// A string in human-readable format.
+ public override string ToString()
+ {
+ return base.ToString() + $" ={DefaultOptionIndex}= -{SelectedIndex}- /{string.Join(";", Options)}/";
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/HeaderSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/HeaderSetting.cs
new file mode 100644
index 000000000..78fd4ee32
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/HeaderSetting.cs
@@ -0,0 +1,64 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Core.UserSettings
+{
+ using Exiled.API.Interfaces;
+ using global::UserSettings.ServerSpecific;
+
+ ///
+ /// Represents a header setting.
+ ///
+ public class HeaderSetting : SettingBase, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ public HeaderSetting(string name, string hintDescription = "", bool paddling = false)
+ : this(new SSGroupHeader(name, paddling, hintDescription))
+ {
+ Base = (SSGroupHeader)base.Base;
+
+ Base.SetId(null, name);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A instance.
+ internal HeaderSetting(SSGroupHeader settingBase)
+ : base(settingBase)
+ {
+ Base = settingBase;
+ Base.SetId(null, settingBase.Label);
+ }
+
+ ///
+ public new SSGroupHeader Base { get; }
+
+ ///
+ /// Gets or sets a value indicating whether to reduce padding.
+ ///
+ public bool ReducedPaddling
+ {
+ get => Base.ReducedPadding;
+ set => Base.ReducedPadding = value;
+ }
+
+ ///
+ /// Returns a representation of this .
+ ///
+ /// A string in human-readable format.
+ public override string ToString()
+ {
+ return base.ToString() + $" /{ReducedPaddling}/";
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/KeybindSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/KeybindSetting.cs
new file mode 100644
index 000000000..cfb6b3bbc
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/KeybindSetting.cs
@@ -0,0 +1,82 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Core.UserSettings
+{
+ using System;
+
+ using Exiled.API.Interfaces;
+ using global::UserSettings.ServerSpecific;
+ using UnityEngine;
+
+ ///
+ /// Represents a keybind setting.
+ ///
+ public class KeybindSetting : SettingBase, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public KeybindSetting(int id, string label, KeyCode suggested, bool preventInteractionOnGUI = false, string hintDescription = "", HeaderSetting header = null, Action onChanged = null)
+ : base(new SSKeybindSetting(id, label, suggested, preventInteractionOnGUI, hintDescription), header, onChanged)
+ {
+ Base = (SSKeybindSetting)base.Base;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A instance.
+ internal KeybindSetting(SSKeybindSetting settingBase)
+ : base(settingBase)
+ {
+ Base = settingBase;
+ }
+
+ ///
+ public new SSKeybindSetting Base { get; }
+
+ ///
+ /// Gets a value indicating whether the key is pressed.
+ ///
+ public bool IsPressed => Base.SyncIsPressed;
+
+ ///
+ /// Gets or sets a value indicating whether the interaction is prevented while player is in RA, Settings etc.
+ ///
+ public bool PreventInteractionOnGUI
+ {
+ get => Base.PreventInteractionOnGUI;
+ set => Base.PreventInteractionOnGUI = value;
+ }
+
+ ///
+ /// Gets or sets the assigned key.
+ ///
+ public KeyCode KeyCode
+ {
+ get => Base.SuggestedKey;
+ set => Base.SuggestedKey = value;
+ }
+
+ ///
+ /// Returns a representation of this .
+ ///
+ /// A string in human-readable format.
+ public override string ToString()
+ {
+ return base.ToString() + $" /{IsPressed}/ *{KeyCode}* +{PreventInteractionOnGUI}+";
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs
new file mode 100644
index 000000000..6a9e65215
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/SettingBase.cs
@@ -0,0 +1,340 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Core.UserSettings
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using System.Linq;
+
+ using Exiled.API.Features.Pools;
+ using Exiled.API.Interfaces;
+ using global::UserSettings.ServerSpecific;
+
+ ///
+ /// A base class for all Server Specific Settings.
+ ///
+ public class SettingBase : TypeCastObject, IWrapper
+ {
+ ///
+ /// A that contains that were received by a players.
+ ///
+ internal static readonly Dictionary> ReceivedSettings = new();
+
+ ///
+ /// A collection that contains all settings that were sent to clients.
+ ///
+ internal static readonly List Settings = new();
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A instance.
+ ///
+ ///
+ internal SettingBase(ServerSpecificSettingBase settingBase, HeaderSetting header, Action onChanged)
+ {
+ Base = settingBase;
+
+ Header = header;
+ OnChanged = onChanged;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ internal SettingBase(ServerSpecificSettingBase settingBase)
+ {
+ Base = settingBase;
+
+ if (OriginalDefinition != null)
+ {
+ Header = OriginalDefinition.Header;
+ OnChanged = OriginalDefinition.OnChanged;
+ Label = OriginalDefinition.Label;
+ HintDescription = OriginalDefinition.HintDescription;
+ }
+ }
+
+ ///
+ /// Gets the list of all synced settings.
+ ///
+ public static IReadOnlyDictionary> SyncedList
+ => new ReadOnlyDictionary>(ReceivedSettings.ToDictionary(x => x.Key, x => x.Value.AsReadOnly()));
+
+ ///
+ /// Gets the list of settings that were used as a prefabs.
+ ///
+ public static IReadOnlyCollection List => Settings;
+
+ ///
+ /// Gets or sets the predicate for syncing this setting when a player joins.
+ ///
+ public static Predicate SyncOnJoin { get; set; }
+
+ ///
+ public ServerSpecificSettingBase Base { get; }
+
+ ///
+ /// Gets or sets the id of this setting.
+ ///
+ public int Id
+ {
+ get => Base.SettingId;
+ set => Base.SetId(value, string.Empty);
+ }
+
+ ///
+ /// Gets or sets the label of this setting.
+ ///
+ public string Label
+ {
+ get => Base.Label;
+ set => Base.Label = value;
+ }
+
+ ///
+ /// Gets or sets the description of this setting.
+ ///
+ public string HintDescription
+ {
+ get => Base.HintDescription;
+ set => Base.HintDescription = value;
+ }
+
+ ///
+ /// Gets the response mode of this setting.
+ ///
+ public ServerSpecificSettingBase.UserResponseMode ResponseMode => Base.ResponseMode;
+
+ ///
+ /// Gets the setting that was sent to players.
+ ///
+ /// Can be null if this is a prefab.
+ public SettingBase OriginalDefinition => Settings.Find(x => x.Id == Id);
+
+ ///
+ /// Gets or sets the header of this setting.
+ ///
+ /// Can be null.
+ public HeaderSetting Header { get; set; }
+
+ ///
+ /// Gets or sets the action to be executed when this setting is changed.
+ ///
+ public Action OnChanged { get; set; }
+
+ ///
+ /// Tries to get the setting with the specified id.
+ ///
+ /// Player who has received the setting.
+ /// Id of the setting.
+ /// A instance if found. Otherwise, null.
+ /// Type of the setting.
+ /// true if the setting was found, false otherwise.
+ public static bool TryGetSetting(Player player, int id, out T setting)
+ where T : SettingBase
+ {
+ setting = null;
+
+ if (!ReceivedSettings.TryGetValue(player, out List list))
+ return false;
+
+ setting = (T)list.FirstOrDefault(x => x.Id == id);
+ return setting != null;
+ }
+
+ ///
+ /// Tries to get the setting with the specified id.
+ ///
+ /// Player who has received the setting.
+ /// Id of the setting.
+ /// A instance if found. Otherwise, null.
+ /// true if the setting was found, false otherwise.
+ public static bool TryGetSetting(Player player, int id, out SettingBase setting) => TryGetSetting(player, id, out setting);
+
+ ///
+ /// Creates a new instance of this setting.
+ ///
+ /// A instance.
+ /// A new instance of this setting.
+ ///
+ /// This method is used only to create a new instance of from an existing instance.
+ /// New setting won't be synced with players.
+ ///
+ public static SettingBase Create(ServerSpecificSettingBase settingBase) => settingBase switch
+ {
+ SSButton button => new ButtonSetting(button),
+ SSDropdownSetting dropdownSetting => new DropdownSetting(dropdownSetting),
+ SSTextArea textArea => new TextInputSetting(textArea),
+ SSGroupHeader header => new HeaderSetting(header),
+ SSKeybindSetting keybindSetting => new KeybindSetting(keybindSetting),
+ SSTwoButtonsSetting twoButtonsSetting => new TwoButtonsSetting(twoButtonsSetting),
+ _ => new SettingBase(settingBase)
+ };
+
+ ///
+ /// Creates a new instance of this setting.
+ ///
+ /// A instance.
+ /// Type of the setting.
+ /// A new instance of this setting.
+ ///
+ /// This method is used only to create a new instance of from an existing instance.
+ /// New setting won't be synced with players.
+ ///
+ public static T Create(ServerSpecificSettingBase settingBase)
+ where T : SettingBase => (T)Create(settingBase);
+
+ ///
+ /// Syncs setting with all players.
+ ///
+ public static void SendToAll() => ServerSpecificSettingsSync.SendToAll();
+
+ ///
+ /// Syncs setting with all players according to the specified predicate.
+ ///
+ /// A requirement to meet.
+ public static void SendToAll(Func predicate)
+ {
+ foreach (Player player in Player.List)
+ {
+ if (predicate(player))
+ SendToPlayer(player);
+ }
+ }
+
+ ///
+ /// Syncs setting with the specified target.
+ ///
+ /// Target player.
+ public static void SendToPlayer(Player player) => ServerSpecificSettingsSync.SendToPlayer(player.ReferenceHub);
+
+ ///
+ /// Registers all settings from the specified collection.
+ ///
+ /// A collection of settings to register.
+ /// A requirement to meet when sending settings to players.
+ /// A of instances that were successfully registered.
+ /// This method is used to sync new settings with players.
+ public static IEnumerable Register(IEnumerable settings, Func predicate = null)
+ {
+ List list = ListPool.Pool.Get(settings);
+ List list2 = new(list.Count);
+
+ while (list.Exists(x => x.Header != null))
+ {
+ SettingBase setting = list.Find(x => x.Header != null);
+ SettingBase header = list.Find(x => x == setting.Header);
+ List range = list.FindAll(x => x.Header?.Id == setting.Header.Id);
+
+ list2.Add(header);
+ list2.AddRange(range);
+
+ list.Remove(header);
+ list.RemoveAll(x => x.Header?.Id == setting.Header.Id);
+ }
+
+ list2.AddRange(list);
+
+ List list3 = ListPool.Pool.Get(ServerSpecificSettingsSync.DefinedSettings ?? Array.Empty());
+ list3.AddRange(list2.Select(x => x.Base));
+
+ ServerSpecificSettingsSync.DefinedSettings = list3.ToArray();
+ Settings.AddRange(list2);
+
+ if (predicate == null)
+ SendToAll();
+ else
+ SendToAll(predicate);
+
+ ListPool.Pool.Return(list3);
+ ListPool.Pool.Return(list);
+
+ return list2;
+ }
+
+ ///
+ /// Removes settings from players.
+ ///
+ /// Determines which players will receive this update.
+ /// Settings to remove. If null, all settings will be removed.
+ /// A of instances that were successfully removed.
+ /// This method is used to unsync settings from players. Using it with provides an opportunity to update synced settings.
+ public static IEnumerable Unregister(Func predicate = null, IEnumerable settings = null)
+ {
+ List list = ListPool.Pool.Get(ServerSpecificSettingsSync.DefinedSettings);
+ List list2 = new((settings ?? Settings).Where(setting => list.Remove(setting.Base)));
+
+ ServerSpecificSettingsSync.DefinedSettings = list.ToArray();
+
+ if (predicate == null)
+ SendToAll();
+ else
+ SendToAll(predicate);
+
+ ListPool.Pool.Return(list);
+
+ return list2;
+ }
+
+ ///
+ /// Returns a string representation of this .
+ ///
+ /// A string in human-readable format.
+ public override string ToString()
+ {
+ return $"{Id} ({Label}) [{HintDescription}] {{{ResponseMode}}} ^{Header}^";
+ }
+
+ ///
+ /// Internal method that fires when a setting is updated.
+ ///
+ /// that has updates the setting.
+ /// A new updated setting.
+ internal static void OnSettingUpdated(ReferenceHub hub, ServerSpecificSettingBase settingBase)
+ {
+ if (!Player.TryGet(hub, out Player player) || hub.IsHost)
+ return;
+
+ SettingBase setting;
+
+ if (!ReceivedSettings.TryGetValue(player, out List list))
+ {
+ setting = Create(settingBase);
+ ReceivedSettings.Add(player, new() { setting });
+
+ if (setting.Is(out ButtonSetting _))
+ setting.OriginalDefinition.OnChanged?.Invoke(player, setting);
+
+ return;
+ }
+
+ if (!list.Exists(x => x.Id == settingBase.SettingId))
+ {
+ setting = Create(settingBase);
+ list.Add(setting);
+
+ if (setting.Is(out ButtonSetting _))
+ setting.OriginalDefinition.OnChanged?.Invoke(player, setting);
+
+ return;
+ }
+
+ setting = list.Find(x => x.Id == settingBase.SettingId);
+
+ if (setting.OriginalDefinition == null)
+ {
+ Settings.Add(Create(settingBase.OriginalDefinition));
+ }
+
+ setting.OriginalDefinition?.OnChanged?.Invoke(player, setting);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/TextInputSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/TextInputSetting.cs
new file mode 100644
index 000000000..69c7875ad
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/TextInputSetting.cs
@@ -0,0 +1,93 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Core.UserSettings
+{
+ using System;
+
+ using Exiled.API.Interfaces;
+ using global::UserSettings.ServerSpecific;
+ using TMPro;
+
+ ///
+ /// Represents a text input setting.
+ ///
+ public class TextInputSetting : SettingBase, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public TextInputSetting(
+ int id,
+ string label,
+ SSTextArea.FoldoutMode foldoutMode = SSTextArea.FoldoutMode.NotCollapsable,
+ TextAlignmentOptions alignment = TextAlignmentOptions.TopLeft,
+ string hintDescription = null,
+ HeaderSetting header = null,
+ Action onChanged = null)
+ : base(new SSTextArea(id, label, foldoutMode, hintDescription, alignment), header, onChanged)
+ {
+ Base = (SSTextArea)base.Base;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A instance.
+ internal TextInputSetting(SSTextArea settingBase)
+ : base(settingBase)
+ {
+ Base = settingBase;
+ }
+
+ ///
+ public new SSTextArea Base { get; }
+
+ ///
+ /// Gets or sets the text for the setting.
+ ///
+ public new string Label
+ {
+ get => Base.Label;
+ set => Base.SendTextUpdate(value);
+ }
+
+ ///
+ /// Gets or sets the foldout mode.
+ ///
+ public SSTextArea.FoldoutMode FoldoutMode
+ {
+ get => Base.Foldout;
+ set => Base.Foldout = value;
+ }
+
+ ///
+ /// Gets or sets the text alignment options.
+ ///
+ public TextAlignmentOptions Alignment
+ {
+ get => Base.AlignmentOptions;
+ set => Base.AlignmentOptions = value;
+ }
+
+ ///
+ /// Returns a representation of this .
+ ///
+ /// A string in human-readable format.
+ public override string ToString()
+ {
+ return base.ToString() + $" /{FoldoutMode}/ *{Alignment}*";
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Core/UserSettings/TwoButtonsSetting.cs b/EXILED/Exiled.API/Features/Core/UserSettings/TwoButtonsSetting.cs
new file mode 100644
index 000000000..4b2f03a0c
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Core/UserSettings/TwoButtonsSetting.cs
@@ -0,0 +1,110 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Core.UserSettings
+{
+ using System;
+
+ using Exiled.API.Interfaces;
+ using global::UserSettings.ServerSpecific;
+
+ ///
+ /// Represents a two-button setting.
+ ///
+ public class TwoButtonsSetting : SettingBase, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public TwoButtonsSetting(int id, string label, string firstOption, string secondOption, bool defaultIsSecond = false, string hintDescription = "", HeaderSetting header = null, Action onChanged = null)
+ : base(new SSTwoButtonsSetting(id, label, firstOption, secondOption, defaultIsSecond, hintDescription), header, onChanged)
+ {
+ Base = (SSTwoButtonsSetting)base.Base;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A instance.
+ internal TwoButtonsSetting(SSTwoButtonsSetting settingBase)
+ : base(settingBase)
+ {
+ Base = settingBase;
+
+ if (OriginalDefinition.Is(out TwoButtonsSetting setting))
+ {
+ FirstOption = setting.FirstOption;
+ SecondOption = setting.SecondOption;
+ }
+ }
+
+ ///
+ public new SSTwoButtonsSetting Base { get; }
+
+ ///
+ /// Gets or sets a value indicating whether the second option is chosen.
+ ///
+ public bool IsSecond
+ {
+ get => Base.SyncIsB;
+ set => Base.SyncIsB = value;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the first option is chosen.
+ ///
+ public bool IsFirst
+ {
+ get => Base.SyncIsA;
+ set => Base.SyncIsB = !value;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the second option is default.
+ ///
+ public bool IsSecondDefault
+ {
+ get => Base.DefaultIsB;
+ set => Base.DefaultIsB = value;
+ }
+
+ ///
+ /// Gets or sets a label for the first option.
+ ///
+ public string FirstOption
+ {
+ get => Base.OptionA;
+ set => Base.OptionA = value;
+ }
+
+ ///
+ /// Gets or sets a label for the second option.
+ ///
+ public string SecondOption
+ {
+ get => Base.OptionB;
+ set => Base.OptionB = value;
+ }
+
+ ///
+ /// Returns a representation of this .
+ ///
+ /// A string in human-readable format.
+ public override string ToString()
+ {
+ return base.ToString() + $" /{FirstOption}/ *{SecondOption}* +{IsSecondDefault}+ '{IsFirst}'";
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/DamageHandlers/CustomDamageHandler.cs b/EXILED/Exiled.API/Features/DamageHandlers/CustomDamageHandler.cs
index 115990925..67b464474 100644
--- a/EXILED/Exiled.API/Features/DamageHandlers/CustomDamageHandler.cs
+++ b/EXILED/Exiled.API/Features/DamageHandlers/CustomDamageHandler.cs
@@ -71,7 +71,7 @@ public CustomDamageHandler(Player target, Player attacker, float damage, DamageT
Base = { Owner = attacker.ReferenceHub },
};
- CustomBase = new FirearmDamageHandler(firearm, target, new BaseFirearmHandler(firearm.Base, damage));
+ CustomBase = new FirearmDamageHandler(firearm, target, new PlayerStatsSystem.FirearmDamageHandler() { Firearm = firearm.Base, Damage = damage });
}
///
diff --git a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs
index 152f77af2..2008936be 100644
--- a/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs
+++ b/EXILED/Exiled.API/Features/DamageHandlers/GenericDamageHandler.cs
@@ -10,14 +10,12 @@ namespace Exiled.API.Features.DamageHandlers
using Enums;
using Footprinting;
-
using Items;
using PlayerRoles.PlayableScps.Scp096;
using PlayerRoles.PlayableScps.Scp939;
using PlayerStatsSystem;
-
using UnityEngine;
///
@@ -92,6 +90,9 @@ public GenericDamageHandler(Player player, Player attacker, float damage, Damage
case DamageType.SeveredHands:
Base = new UniversalDamageHandler(damage, DeathTranslations.SeveredHands, cassieAnnouncement);
break;
+ case DamageType.SeveredEyes:
+ Base = new UniversalDamageHandler(damage, DeathTranslations.Scp1344, cassieAnnouncement);
+ break;
case DamageType.Warhead:
Base = new WarheadDamageHandler();
break;
@@ -110,10 +111,10 @@ public GenericDamageHandler(Player player, Player attacker, float damage, Damage
case DamageType.MicroHid:
InventorySystem.Items.MicroHID.MicroHIDItem microHidOwner = new();
microHidOwner.Owner = attacker.ReferenceHub;
- Base = new MicroHidDamageHandler(microHidOwner, damage);
+ Base = new MicroHidDamageHandler(damage, microHidOwner);
break;
case DamageType.Explosion:
- Base = new ExplosionDamageHandler(attacker.Footprint, UnityEngine.Vector3.zero, damage, 0);
+ Base = new ExplosionDamageHandler(attacker.Footprint, UnityEngine.Vector3.zero, damage, 0, ExplosionType.Grenade);
break;
case DamageType.Firearm:
GenericFirearm(player, attacker, damage, damageType, ItemType.GunAK);
@@ -155,7 +156,7 @@ public GenericDamageHandler(Player player, Player attacker, float damage, Damage
GenericFirearm(player, attacker, damage, damageType, ItemType.GunA7);
break;
case DamageType.ParticleDisruptor:
- Base = new DisruptorDamageHandler(Attacker, damage);
+ Base = new DisruptorDamageHandler(new (Item.Create(ItemType.ParticleDisruptor, attacker).Base as InventorySystem.Items.Firearms.Firearm, InventorySystem.Items.Firearms.Modules.DisruptorActionModule.FiringState.FiringSingle), Vector3.up, damage);
break;
case DamageType.Scp096:
Scp096Role curr096 = attacker.ReferenceHub.roleManager.CurrentRole as Scp096Role ?? new Scp096Role();
@@ -259,7 +260,7 @@ private void GenericFirearm(Player player, Player attacker, float amount, Damage
Owner = attacker.ReferenceHub,
},
};
- Base = new PlayerStatsSystem.FirearmDamageHandler(firearm.Base, amount);
+ Base = new PlayerStatsSystem.FirearmDamageHandler() { Firearm = firearm.Base, Damage = amount };
}
}
}
diff --git a/EXILED/Exiled.API/Features/Doors/BreakableDoor.cs b/EXILED/Exiled.API/Features/Doors/BreakableDoor.cs
index 9148067dd..862332c89 100644
--- a/EXILED/Exiled.API/Features/Doors/BreakableDoor.cs
+++ b/EXILED/Exiled.API/Features/Doors/BreakableDoor.cs
@@ -92,6 +92,11 @@ public bool IgnoreRemoteAdmin
set => Base._nonInteractable = value;
}
+ ///
+ /// Repair the door.
+ ///
+ public void Repair() => Base.ServerRepair();
+
///
/// Damages the door.
///
diff --git a/EXILED/Exiled.API/Features/Doors/CheckpointDoor.cs b/EXILED/Exiled.API/Features/Doors/CheckpointDoor.cs
index 9681290d8..837bd5ff7 100644
--- a/EXILED/Exiled.API/Features/Doors/CheckpointDoor.cs
+++ b/EXILED/Exiled.API/Features/Doors/CheckpointDoor.cs
@@ -133,6 +133,11 @@ public DoorDamageType IgnoredDamage
///
internal List SubDoorsValue { get; } = new();
+ ///
+ /// Repair the door.
+ ///
+ public void Repair() => Base.ServerRepair();
+
///
/// Toggles the state of the doors from .
///
diff --git a/EXILED/Exiled.API/Features/Doors/Door.cs b/EXILED/Exiled.API/Features/Doors/Door.cs
index 4f949748e..63b4f62ce 100644
--- a/EXILED/Exiled.API/Features/Doors/Door.cs
+++ b/EXILED/Exiled.API/Features/Doors/Door.cs
@@ -14,17 +14,13 @@ namespace Exiled.API.Features.Doors
using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Features.Core;
- using Exiled.API.Features.Hazards;
using Exiled.API.Interfaces;
- using global::Hazards;
using Interactables.Interobjects;
using Interactables.Interobjects.DoorUtils;
using MEC;
using Mirror;
using UnityEngine;
- using static Interactables.Interobjects.ElevatorManager;
-
using BaseBreakableDoor = Interactables.Interobjects.BreakableDoor;
using BaseKeycardPermissions = Interactables.Interobjects.DoorUtils.KeycardPermissions;
using Breakable = BreakableDoor;
@@ -59,9 +55,9 @@ internal Door(DoorVariant door, List rooms)
}
Type = GetDoorType();
-#if Debug
- if (Type is DoorType.Unknown)
- Log.Error($"[DOORTYPE UNKNOWN] {this}");
+#if DEBUG
+ if (Type is DoorType.UnknownDoor or DoorType.UnknownGate or DoorType.UnknownElevator)
+ Log.Error($"[DOORTYPE UNKNOWN] {this} BASE = {Base}");
#endif
}
@@ -518,10 +514,22 @@ public void ChangeLock(DoorLockType lockType)
/// The of the lockdown.
public void Lock(float time, DoorLockType lockType)
{
- ChangeLock(lockType);
+ Lock(lockType);
Unlock(time, lockType);
}
+ ///
+ /// Locks all active locks on the door for infinite time.
+ ///
+ /// The of the lockdown.
+ public void Lock(DoorLockType lockType)
+ {
+ DoorLockType locks = DoorLockType;
+ locks |= lockType;
+ Base.NetworkActiveLocks = (ushort)locks;
+ DoorEvents.TriggerAction(Base, IsLocked ? DoorAction.Locked : DoorAction.Unlocked, null);
+ }
+
///
/// Unlocks and clears all active locks on the door.
///
@@ -545,7 +553,7 @@ public void Lock(float time, DoorLockType lockType)
/// Returns the Door in a human-readable format.
///
/// A string containing Door-related data.
- public override string ToString() => $"{Type} ({Zone}) [{Room}] *{DoorLockType}* ={RequiredPermissions.RequiredPermissions}=";
+ public override string ToString() => $"{Type} ({Zone}) [{Room}] *{DoorLockType}* ={RequiredPermissions?.RequiredPermissions}=";
///
/// Creates the door object associated with a specific .
@@ -576,38 +584,38 @@ private DoorType GetDoorType()
{
if (Nametag is null)
{
- string doorName = GameObject.name.GetBefore(' ');
+ string doorName = GameObject.name.GetBefore('(').TrimEnd();
+
return doorName switch
{
- "LCZ" => Room?.Type switch
- {
- RoomType.LczAirlock => (Base.GetComponentInParent() != null) ? DoorType.Airlock : DoorType.LightContainmentDoor,
- _ => DoorType.LightContainmentDoor,
- },
- "HCZ" => DoorType.HeavyContainmentDoor,
- "EZ" => DoorType.EntranceDoor,
- "Prison" => DoorType.PrisonDoor,
- "914" => DoorType.Scp914Door,
- "Intercom" => Room?.Type switch
+ "LCZ PortallessBreakableDoor" => DoorType.Airlock,
+ "LCZ BreakableDoor" => DoorType.LightContainmentDoor,
+ "HCZ BreakableDoor" => DoorType.HeavyContainmentDoor,
+ "HCZ BulkDoor" => DoorType.HeavyBulkDoor,
+ "EZ BreakableDoor" => DoorType.EntranceDoor,
+ "Prison BreakableDoor" => DoorType.PrisonDoor,
+ "914 Door" => DoorType.Scp914Door,
+ "Intercom BreakableDoor" => Room?.Type switch
{
RoomType.HczEzCheckpointA => DoorType.CheckpointArmoryA,
RoomType.HczEzCheckpointB => DoorType.CheckpointArmoryB,
_ => DoorType.UnknownDoor,
},
- "Unsecured" => Room?.Type switch
+ "Unsecured Pryable GateDoor" => Room?.Type switch
{
- RoomType.EzCheckpointHallway => DoorType.CheckpointGate,
+ RoomType.EzCheckpointHallwayA => DoorType.CheckpointGateA,
+ RoomType.EzCheckpointHallwayB => DoorType.CheckpointGateB,
RoomType.Hcz049 => Position.y < -805 ? DoorType.Scp049Gate : DoorType.Scp173NewGate,
_ => DoorType.UnknownGate,
},
- "Elevator" => (Base as Interactables.Interobjects.ElevatorDoor)?.Group switch
+ "Elevator Door" or "Nuke Elevator Door" or "Elevator Door 02" => (Base as Interactables.Interobjects.ElevatorDoor)?.Group switch
{
- ElevatorGroup.Nuke => DoorType.ElevatorNuke,
ElevatorGroup.Scp049 => DoorType.ElevatorScp049,
ElevatorGroup.GateB => DoorType.ElevatorGateB,
ElevatorGroup.GateA => DoorType.ElevatorGateA,
ElevatorGroup.LczA01 or ElevatorGroup.LczA02 => DoorType.ElevatorLczA,
ElevatorGroup.LczB01 or ElevatorGroup.LczB02 => DoorType.ElevatorLczB,
+ ElevatorGroup.Nuke01 or ElevatorGroup.Nuke02 => DoorType.ElevatorNuke,
_ => DoorType.UnknownElevator,
},
_ => DoorType.UnknownDoor,
@@ -629,7 +637,6 @@ private DoorType GetDoorType()
"NUKE_ARMORY" => DoorType.NukeArmory,
"LCZ_ARMORY" => DoorType.LczArmory,
"SURFACE_NUKE" => DoorType.NukeSurface,
- "HID" => DoorType.HID,
"HCZ_ARMORY" => DoorType.HczArmory,
"096" => DoorType.Scp096,
"049_ARMORY" => DoorType.Scp049Armory,
@@ -639,11 +646,11 @@ private DoorType GetDoorType()
"079_FIRST" => DoorType.Scp079First,
"GATE_B" => DoorType.GateB,
"079_SECOND" => DoorType.Scp079Second,
- "SERVERS_BOTTOM" => DoorType.ServersBottom,
"173_CONNECTOR" => DoorType.Scp173Connector,
"LCZ_WC" => DoorType.LczWc,
- "HID_RIGHT" => DoorType.HIDRight,
- "HID_LEFT" => DoorType.HIDLeft,
+ "HID_CHAMBER" => DoorType.HIDChamber,
+ "HID_UPPER" => DoorType.HIDUpper,
+ "HID_LOWER" => DoorType.HIDLower,
"173_ARMORY" => DoorType.Scp173Armory,
"173_GATE" => DoorType.Scp173Gate,
"GR18" => DoorType.GR18Gate,
@@ -652,6 +659,7 @@ private DoorType GetDoorType()
"330_CHAMBER" => DoorType.Scp330Chamber,
"GR18_INNER" => DoorType.GR18Inner,
"939_CRYO" => DoorType.Scp939Cryo,
+ "ESCAPE_FINAL" => DoorType.EscapeFinal,
// Doors spawned by the DoorSpawnPoint component
"LCZ_CAFE" => DoorType.LczCafe,
diff --git a/EXILED/Exiled.API/Features/Doors/ElevatorDoor.cs b/EXILED/Exiled.API/Features/Doors/ElevatorDoor.cs
index aa011f7fe..797378312 100644
--- a/EXILED/Exiled.API/Features/Doors/ElevatorDoor.cs
+++ b/EXILED/Exiled.API/Features/Doors/ElevatorDoor.cs
@@ -12,6 +12,7 @@ namespace Exiled.API.Features.Doors
using Exiled.API.Enums;
using Interactables.Interobjects;
+ using UnityEngine;
///
/// Represents an elevator door.
@@ -28,6 +29,8 @@ internal ElevatorDoor(Interactables.Interobjects.ElevatorDoor door, List r
{
Base = door;
Lift = Lift.Get(x => x.Group == Group).FirstOrDefault();
+
+ Panel = Object.FindObjectsOfType().FirstOrDefault(x => x._door == door);
}
///
@@ -36,29 +39,29 @@ internal ElevatorDoor(Interactables.Interobjects.ElevatorDoor door, List r
public new Interactables.Interobjects.ElevatorDoor Base { get; }
///
- /// Gets the that this door's belongs to.
+ /// Gets the that this door's belongs to.
+ ///
+ public ElevatorGroup Group => Base.Group;
+
+ ///
+ /// Gets the associated with this lift.
///
- public ElevatorManager.ElevatorGroup Group => Base.Group;
+ public ElevatorPanel Panel { get; }
///
/// Gets the type according to .
///
public ElevatorType ElevatorType => Group switch
{
- ElevatorManager.ElevatorGroup.Scp049 => ElevatorType.Scp049,
- ElevatorManager.ElevatorGroup.GateA => ElevatorType.GateA,
- ElevatorManager.ElevatorGroup.GateB => ElevatorType.GateB,
- ElevatorManager.ElevatorGroup.LczA01 or ElevatorManager.ElevatorGroup.LczA02 => ElevatorType.LczA,
- ElevatorManager.ElevatorGroup.LczB01 or ElevatorManager.ElevatorGroup.LczB02 => ElevatorType.LczB,
- ElevatorManager.ElevatorGroup.Nuke => ElevatorType.Nuke,
+ ElevatorGroup.Scp049 => ElevatorType.Scp049,
+ ElevatorGroup.GateA => ElevatorType.GateA,
+ ElevatorGroup.GateB => ElevatorType.GateB,
+ ElevatorGroup.LczA01 or ElevatorGroup.LczA02 => ElevatorType.LczA,
+ ElevatorGroup.LczB01 or ElevatorGroup.LczB02 => ElevatorType.LczB,
+ ElevatorGroup.Nuke01 or ElevatorGroup.Nuke02 => ElevatorType.Nuke,
_ => ElevatorType.Unknown,
};
- ///
- /// Gets the target panel for this lift.
- ///
- public ElevatorPanel Panel => Base.TargetPanel;
-
///
/// Gets the associated with this elevator door.
///
diff --git a/EXILED/Exiled.API/Features/Items/Armor.cs b/EXILED/Exiled.API/Features/Items/Armor.cs
index 30b99bc7c..6fe2bc097 100644
--- a/EXILED/Exiled.API/Features/Items/Armor.cs
+++ b/EXILED/Exiled.API/Features/Items/Armor.cs
@@ -115,14 +115,9 @@ public float StaminaUseMultiplier
public float StaminaRegenMultiplier { get; set; } = 1f;
///
- /// Gets or sets how much the users movement speed should be affected when wearing this armor. (higher values = slower movement).
+ /// Gets how much the users movement speed should be affected when wearing this armor. (higher values = slower movement).
///
- public float MovementSpeedMultiplier
- {
- get => Base._movementSpeedMultiplier;
- [Obsolete("This Setter was causing desync to client", true)]
- set => _ = value;
- }
+ public float MovementSpeedMultiplier => Base._movementSpeedMultiplier;
///
/// Gets how much worse and s are affected by wearing this armor.
diff --git a/EXILED/Exiled.API/Features/Items/Firearm.cs b/EXILED/Exiled.API/Features/Items/Firearm.cs
index 750bd9d96..98cd780c2 100644
--- a/EXILED/Exiled.API/Features/Items/Firearm.cs
+++ b/EXILED/Exiled.API/Features/Items/Firearm.cs
@@ -12,15 +12,15 @@ namespace Exiled.API.Features.Items
using System.Linq;
using CameraShaking;
-
using Enums;
+ using Exiled.API.Features.Items.FirearmModules;
+ using Exiled.API.Features.Items.FirearmModules.Barrel;
+ using Exiled.API.Features.Items.FirearmModules.Primary;
using Exiled.API.Features.Pickups;
using Exiled.API.Interfaces;
using Exiled.API.Structs;
-
using Extensions;
-
using InventorySystem;
using InventorySystem.Items;
using InventorySystem.Items.Firearms;
@@ -29,7 +29,7 @@ namespace Exiled.API.Features.Items
using InventorySystem.Items.Firearms.BasicMessages;
using InventorySystem.Items.Firearms.Modules;
using InventorySystem.Items.Pickups;
-
+ using MEC;
using UnityEngine;
using BaseFirearm = InventorySystem.Items.Firearms.Firearm;
@@ -59,6 +59,20 @@ public Firearm(BaseFirearm itemBase)
: base(itemBase)
{
Base = itemBase;
+
+ foreach (ModuleBase module in Base.Modules)
+ {
+ if (module is IPrimaryAmmoContainerModule primaryAmmoModule)
+ {
+ PrimaryMagazine ??= (PrimaryMagazine)Magazine.Get(primaryAmmoModule);
+ continue;
+ }
+
+ if (module is IAmmoContainerModule ammoModule)
+ {
+ BarrelMagazine ??= (BarrelMagazine)Magazine.Get(ammoModule);
+ }
+ }
}
///
@@ -68,11 +82,10 @@ public Firearm(BaseFirearm itemBase)
internal Firearm(ItemType type)
: this((BaseFirearm)Server.Host.Inventory.CreateItemInstance(new(type, 0), false))
{
- FirearmStatusFlags firearmStatusFlags = FirearmStatusFlags.MagazineInserted;
- if (Base.HasAdvantageFlag(AttachmentDescriptiveAdvantages.Flashlight))
- firearmStatusFlags |= FirearmStatusFlags.FlashlightEnabled;
+ FlashlightAttachment flashlight = Attachments.OfType().FirstOrDefault();
- Base.Status = new FirearmStatus(MaxAmmo, firearmStatusFlags, Base.Status.Attachments);
+ if (flashlight != null && flashlight.IsEnabled)
+ flashlight.ServerSendStatus(true);
}
/// .
@@ -110,41 +123,94 @@ public static IReadOnlyDictionary
- /// Gets or sets the amount of ammo in the firearm.
+ /// Gets a primaty magazine for current firearm.
+ ///
+ public PrimaryMagazine PrimaryMagazine { get; }
+
+ ///
+ /// Gets a barrel magazine for current firearm.
+ ///
+ ///
+ /// for Revolver and ParticleDisruptor.
+ ///
+ public BarrelMagazine BarrelMagazine { get; }
+
+ ///
+ /// Gets or sets the amount of ammo in the firearm magazine.
+ ///
+ public int MagazineAmmo
+ {
+ get => PrimaryMagazine.Ammo;
+ set => PrimaryMagazine.Ammo = value;
+ }
+
+ ///
+ /// Gets or sets the amount of ammo in the firearm barrel.
///
- public byte Ammo
+ ///
+ /// not working for Revolver and ParticleDisruptor.
+ ///
+ public int BarrelAmmo
{
- get => Base.Status.Ammo;
- set => Base.Status = new FirearmStatus(value, Base.Status.Flags, Base.Status.Attachments);
+ get => BarrelMagazine?.Ammo ?? 0;
+
+ set
+ {
+ if (BarrelMagazine != null)
+ BarrelMagazine.Ammo = value;
+ }
}
+ ///
+ /// Gets the total amount of ammo in the firearm.
+ ///
+ public int TotalAmmo => Base.GetTotalStoredAmmo();
+
///
/// Gets or sets the max ammo for this firearm.
///
- /// Disruptor can't be used for MaxAmmo.
- public byte MaxAmmo
+ public int MaxMagazineAmmo
+ {
+ get => PrimaryMagazine.MaxAmmo;
+ set => PrimaryMagazine.MaxAmmo = value;
+ }
+
+ ///
+ /// Gets or sets the amount of max ammo in the firearm barrel.
+ ///
+ ///
+ /// not working for Revolver and ParticleDisruptor.
+ ///
+ public int MaxBarrelAmmo
{
- get => Base.AmmoManagerModule.MaxAmmo;
+ get => BarrelMagazine?.MaxAmmo ?? 0;
+
set
{
- switch (Base.AmmoManagerModule)
- {
- case TubularMagazineAmmoManager tubularMagazineAmmoManager:
- tubularMagazineAmmoManager.MaxAmmo = (byte)(value - Base.AttachmentsValue(AttachmentParam.MagazineCapacityModifier) - (Base.Status.Flags.HasFlagFast(FirearmStatusFlags.Cocked) ? tubularMagazineAmmoManager.ChamberedRounds : 0));
- break;
- case ClipLoadedInternalMagAmmoManager clipLoadedInternalMagAmmoManager:
- clipLoadedInternalMagAmmoManager.MaxAmmo = (byte)(value - Base.AttachmentsValue(AttachmentParam.MagazineCapacityModifier));
- break;
- case AutomaticAmmoManager automaticAmmoManager:
- automaticAmmoManager.MaxAmmo = (byte)(value - Base.AttachmentsValue(AttachmentParam.MagazineCapacityModifier) - automaticAmmoManager.ChamberedAmount);
- break;
- default:
- Log.Warn($"MaxAmmo can't be used for this Item: {Type} ({Base.AmmoManagerModule})");
- return;
- }
+ if (BarrelMagazine != null)
+ BarrelMagazine.MaxAmmo = value;
}
}
+ ///
+ /// Gets the total amount of ammo in the firearm.
+ ///
+ public int TotalMaxAmmo => Base.GetTotalMaxAmmo();
+
+ ///
+ /// Gets or sets a ammo drain per shoot.
+ ///
+ ///
+ /// Always by default.
+ /// Applied on a high layer nether basegame ammo controllers.
+ ///
+ public int AmmoDrain { get; set; } = 1;
+
+ ///
+ /// Gets a value indicating whether the weapon is reloading.
+ ///
+ public bool IsReloading => Base.TryGetModule(out IReloaderModule module) && module.IsReloading;
+
///
/// Gets the of the firearm.
///
@@ -153,17 +219,17 @@ public byte MaxAmmo
///
/// Gets the of the firearm.
///
- public AmmoType AmmoType => Base.AmmoType.GetAmmoType();
+ public AmmoType AmmoType => PrimaryMagazine.AmmoType;
///
/// Gets a value indicating whether the firearm is being aimed.
///
- public bool Aiming => Base.AdsModule.ServerAds;
+ public bool Aiming => Base.TryGetModule(out LinearAdsModule module) && module.AdsTarget;
///
/// Gets a value indicating whether the firearm's flashlight module is enabled.
///
- public bool FlashlightEnabled => Base.Status.Flags.HasFlagFast(FirearmStatusFlags.FlashlightEnabled);
+ public bool FlashlightEnabled => Base.IsEmittingLight;
///
/// Gets a value indicating whether the firearm's NightVision is being used.
@@ -178,7 +244,7 @@ public byte MaxAmmo
///
/// Gets a value indicating whether the firearm is automatic.
///
- public bool IsAutomatic => Base is AutomaticFirearm;
+ public bool IsAutomatic => BarrelMagazine is AutomaticBarrelMagazine;
///
/// Gets the s of the firearm.
@@ -202,21 +268,6 @@ public IEnumerable AttachmentIdentifiers
///
public uint BaseCode => BaseCodesValue[FirearmType];
- ///
- /// Gets or sets the fire rate of the firearm, if it is an automatic weapon.
- ///
- /// This property will not do anything if the firearm is not an automatic weapon.
- ///
- public float FireRate
- {
- get => Base is AutomaticFirearm auto ? auto._fireRate : 1f;
- set
- {
- if (Base is AutomaticFirearm auto)
- auto._fireRate = value;
- }
- }
-
///
/// Gets or sets the recoil settings of the firearm, if it's an automatic weapon.
///
@@ -224,19 +275,14 @@ public float FireRate
///
public RecoilSettings Recoil
{
- get => Base is AutomaticFirearm auto ? auto._recoil : default;
+ get => Base.TryGetModule(out RecoilPatternModule module) ? module.BaseRecoil : default;
set
{
- if (Base is AutomaticFirearm auto)
- auto.ActionModule = new AutomaticAction(Base, auto._semiAutomatic, auto._boltTravelTime, 1f / auto._fireRate, auto._dryfireClipId, auto._triggerClipId, auto._gunshotPitchRandomization, value, auto._recoilPattern, false, Mathf.Max(1, auto._chamberSize));
+ if (Base.TryGetModule(out RecoilPatternModule module))
+ module.BaseRecoil = value;
}
}
- ///
- /// Gets the firearm's . Will be for non-automatic weapons.
- ///
- public FirearmRecoilPattern RecoilPattern => Base is AutomaticFirearm auto ? auto._recoilPattern : null;
-
///
/// Gets a of and [] which contains all available attachments for all firearms.
///
@@ -277,7 +323,9 @@ public void AddAttachment(AttachmentIdentifier identifier)
: identifier.Code;
Base.ApplyAttachmentsCode((Base.GetCurrentAttachmentsCode() & ~toRemove) | newCode, true);
- Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());
+
+ // TODO Not finish
+ // Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());
}
///
@@ -319,10 +367,12 @@ public void RemoveAttachment(AttachmentIdentifier identifier)
Base.ApplyAttachmentsCode(Base.GetCurrentAttachmentsCode() & ~code, true);
+ // TODO: Not finish
+ /*
if (identifier.Name == AttachmentName.Flashlight)
Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags & ~FirearmStatusFlags.FlashlightEnabled, Base.GetCurrentAttachmentsCode());
else
- Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());
+ Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());*/
}
///
@@ -335,10 +385,12 @@ public void RemoveAttachment(AttachmentName attachmentName)
Base.ApplyAttachmentsCode(Base.GetCurrentAttachmentsCode() & ~code, true);
+ // TODO Not finish
+ /*
if (attachmentName == AttachmentName.Flashlight)
Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags & ~FirearmStatusFlags.FlashlightEnabled, Base.GetCurrentAttachmentsCode());
else
- Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());
+ Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());*/
}
///
@@ -356,10 +408,12 @@ public void RemoveAttachment(AttachmentSlot attachmentSlot)
Base.ApplyAttachmentsCode(Base.GetCurrentAttachmentsCode() & ~code, true);
+ // TODO Not finish
+ /*
if (firearmAttachment.Name == AttachmentName.Flashlight)
Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags & ~FirearmStatusFlags.FlashlightEnabled, Base.GetCurrentAttachmentsCode());
else
- Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());
+ Base.Status = new FirearmStatus(Math.Min(Ammo, MaxAmmo), Base.Status.Flags, Base.GetCurrentAttachmentsCode());*/
}
///
@@ -397,16 +451,6 @@ public void RemoveAttachment(IEnumerable attachmentSlots)
///
public void ClearAttachments() => Base.ApplyAttachmentsCode(BaseCode, true);
- ///
- /// Creates the that based on this .
- ///
- /// The location to spawn the item.
- /// The rotation of the item.
- /// Whether the should be initially spawned.
- /// The created .
- public override Pickup CreatePickup(Vector3 position, Quaternion rotation = default, bool spawn = true)
- => base.CreatePickup(position, rotation, spawn); // TODO: Deleted this overide
-
///
/// Gets a of the specified .
///
@@ -602,6 +646,20 @@ public void ClearPreferences()
ClearPreferences(player);
}
+ ///
+ /// Reloads current .
+ ///
+ ///
+ /// For specific reloading logic you also can use for avaible weapons.
+ ///
+ public void Reload()
+ {
+ if (Base.TryGetModule(out AnimatorReloaderModuleBase module))
+ {
+ module.StartReloading();
+ }
+ }
+
///
/// Clones current object.
///
@@ -610,14 +668,15 @@ public override Item Clone()
{
Firearm cloneableItem = new(Type)
{
- Ammo = Ammo,
};
+ // TODO Not finish
+ /*
if (cloneableItem.Base is AutomaticFirearm)
{
cloneableItem.FireRate = FireRate;
cloneableItem.Recoil = Recoil;
- }
+ }*/
cloneableItem.AddAttachment(AttachmentIdentifiers);
@@ -632,14 +691,23 @@ public override Item Clone()
internal override void ChangeOwner(Player oldOwner, Player newOwner)
{
Base.Owner = newOwner.ReferenceHub;
-
- if (Base.HitregModule is StandardHitregBase hitReg)
+ Base._footprintCacheSet = false;
+ foreach (ModuleBase module in Base.Modules)
{
- hitReg.Hub = Base.Owner;
+ module.OnAdded();
}
+ }
- Base._sendStatusNextFrame = true;
- Base._footprintValid = false;
+ ///
+ internal override void ReadPickupInfo(Pickup pickup)
+ {
+ base.ReadPickupInfo(pickup);
+
+ if (pickup is FirearmPickup firearmPickup)
+ {
+ PrimaryMagazine.MaxAmmo = firearmPickup.MaxAmmo;
+ AmmoDrain = firearmPickup.AmmoDrain;
+ }
}
}
}
diff --git a/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/AutomaticBarrelMagazine.cs b/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/AutomaticBarrelMagazine.cs
new file mode 100644
index 000000000..db8992d72
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/AutomaticBarrelMagazine.cs
@@ -0,0 +1,105 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.FirearmModules.Barrel
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ using InventorySystem.Items.Firearms.Modules;
+
+ using UnityEngine;
+
+ ///
+ /// Basic realization of barrel.
+ ///
+ public class AutomaticBarrelMagazine : BarrelMagazine
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Target .
+ public AutomaticBarrelMagazine(AutomaticActionModule automaticModule)
+ : base(automaticModule)
+ {
+ AutomaticBarrel = automaticModule;
+ }
+
+ ///
+ /// Gets an original .
+ ///
+ public AutomaticActionModule AutomaticBarrel { get; }
+
+ ///
+ public override Firearm Firearm => Item.Get(AutomaticBarrel.Firearm);
+
+ ///
+ public override int Ammo
+ {
+ get => AutomaticBarrel.AmmoStored;
+
+ set
+ {
+ AutomaticBarrel.AmmoStored = Mathf.Max(value, 0);
+ Resync();
+ }
+ }
+
+ ///
+ ///
+ /// Will be ranged between and due basegame logic.
+ ///
+ public override int MaxAmmo
+ {
+ get => AutomaticBarrel.ChamberSize;
+
+ set => AutomaticBarrel.ChamberSize = Mathf.Clamp(value, 0, 16);
+ }
+
+ ///
+ public override bool IsCocked
+ {
+ get => AutomaticBarrel.Cocked;
+
+ set
+ {
+ AutomaticBarrel.Cocked = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether barrel magazine has open bolt or not.
+ ///
+ public bool IsOpenBolted => AutomaticBarrel.OpenBolt;
+
+ ///
+ /// Gets or sets a value indicating whether barrel bolt is currently locked.
+ ///
+ public bool BoltLocked
+ {
+ get => AutomaticBarrel.BoltLocked;
+
+ set
+ {
+ AutomaticBarrel.BoltLocked = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets the fire rate of the firearm.
+ ///
+ public float FireRate => AutomaticBarrel.BaseFireRate;
+
+ ///
+ public override void Resync() => AutomaticBarrel.ServerResync();
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/BarrelMagazine.cs b/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/BarrelMagazine.cs
new file mode 100644
index 000000000..b1e11f758
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/BarrelMagazine.cs
@@ -0,0 +1,31 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.FirearmModules.Barrel
+{
+ using InventorySystem.Items.Firearms.Modules;
+
+ ///
+ /// Basic abstraction of whose are logically used to be a barrels magazines.
+ ///
+ public abstract class BarrelMagazine : Magazine
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// target .
+ public BarrelMagazine(IAmmoContainerModule module)
+ : base(module)
+ {
+ }
+
+ ///
+ /// Gets or sets a value indicating whether barrel is cocked.
+ ///
+ public abstract bool IsCocked { get; set; }
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/PumpBarrelMagazine.cs b/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/PumpBarrelMagazine.cs
new file mode 100644
index 000000000..57ab59b08
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/FirearmModules/Barrel/PumpBarrelMagazine.cs
@@ -0,0 +1,91 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.FirearmModules.Barrel
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ using InventorySystem.Items.Firearms.Modules;
+
+ using UnityEngine;
+
+ ///
+ /// Basic realization of barrel.
+ ///
+ public class PumpBarrelMagazine : BarrelMagazine
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Target .
+ public PumpBarrelMagazine(PumpActionModule pumpModule)
+ : base(pumpModule)
+ {
+ PumpBarrel = pumpModule;
+ }
+
+ ///
+ /// Gets an original .
+ ///
+ public PumpActionModule PumpBarrel { get; }
+
+ ///
+ public override Firearm Firearm => Item.Get(PumpBarrel.Firearm);
+
+ ///
+ public override int Ammo
+ {
+ get => PumpBarrel.SyncChambered;
+
+ set
+ {
+ PumpBarrel.SyncChambered = Mathf.Max(value, 0);
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets an amount of bullets, that pump module will try to shot.
+ ///
+ public int CockedAmmo
+ {
+ get => PumpBarrel.SyncCocked;
+
+ set
+ {
+ PumpBarrel.SyncCocked = Mathf.Max(value, 0);
+ Resync();
+ }
+ }
+
+ ///
+ public override int MaxAmmo
+ {
+ get => PumpBarrel._numberOfBarrels;
+ set => PumpBarrel._numberOfBarrels = Mathf.Max(value, 0);
+ }
+
+ ///
+ public override bool IsCocked
+ {
+ get => PumpBarrel.SyncCocked > 0;
+
+ set
+ {
+ PumpBarrel.SyncCocked = MaxAmmo;
+ Resync();
+ }
+ }
+
+ ///
+ public override void Resync() => PumpBarrel.ServerResync();
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/FirearmModules/Magazine.cs b/EXILED/Exiled.API/Features/Items/FirearmModules/Magazine.cs
new file mode 100644
index 000000000..50a2538c6
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/FirearmModules/Magazine.cs
@@ -0,0 +1,111 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.FirearmModules
+{
+ using System;
+
+ using Exiled.API.Features.Items.FirearmModules.Barrel;
+ using Exiled.API.Features.Items.FirearmModules.Primary;
+
+ using InventorySystem.Items.Firearms.Modules;
+
+ using UnityEngine;
+
+ ///
+ /// Basic abstraction of .
+ ///
+ public abstract class Magazine
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// target .
+ public Magazine(IAmmoContainerModule module)
+ {
+ AmmoContainerModule = module;
+ }
+
+ ///
+ /// Gets an original .
+ ///
+ public IAmmoContainerModule AmmoContainerModule { get; }
+
+ ///
+ /// Gets or sets a count of current ammo in magazine.
+ ///
+ public abstract int Ammo { get; set; }
+
+ ///
+ /// Gets or sets a max avaible ammo count in magazine.
+ ///
+ public abstract int MaxAmmo { get; set; }
+
+ ///
+ /// Gets target assotiated with this magazine.
+ ///
+ public abstract Firearm Firearm { get; }
+
+ ///
+ /// Gets wrapper to an .
+ ///
+ /// The target .
+ /// The wrapper for the given .
+ public static Magazine Get(IAmmoContainerModule module)
+ {
+ if (module == null)
+ return null;
+
+ return module switch
+ {
+ AutomaticActionModule actomatic => new AutomaticBarrelMagazine(actomatic),
+ PumpActionModule pump => new PumpBarrelMagazine(pump),
+ IPrimaryAmmoContainerModule primary => primary switch
+ {
+ MagazineModule magazine => new NormalMagazine(magazine),
+ CylinderAmmoModule cylinder => new CylinderMagazine(cylinder),
+ _ => null,
+ },
+ _ => null,
+ };
+ }
+
+ ///
+ /// Modifies stored ammo in magazine.
+ ///
+ /// Ammo change value.
+ /// Whether new ammo should be clamped in range of and .
+ /// Resultly changed ammos.
+ ///
+ /// Just a variation of the setter.
+ ///
+ public int ModifyAmmo(int delta, bool useBorders = true)
+ {
+ int oldAmmo = Ammo;
+ if (useBorders)
+ {
+ Ammo = Mathf.Clamp(Ammo + delta, 0, MaxAmmo);
+ }
+ else
+ {
+ Ammo += delta;
+ }
+
+ return Ammo - oldAmmo;
+ }
+
+ ///
+ /// Fills current to .
+ ///
+ public void Fill() => Ammo = MaxAmmo;
+
+ ///
+ /// Resyncs a related values with a client.
+ ///
+ public abstract void Resync();
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/CylinderMagazine.cs b/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/CylinderMagazine.cs
new file mode 100644
index 000000000..2beedd7bb
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/CylinderMagazine.cs
@@ -0,0 +1,105 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.FirearmModules.Primary
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Linq;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Extensions;
+
+ using InventorySystem.Items.Firearms.Modules;
+
+ ///
+ /// Basic realization of .
+ ///
+ public class CylinderMagazine : PrimaryMagazine
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// target .
+ public CylinderMagazine(CylinderAmmoModule magazine)
+ : base(magazine)
+ {
+ CylinderModule = magazine;
+ }
+
+ ///
+ /// Gets an original .
+ ///
+ public CylinderAmmoModule CylinderModule { get; }
+
+ ///
+ public override Firearm Firearm => Item.Get(CylinderModule.Firearm);
+
+ ///
+ public override int MaxAmmo
+ {
+ set
+ {
+ CylinderModule._defaultCapacity = value;
+ Resync();
+ }
+ }
+
+ ///
+ public override int ConstantMaxAmmo => CylinderModule._defaultCapacity;
+
+ ///
+ /// Gets or sets an used for this magazine.
+ ///
+ public override AmmoType AmmoType
+ {
+ get => Magazine.AmmoType.GetAmmoType();
+ set => CylinderModule.AmmoType = value.GetItemType();
+ }
+
+ ///
+ /// Gets a of chambers in cylindric magazine.
+ ///
+ public IEnumerable Chambers => CylinderAmmoModule.GetChambersArrayForSerial(CylinderModule.ItemSerial, MaxAmmo).Select(baseChamber => new Chamber(baseChamber));
+
+ ///
+ public override void Resync() => CylinderModule._needsResyncing = true;
+
+ ///
+ /// Rotates cylindric magazine by fixed rotatins.
+ ///
+ /// Rotations count.
+ public void Rotate(int rotations) => CylinderModule.RotateCylinder(rotations);
+
+ ///
+ /// A basic wrapper for chamber in cylinder magazine.
+ ///
+ public class Chamber
+ {
+ private CylinderAmmoModule.Chamber baseChamber;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Basic class.
+ internal Chamber(CylinderAmmoModule.Chamber baseChamber)
+ {
+ this.baseChamber = baseChamber;
+ }
+
+ ///
+ /// Gets or sets an state for current chamber.
+ ///
+ public RevolverChamberState State
+ {
+ get => (RevolverChamberState)baseChamber.ContextState;
+ set => baseChamber.ContextState = (CylinderAmmoModule.ChamberState)value;
+ }
+ }
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/NormalMagazine.cs b/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/NormalMagazine.cs
new file mode 100644
index 000000000..dd8cfaa21
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/NormalMagazine.cs
@@ -0,0 +1,88 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.FirearmModules.Primary
+{
+ using System;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Extensions;
+
+ using InventorySystem.Items.Firearms.Modules;
+
+ ///
+ /// Basic realization of .
+ ///
+ public class NormalMagazine : PrimaryMagazine
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// target .
+ public NormalMagazine(MagazineModule magazine)
+ : base(magazine)
+ {
+ MagazineModule = magazine;
+ }
+
+ ///
+ /// Gets an original .
+ ///
+ public MagazineModule MagazineModule { get; }
+
+ ///
+ public override Firearm Firearm => Item.Get(MagazineModule.Firearm);
+
+ ///
+ public override int MaxAmmo
+ {
+ set => MagazineModule._defaultCapacity = value;
+ }
+
+ ///
+ public override int ConstantMaxAmmo => MagazineModule._defaultCapacity;
+
+ ///
+ public override AmmoType AmmoType
+ {
+ get => Magazine.AmmoType.GetAmmoType();
+
+ set => MagazineModule._ammoType = value.GetItemType();
+ }
+
+ ///
+ /// Gets or sets a value indicating whether magazine is inserted.
+ ///
+ public bool MagazineInserted
+ {
+ get => MagazineModule.MagazineInserted;
+
+ set
+ {
+ MagazineModule.MagazineInserted = value;
+ Resync();
+ }
+ }
+
+ ///
+ /// Removes magazine from current .
+ ///
+ ///
+ /// Affects on actual ammo count.
+ /// Removes all ammo from magazine.
+ ///
+ public void RemoveMagazine() => MagazineModule.ServerRemoveMagazine();
+
+ ///
+ /// Inserts current magazine from current .
+ ///
+ public void InsertMagazine() => MagazineModule.ServerInsertEmptyMagazine();
+
+ ///
+ public override void Resync() => MagazineModule.ServerResyncData();
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/PrimaryMagazine.cs b/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/PrimaryMagazine.cs
new file mode 100644
index 000000000..39ff42855
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/FirearmModules/Primary/PrimaryMagazine.cs
@@ -0,0 +1,63 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items.FirearmModules.Primary
+{
+ using System;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Extensions;
+
+ using InventorySystem.Items.Firearms.Modules;
+
+ ///
+ /// Basic abstraction of whose are logically used to be a primary magazines.
+ ///
+ public abstract class PrimaryMagazine : Magazine
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// target .
+ public PrimaryMagazine(IPrimaryAmmoContainerModule magazine)
+ : base(magazine)
+ {
+ Magazine = magazine;
+ }
+
+ ///
+ /// Gets an original .
+ ///
+ public IPrimaryAmmoContainerModule Magazine { get; }
+
+ ///
+ public override int MaxAmmo => Magazine.AmmoMax;
+
+ ///
+ /// Gets a max avaible ammo count in magazine without attachments.
+ ///
+ public abstract int ConstantMaxAmmo { get; }
+
+ ///
+ public override int Ammo
+ {
+ get => Magazine.AmmoStored;
+
+ set
+ {
+ int modifyCount = Math.Max(0, value) - Ammo;
+ Magazine.ServerModifyAmmo(modifyCount);
+ Resync();
+ }
+ }
+
+ ///
+ /// Gets or sets an used for this magazine.
+ ///
+ public abstract AmmoType AmmoType { get; set; }
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/Flashlight.cs b/EXILED/Exiled.API/Features/Items/Flashlight.cs
index 7cdf432bf..93a3876ca 100644
--- a/EXILED/Exiled.API/Features/Items/Flashlight.cs
+++ b/EXILED/Exiled.API/Features/Items/Flashlight.cs
@@ -45,14 +45,6 @@ internal Flashlight(ItemType type)
/// Can be or .
public new ToggleableLightItemBase Base { get; }
- ///
- [Obsolete("Use IsEmittingLight instead.")]
- public bool Active
- {
- get => IsEmittingLight;
- set => IsEmittingLight = value;
- }
-
///
/// Gets or sets a value indicating whether the item is emitting light.
///
diff --git a/EXILED/Exiled.API/Features/Items/Item.cs b/EXILED/Exiled.API/Features/Items/Item.cs
index 7ba1afab5..e5207c99f 100644
--- a/EXILED/Exiled.API/Features/Items/Item.cs
+++ b/EXILED/Exiled.API/Features/Items/Item.cs
@@ -13,10 +13,10 @@ namespace Exiled.API.Features.Items
using Exiled.API.Features.Core;
using Exiled.API.Features.Pickups;
using Exiled.API.Interfaces;
-
using InventorySystem;
using InventorySystem.Items;
using InventorySystem.Items.Armor;
+ using InventorySystem.Items.Autosync;
using InventorySystem.Items.Firearms.Ammo;
using InventorySystem.Items.Jailbird;
using InventorySystem.Items.Keycards;
@@ -26,6 +26,7 @@ namespace Exiled.API.Features.Items
using InventorySystem.Items.ThrowableProjectiles;
using InventorySystem.Items.ToggleableLights;
using InventorySystem.Items.Usables;
+ using InventorySystem.Items.Usables.Scp1344;
using InventorySystem.Items.Usables.Scp1576;
using InventorySystem.Items.Usables.Scp244;
using InventorySystem.Items.Usables.Scp330;
@@ -50,6 +51,10 @@ public class Item : TypeCastObject, IWrapper
public Item(ItemBase itemBase)
{
Base = itemBase;
+
+ if (Base is ModularAutosyncItem modularItem && modularItem.InstantiationStatus is AutosyncInstantiationStatus.Template or AutosyncInstantiationStatus.SimulatedInstance)
+ return;
+
BaseToItem.Add(itemBase, this);
if (Base.ItemSerial is 0 && itemBase.Owner != null)
@@ -157,7 +162,12 @@ public ushort Serial
///
/// Gets a value indicating whether this item is a weapon.
///
- public bool IsWeapon => this is Firearm;
+ public bool IsWeapon => this is Firearm || Type is ItemType.Jailbird or ItemType.MicroHID;
+
+ ///
+ /// Gets a value indicating whether or not this item is a firearm.
+ ///
+ public bool IsFirearm => this is Firearm;
///
/// Gets a value indicating whether this item emits light.
@@ -174,6 +184,15 @@ public ushort Serial
///
public Player Owner => Player.Get(Base.Owner) ?? Server.Host;
+ ///
+ /// Gets or sets a reason for adding this item to the inventory.
+ ///
+ public ItemAddReason AddReason
+ {
+ get => Base.ServerAddReason;
+ set => Base.ServerAddReason = value;
+ }
+
///
/// Gets an existing or creates a new instance of one.
///
@@ -196,6 +215,7 @@ public static Item Get(ItemBase itemBase)
Scp330Bag scp330Bag => new Scp330(scp330Bag),
Scp244Item scp244Item => new Scp244(scp244Item),
Scp1576Item scp1576 => new Scp1576(scp1576),
+ Scp1344Item scp1344 => new Scp1344(scp1344),
BaseConsumable consumable => new Consumable(consumable),
_ => new Usable(usable),
},
@@ -213,7 +233,7 @@ public static Item Get(ItemBase itemBase)
Scp018Projectile => new Scp018(throwable),
_ => new Throwable(throwable),
},
- _ => new Item(itemBase),
+ _ => new(itemBase),
};
}
@@ -233,6 +253,15 @@ public static T Get(ItemBase itemBase)
/// Returns the Item found or if not found.
public static Item Get(ushort serial) => List.FirstOrDefault(x => x.Serial == serial);
+ ///
+ /// Gets the Item belonging to the specified serial.
+ ///
+ /// The Item serial.
+ /// The specified type.
+ /// Returns the Item found or if not found.
+ public static T Get(ushort serial)
+ where T : Item => Get(serial) as T;
+
///
/// Creates a new with the proper inherited subclass.
///
@@ -254,6 +283,7 @@ public static T Get(ItemBase itemBase)
/// - SCP-330 can be casted to .
/// - SCP-2176 can be casted to the class.
/// - SCP-1576 can be casted to the class.
+ /// - SCP-1344 can be casted to the class.
/// - Jailbird can be casted to the class.
///
///
@@ -282,6 +312,7 @@ ItemType.KeycardGuard or ItemType.KeycardJanitor or ItemType.KeycardO5 or ItemTy
ItemType.SCP330 => new Scp330(),
ItemType.SCP2176 => new Scp2176(owner),
ItemType.SCP1576 => new Scp1576(),
+ ItemType.SCP1344 => new Scp1344(),
ItemType.Jailbird => new Jailbird(),
_ => new Item(type),
};
@@ -307,6 +338,7 @@ ItemType.KeycardGuard or ItemType.KeycardJanitor or ItemType.KeycardO5 or ItemTy
/// - SCP-330 can be casted to .
/// - SCP-2176 can be casted to the class.
/// - SCP-1576 can be casted to the class.
+ /// - SCP-1344 can be casted to the class.
/// - Jailbird can be casted to the class.
///
///
@@ -338,11 +370,11 @@ public static Item Create(ItemType type, Player owner = null)
/// The rotation of the item.
/// Whether the should be initially spawned.
/// The created .
- public virtual Pickup CreatePickup(Vector3 position, Quaternion rotation = default, bool spawn = true)
+ public virtual Pickup CreatePickup(Vector3 position, Quaternion? rotation = null, bool spawn = true)
{
PickupSyncInfo info = new(Type, Weight, Serial);
- ItemPickupBase ipb = InventoryExtensions.ServerCreatePickup(Base, info, position, rotation);
+ ItemPickupBase ipb = InventoryExtensions.ServerCreatePickup(Base, info, position, rotation ?? Quaternion.identity);
Base.OnRemoved(ipb);
diff --git a/EXILED/Exiled.API/Features/Items/Jailbird.cs b/EXILED/Exiled.API/Features/Items/Jailbird.cs
index a560abba5..b7a48eae6 100644
--- a/EXILED/Exiled.API/Features/Items/Jailbird.cs
+++ b/EXILED/Exiled.API/Features/Items/Jailbird.cs
@@ -11,6 +11,7 @@ namespace Exiled.API.Features.Items
using Exiled.API.Features.Pickups;
using Exiled.API.Interfaces;
+ using InventorySystem.Items;
using InventorySystem.Items.Autosync;
using InventorySystem.Items.Jailbird;
using Mirror;
@@ -152,13 +153,14 @@ public float GetDamage(JailbirdWearState wearState)
public void Break()
{
WearState = JailbirdWearState.Broken;
- using (new AutosyncRpc(Base, true, out NetworkWriter networkWriter))
+ ItemIdentifier identifier = new(Base);
+ using (new AutosyncRpc(identifier, out NetworkWriter networkWriter))
{
networkWriter.WriteByte(0);
networkWriter.WriteByte((byte)JailbirdWearState.Broken);
}
- using (new AutosyncRpc(Base, true, out NetworkWriter networkWriter2))
+ using (new AutosyncRpc(identifier, out NetworkWriter networkWriter2))
{
networkWriter2.WriteByte(1);
}
diff --git a/EXILED/Exiled.API/Features/Items/MicroHid.cs b/EXILED/Exiled.API/Features/Items/MicroHid.cs
index 80bde0708..f83dab90d 100644
--- a/EXILED/Exiled.API/Features/Items/MicroHid.cs
+++ b/EXILED/Exiled.API/Features/Items/MicroHid.cs
@@ -7,9 +7,15 @@
namespace Exiled.API.Features.Items
{
- using Exiled.API.Interfaces;
+ using System;
+ using System.Reflection;
+ using Exiled.API.Features.Pickups;
+ using Exiled.API.Interfaces;
using InventorySystem.Items.MicroHID;
+ using InventorySystem.Items.MicroHID.Modules;
+
+ using Random = UnityEngine.Random;
///
/// A wrapper class for .
@@ -34,13 +40,34 @@ internal MicroHid()
{
}
+ ///
+ /// Gets the of the MicroHID.
+ ///
+ public EnergyManagerModule EnergyManager => Base.EnergyManager;
+
+ ///
+ /// Gets the of the MicroHID.
+ ///
+ public BrokenSyncModule BrokenModule => Base.BrokenSync;
+
+ ///
+ /// Gets the of the MicroHID.
+ ///
+ public InputSyncModule InputModule => Base.InputSync;
+
+ ///
+ /// Gets the of the MicroHID.
+ ///
+ public CycleController CycleController => Base.CycleController;
+
///
/// Gets or sets the remaining energy in the MicroHID.
///
+ /// Maximum energy is 1. Minimum energy is 0.
public float Energy
{
- get => Base.RemainingEnergy;
- set => Base.RemainingEnergy = value;
+ get => EnergyManager.Energy;
+ set => EnergyManager.ServerSetEnergy(Serial, value);
}
///
@@ -49,23 +76,128 @@ public float Energy
public new MicroHIDItem Base { get; }
///
- /// Gets or sets the .
+ /// Gets or sets a value indicating whether the MicroHID is broken.
///
- public HidState State
+ public bool IsBroken
{
- get => Base.State;
- set => Base.State = value;
+ get => BrokenModule.Broken;
+ set => BrokenModule.ServerSetBroken(Serial, value);
}
+ ///
+ /// Gets a time when this was broken.
+ ///
+ /// A time when this was broken, or 0 if it is not broken.
+ public float BrokeTime => BrokenSyncModule.TryGetBrokenElapsed(Serial, out float time) ? time : 0;
+
+ ///
+ /// Gets or sets the .
+ ///
+ public MicroHidPhase State
+ {
+ get => CycleController.Phase;
+ set => CycleController.Phase = value;
+ }
+
+ ///
+ /// Gets or sets progress of winging up.
+ ///
+ /// A value between 0 and 1.
+ public float WindUpProgress
+ {
+ get => CycleController.ServerWindUpProgress;
+ set => CycleController.ServerWindUpProgress = value;
+ }
+
+ ///
+ /// Gets or sets the last received .
+ ///
+ public MicroHidFiringMode LastFiringMode
+ {
+ get => CycleController.LastFiringMode;
+ set => CycleController.LastFiringMode = value;
+ }
+
+ ///
+ /// Gets or sets the last received .
+ ///
+ public InputSyncModule.SyncData LastReceived
+ {
+ get => InputModule._lastReceived;
+ set => InputModule._lastReceived = value;
+ }
+
+ ///
+ /// Gets a value indicating whether the is .
+ ///
+ public bool IsPrimary => InputModule.Primary;
+
///
/// Starts firing the MicroHID.
///
- public void Fire() => Base.Fire();
+ /// Fire mode.
+ public void Fire(MicroHidFiringMode firingMode = MicroHidFiringMode.PrimaryFire)
+ {
+ switch (firingMode)
+ {
+ case MicroHidFiringMode.PrimaryFire:
+ if (TryGetFireController(MicroHidFiringMode.PrimaryFire, out PrimaryFireModeModule primaryFireModeModule))
+ primaryFireModeModule.ServerFire();
+ break;
+ case MicroHidFiringMode.ChargeFire:
+ if (TryGetFireController(MicroHidFiringMode.ChargeFire, out ChargeFireModeModule chargeFireModeModule))
+ chargeFireModeModule.ServerFire();
+ break;
+ default:
+ if (TryGetFireController(MicroHidFiringMode.BrokenFire, out BrokenFireModeModule brokenFireModeModule))
+ brokenFireModeModule.ServerFire();
+ break;
+ }
+ }
///
/// Recharges the MicroHID.
///
- public void Recharge() => Base.Recharge();
+ public void Recharge()
+ {
+ if (IsBroken)
+ Energy = Random.value;
+ else
+ Energy = 1;
+ }
+
+ ///
+ /// Explodes the MicroHID.
+ ///
+ public void Explode()
+ {
+ if (TryGetFireController(MicroHidFiringMode.ChargeFire, out ChargeFireModeModule module))
+ module.ServerExplode();
+ }
+
+ ///
+ /// Tries to get a assosiated with the specified .
+ ///
+ /// Target firing mode.
+ /// Found module or null.
+ /// Type of module.
+ /// true if module was found, false otherwise.
+ public bool TryGetFireController(MicroHidFiringMode firingMode, out T module)
+ where T : FiringModeControllerModule
+ {
+ if (CycleController._firingModeControllers.Count == 0)
+ CycleController.RecacheFiringModes(Base);
+
+ module = (T)CycleController._firingModeControllers.Find(x => x.AssignedMode == firingMode);
+ return module != null;
+ }
+
+ ///
+ /// Tries to get a assosiated with the last .
+ ///
+ /// Found module or null.
+ /// true if module was found, false otherwise.
+ public bool TryGetLastFireController(out FiringModeControllerModule module) => TryGetFireController(LastFiringMode, out module);
///
/// Clones current object.
diff --git a/EXILED/Exiled.API/Features/Items/Scp1344.cs b/EXILED/Exiled.API/Features/Items/Scp1344.cs
new file mode 100644
index 000000000..460aeb8c0
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Items/Scp1344.cs
@@ -0,0 +1,89 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Items
+{
+ using Exiled.API.Interfaces;
+
+ using InventorySystem.Items.Usables;
+ using InventorySystem.Items.Usables.Scp1344;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
+
+ ///
+ /// A wrapper class for .
+ ///
+ public class Scp1344 : Usable, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The base class.
+ public Scp1344(Scp1344Item itemBase)
+ : base(itemBase)
+ {
+ Base = itemBase;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ internal Scp1344()
+ : this((Scp1344Item)Server.Host.Inventory.CreateItemInstance(new(ItemType.SCP1344, 0), false))
+ {
+ }
+
+ ///
+ /// Gets the that this class is encapsulating.
+ ///
+ public new Scp1344Item Base { get; }
+
+ ///
+ /// Gets a value indicating whether the item is worn.
+ ///
+ public bool IsWorn => Base.IsWorn;
+
+ ///
+ /// Gets a value indicating whether it can be started to use.
+ ///
+ public bool CanStartUsing => Base.CanStartUsing;
+
+ ///
+ /// Gets or sets the status of Scp1344.
+ ///
+ public Scp1344Status Status
+ {
+ get => Base.Status;
+ set => Base.Status = value;
+ }
+
+ ///
+ /// Forcefully deactivate SCP-1344.
+ ///
+ /// Whether or not 1344 should be dropped.
+ public void Deactivate(bool dropItem = false)
+ {
+ if (Status is not(Scp1344Status.Active or Scp1344Status.Stabbing or Scp1344Status.Dropping))
+ {
+ return;
+ }
+
+ Base.Owner.DisableWearables(WearableElements.Scp1344Goggles);
+ Base.ActivateFinalEffects();
+ Status = Scp1344Status.Idle;
+
+ if (dropItem)
+ {
+ Base.ServerDropItem(true);
+ }
+ }
+
+ ///
+ /// Forcefully activated SCP-1344.
+ ///
+ public void Actived() => Status = Scp1344Status.Stabbing;
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Items/Scp244.cs b/EXILED/Exiled.API/Features/Items/Scp244.cs
index 1ed62113c..0cfea6c3a 100644
--- a/EXILED/Exiled.API/Features/Items/Scp244.cs
+++ b/EXILED/Exiled.API/Features/Items/Scp244.cs
@@ -82,11 +82,11 @@ public bool Primed
/// The rotation of the item.
/// Whether the should be initially spawned.
/// The created .
- public override Pickup CreatePickup(Vector3 position, Quaternion rotation = default, bool spawn = true)
+ public override Pickup CreatePickup(Vector3 position, Quaternion? rotation = null, bool spawn = true)
{
PickupSyncInfo info = new(Type, Weight, Serial);
- Scp244DeployablePickup ipb = (Scp244DeployablePickup)InventoryExtensions.ServerCreatePickup(Base, info, position, rotation);
+ Scp244DeployablePickup ipb = (Scp244DeployablePickup)InventoryExtensions.ServerCreatePickup(Base, info, position, rotation ?? Quaternion.identity);
Base.OnRemoved(ipb);
diff --git a/EXILED/Exiled.API/Features/Items/Scp330.cs b/EXILED/Exiled.API/Features/Items/Scp330.cs
index 159e6ccac..38c9ded76 100644
--- a/EXILED/Exiled.API/Features/Items/Scp330.cs
+++ b/EXILED/Exiled.API/Features/Items/Scp330.cs
@@ -87,11 +87,6 @@ internal Scp330()
///
public CandyKindID ExposedType { get; set; } = CandyKindID.None;
- ///
- /// Gets or sets the candy that will be added to the bag. Used for events.
- ///
- internal CandyKindID CandyToAdd { get; set; } = CandyKindID.None;
-
///
/// Adds a specific candy to the bag.
///
@@ -245,11 +240,11 @@ public IEnumerable DropCandy(CandyKindID type, bool dropAll = fals
/// The rotation to give the item.
/// Whether the should be initially spawned.
/// The created .
- public override Pickup CreatePickup(Vector3 position, Quaternion rotation = default, bool spawn = true)
+ public override Pickup CreatePickup(Vector3 position, Quaternion? rotation = null, bool spawn = true)
{
PickupSyncInfo info = new(Type, Weight, Serial);
- InventorySystem.Items.Usables.Scp330.Scp330Pickup ipb = (InventorySystem.Items.Usables.Scp330.Scp330Pickup)InventoryExtensions.ServerCreatePickup(Base, info, position, rotation);
+ InventorySystem.Items.Usables.Scp330.Scp330Pickup ipb = (InventorySystem.Items.Usables.Scp330.Scp330Pickup)InventoryExtensions.ServerCreatePickup(Base, info, position, rotation ?? Quaternion.identity);
Base.OnRemoved(ipb);
diff --git a/EXILED/Exiled.API/Features/Items/Usable.cs b/EXILED/Exiled.API/Features/Items/Usable.cs
index fe07f3c24..6ba68e2cb 100644
--- a/EXILED/Exiled.API/Features/Items/Usable.cs
+++ b/EXILED/Exiled.API/Features/Items/Usable.cs
@@ -109,11 +109,11 @@ public float RemainingCooldown
/// The rotation of the item.
/// Whether the should be initially spawned.
/// The created .
- public override Pickup CreatePickup(Vector3 position, Quaternion rotation = default, bool spawn = true)
+ public override Pickup CreatePickup(Vector3 position, Quaternion? rotation = null, bool spawn = true)
{
PickupSyncInfo info = new(Type, Weight, Serial);
- ItemPickupBase ipb = InventoryExtensions.ServerCreatePickup(Base, info, position, rotation);
+ ItemPickupBase ipb = InventoryExtensions.ServerCreatePickup(Base, info, position, rotation ?? Quaternion.identity);
Pickup pickup = Pickup.Get(ipb);
diff --git a/EXILED/Exiled.API/Features/Lift.cs b/EXILED/Exiled.API/Features/Lift.cs
index 04b15f4c3..c38e146a3 100644
--- a/EXILED/Exiled.API/Features/Lift.cs
+++ b/EXILED/Exiled.API/Features/Lift.cs
@@ -21,7 +21,6 @@ namespace Exiled.API.Features
using UnityEngine;
using static Interactables.Interobjects.ElevatorChamber;
- using static Interactables.Interobjects.ElevatorManager;
using Elevator = Interactables.Interobjects.ElevatorDoor;
@@ -33,7 +32,7 @@ public class Lift : IWrapper, IWorldSpace
///
/// A containing all known s and their corresponding .
///
- internal static readonly Dictionary ElevatorChamberToLift = new(8, new ComponentsEqualityComparer());
+ internal static readonly Dictionary ElevatorChamberToLift = new(9, new ComponentsEqualityComparer());
///
/// Internal list that contains all ElevatorDoor for current group.
@@ -121,8 +120,8 @@ public Quaternion Rotation
///
public ElevatorSequence Status
{
- get => Base._curSequence;
- set => Base._curSequence = value;
+ get => Base.CurSequence;
+ set => Base.CurSequence = value;
}
///
@@ -140,7 +139,7 @@ public ElevatorSequence Status
ElevatorGroup.GateB => ElevatorType.GateB,
ElevatorGroup.LczA01 or ElevatorGroup.LczA02 => ElevatorType.LczA,
ElevatorGroup.LczB01 or ElevatorGroup.LczB02 => ElevatorType.LczB,
- ElevatorGroup.Nuke => ElevatorType.Nuke,
+ ElevatorGroup.Nuke01 or ElevatorGroup.Nuke02 => ElevatorType.Nuke,
_ => ElevatorType.Unknown,
};
@@ -162,7 +161,7 @@ public ElevatorSequence Status
///
/// Gets a value indicating whether the lift is locked.
///
- public bool IsLocked => Base.ActiveLocks > 0;
+ public bool IsLocked => Base.ActiveLocksAnyDoors > 0 || Base.ActiveLocksAllDoors > 0;
///
/// Gets or sets the .
@@ -196,12 +195,12 @@ public float AnimationTime
///
/// Gets the .
///
- public int CurrentLevel => Base.CurrentLevel;
+ public int CurrentLevel => Base.DestinationLevel;
///
/// Gets the .
///
- public Doors.ElevatorDoor CurrentDestination => Door.Get(Base.CurrentDestination);
+ public Doors.ElevatorDoor CurrentDestination => Door.Get(Base.DestinationDoor);
///
/// Gets a of which contains all the instances from the specified .
@@ -272,9 +271,8 @@ public static bool TryMeltPlayer(Player player)
/// Tries to start the lift.
///
/// The destination level.
- /// Indicates whether the start will be forced.
- /// if the lift was started successfully; otherwise, .
- public bool TryStart(int level, bool isForced = false) => TrySetDestination(Group, level, isForced);
+ /// Allowing queing.
+ public void TryStart(int level, bool allowQueueing = false) => Base.ServerSetDestination(level, allowQueueing);
///
/// Changes lock of the lift.
@@ -295,12 +293,7 @@ public void ChangeLock(DoorLockReason lockReason)
else
{
door.ChangeLock((DoorLockType)lockReason);
-
- if (CurrentLevel != 1)
- TrySetDestination(Group, 1, true);
}
-
- Base.RefreshLocks(Group, door.Base);
}
}
diff --git a/EXILED/Exiled.API/Features/Map.cs b/EXILED/Exiled.API/Features/Map.cs
index 6f1d288db..081999068 100644
--- a/EXILED/Exiled.API/Features/Map.cs
+++ b/EXILED/Exiled.API/Features/Map.cs
@@ -7,34 +7,26 @@
namespace Exiled.API.Features
{
+#pragma warning disable SA1401
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
- using Decals;
using Enums;
using Exiled.API.Extensions;
using Exiled.API.Features.Hazards;
- using Exiled.API.Features.Lockers;
using Exiled.API.Features.Pickups;
using Exiled.API.Features.Toys;
- using global::Hazards;
using InventorySystem;
- using InventorySystem.Items.Firearms;
- using InventorySystem.Items.Firearms.BasicMessages;
using InventorySystem.Items.Pickups;
using InventorySystem.Items.ThrowableProjectiles;
using Items;
using LightContainmentZoneDecontamination;
using MapGeneration;
- using MapGeneration.Distributors;
- using PlayerRoles.PlayableScps.Scp939;
using PlayerRoles.Ragdolls;
- using RelativePositioning;
using UnityEngine;
using Utils;
- using Utils.Networking;
using Object = UnityEngine.Object;
@@ -44,24 +36,14 @@ namespace Exiled.API.Features
public static class Map
{
///
- /// A list of s on the map.
+ /// Gets a list of s on the map.
///
- internal static readonly List TeleportsValue = new(8);
+ internal static List TeleportsValue = new();
private static AmbientSoundPlayer ambientSoundPlayer;
private static SqueakSpawner squeakSpawner;
- ///
- /// Gets the tantrum prefab.
- ///
- public static TantrumEnvironmentalHazard TantrumPrefab => TantrumHazard.TantrumPrefab; // TODO: Remove this.
-
- ///
- /// Gets the amnestic cloud prefab.
- ///
- public static Scp939AmnesticCloudInstance AmnesticCloudPrefab => AmnesticCloudHazard.AmnesticCloudPrefab; // TODO: Remove this.
-
///
/// Gets a value indicating whether decontamination has begun in the light containment zone.
///
@@ -79,20 +61,6 @@ DecontaminationController.Singleton.NetworkDecontaminationOverride is Decontamin
///
public static ReadOnlyCollection PocketDimensionTeleports { get; } = TeleportsValue.AsReadOnly();
- ///
- /// Gets all objects in the current map.
- ///
- ///
- /// This property is obsolete. Use instead to retrieve a collection of all instances.
- ///
- [Obsolete("Use Locker.List instead.")]
- public static ReadOnlyCollection Lockers { get; } = Features.Lockers.Locker.BaseToExiledLockers.Keys.ToList().AsReadOnly();
-
- ///
- /// Gets all objects.
- ///
- public static ReadOnlyCollection Toys => AdminToy.BaseToAdminToy.Values.ToList().AsReadOnly(); // TODO: Obsolete it and make people use AdminToy.List
-
///
/// Gets or sets the current seed of the map.
///
@@ -102,7 +70,7 @@ public static int Seed
set
{
if (!SeedSynchronizer.MapGenerated)
- SeedSynchronizer._singleton.Network_syncSeed = value;
+ SeedSynchronizer.Seed = value;
}
}
@@ -121,7 +89,7 @@ public static bool IsDecontaminationEnabled
///
/// Gets the .
///
- public static AmbientSoundPlayer AmbientSoundPlayer => ambientSoundPlayer ??= ReferenceHub.HostHub.GetComponent();
+ public static AmbientSoundPlayer AmbientSoundPlayer => ambientSoundPlayer ??= ReferenceHub._hostHub.GetComponent();
///
/// Gets the .
@@ -229,16 +197,6 @@ public static void ResetLightsColor()
light.NetworkOverrideColor = Color.clear;
}
- ///
- /// Gets a random object from the current map.
- ///
- ///
- /// This method is obsolete. Use instead to get a random instance.
- ///
- /// A randomly selected object.
- [Obsolete("Use Locker.Random() instead.")]
- public static MapGeneration.Distributors.Locker GetRandomLocker() => Lockers.GetRandomValue();
-
///
/// Gets a random .
///
@@ -267,15 +225,6 @@ public static void PlayAmbientSound(int id)
AmbientSoundPlayer.RpcPlaySound(AmbientSoundPlayer.clips[id].index);
}
- ///
- /// Places a Tantrum (SCP-173's ability) in the indicated position.
- ///
- /// The position where you want to spawn the Tantrum.
- /// Whether the tantrum will apply the effect.
- /// If is , the tantrum is moved slightly up from its original position. Otherwise, the collision will not be detected and the slowness will not work.
- /// The instance.
- public static TantrumHazard PlaceTantrum(Vector3 position, bool isActive = true) => TantrumHazard.PlaceTantrum(position, isActive); // TODO: Remove this.
-
///
/// Destroy all objects.
///
@@ -319,7 +268,7 @@ public static void CleanAllRagdolls(IEnumerable ragDolls)
///
/// The position of the blood decal.
/// The direction of the blood decal.
- public static void PlaceBlood(Vector3 position, Vector3 direction) => new GunDecalMessage(position, direction, DecalPoolType.Blood).SendToAuthenticated(0);
+ public static void PlaceBlood(Vector3 position, Vector3 direction) => _ = 0; /* new GunDecalMessage(position, direction, DecalPoolType.Blood).SendToAuthenticated(0);*/ // TODO: Not finish
///
/// Gets all the near cameras.
@@ -380,15 +329,17 @@ public static void ExplodeEffect(Vector3 position, ProjectileType projectileType
/// The audio clip ID to play.
public static void PlayGunSound(Vector3 position, ItemType firearmType, byte maxDistance = 45, byte audioClipId = 0)
{
+ // TODO: Not finish
+ /*
GunAudioMessage msg = new()
{
Weapon = firearmType,
AudioClipId = audioClipId,
MaxDistance = maxDistance,
- ShooterHub = ReferenceHub.HostHub,
+ ShooterHub = ReferenceHub._hostHub,
ShooterPosition = new RelativePosition(position),
};
- msg.SendToAuthenticated();
+ msg.SendToAuthenticated();*/
}
///
@@ -413,9 +364,9 @@ internal static void ClearCache()
Ragdoll.BasicRagdollToRagdoll.Clear();
- Items.Firearm.ItemTypeToFirearmInstance.Clear();
- Items.Firearm.BaseCodesValue.Clear();
- Items.Firearm.AvailableAttachmentsValue.Clear();
+ Firearm.ItemTypeToFirearmInstance.Clear();
+ Firearm.BaseCodesValue.Clear();
+ Firearm.AvailableAttachmentsValue.Clear();
}
}
}
diff --git a/EXILED/Exiled.API/Features/Npc.cs b/EXILED/Exiled.API/Features/Npc.cs
index 28ee0d117..4055dfa6a 100644
--- a/EXILED/Exiled.API/Features/Npc.cs
+++ b/EXILED/Exiled.API/Features/Npc.cs
@@ -15,10 +15,12 @@ namespace Exiled.API.Features
using CentralAuth;
using CommandSystem;
+ using CommandSystem.Commands.RemoteAdmin.Dummies;
using Exiled.API.Enums;
using Exiled.API.Features.Components;
using Exiled.API.Features.Roles;
using Footprinting;
+ using GameCore;
using MEC;
using Mirror;
using PlayerRoles;
@@ -46,7 +48,7 @@ public Npc(GameObject gameObject)
///
/// Gets a list of Npcs.
///
- public static new List List => Player.List.OfType().ToList();
+ public static new IReadOnlyCollection List => Dictionary.Values.OfType().ToList();
///
/// Gets or sets the player's position.
@@ -62,6 +64,113 @@ public override Vector3 Position
}
}
+ ///
+ /// Gets or sets the player being followed.
+ ///
+ /// The npc must have .
+ public Player? FollowedPlayer
+ {
+ get => !GameObject.TryGetComponent(out PlayerFollower follower) ? null : Player.Get(follower._hubToFollow);
+
+ set
+ {
+ if (!GameObject.TryGetComponent(out PlayerFollower follower))
+ {
+ GameObject.AddComponent()._hubToFollow = value?.ReferenceHub;
+ return;
+ }
+
+ follower._hubToFollow = value?.ReferenceHub;
+ }
+ }
+
+ ///
+ /// Gets or sets the Max Distance of the npc.
+ ///
+ /// The npc must have .
+ public float? MaxDistance
+ {
+ get
+ {
+ if (!GameObject.TryGetComponent(out PlayerFollower follower))
+ return null;
+
+ return follower._maxDistance;
+ }
+
+ set
+ {
+ if(!value.HasValue)
+ return;
+
+ if (!GameObject.TryGetComponent(out PlayerFollower follower))
+ {
+ GameObject.AddComponent()._maxDistance = value.Value;
+ return;
+ }
+
+ follower._maxDistance = value.Value;
+ }
+ }
+
+ ///
+ /// Gets or sets the Min Distance of the npc.
+ ///
+ /// The npc must have .
+ public float? MinDistance
+ {
+ get
+ {
+ if (!GameObject.TryGetComponent(out PlayerFollower follower))
+ return null;
+
+ return follower._minDistance;
+ }
+
+ set
+ {
+ if(!value.HasValue)
+ return;
+
+ if (!GameObject.TryGetComponent(out PlayerFollower follower))
+ {
+ GameObject.AddComponent()._minDistance = value.Value;
+ return;
+ }
+
+ follower._minDistance = value.Value;
+ }
+ }
+
+ ///
+ /// Gets or sets the Speed of the npc.
+ ///
+ /// The npc must have .
+ public float? Speed
+ {
+ get
+ {
+ if (!GameObject.TryGetComponent(out PlayerFollower follower))
+ return null;
+
+ return follower._speed;
+ }
+
+ set
+ {
+ if(!value.HasValue)
+ return;
+
+ if (!GameObject.TryGetComponent(out PlayerFollower follower))
+ {
+ GameObject.AddComponent()._speed = value.Value;
+ return;
+ }
+
+ follower._speed = value.Value;
+ }
+ }
+
///
/// Retrieves the NPC associated with the specified ReferenceHub.
///
@@ -137,74 +246,19 @@ public override Vector3 Position
///
/// The name of the NPC.
/// The RoleTypeId of the NPC.
- /// The player ID of the NPC.
- /// The userID of the NPC.
- /// The position to spawn the NPC.
- /// The spawned.
- [Obsolete("This metod is marked as obsolet due to a bug that make player have the same id. Use Npc.Spawn(string) instead")]
- public static Npc Spawn(string name, RoleTypeId role, int id = 0, string userId = PlayerAuthenticationManager.DedicatedId, Vector3? position = null)
+ /// The position where the NPC should spawn.
+ /// Docs4.
+ public static Npc Spawn(string name, RoleTypeId role, Vector3 position)
{
- GameObject newObject = UnityEngine.Object.Instantiate(Mirror.NetworkManager.singleton.playerPrefab);
-
- Npc npc = new(newObject)
- {
- IsNPC = true,
- };
-
- if (!RecyclablePlayerId.FreeIds.Contains(id) && RecyclablePlayerId._autoIncrement >= id)
- {
- Log.Warn($"{Assembly.GetCallingAssembly().GetName().Name} tried to spawn an NPC with a duplicate PlayerID. Using auto-incremented ID instead to avoid an ID clash.");
- id = new RecyclablePlayerId(true).Value;
- }
-
- try
- {
- if (userId == PlayerAuthenticationManager.DedicatedId)
- {
- npc.ReferenceHub.authManager.SyncedUserId = userId;
- try
- {
- npc.ReferenceHub.authManager.InstanceMode = ClientInstanceMode.DedicatedServer;
- }
- catch (Exception e)
- {
- Log.Debug($"Ignore: {e.Message}");
- }
- }
- else
- {
- npc.ReferenceHub.authManager.InstanceMode = ClientInstanceMode.Unverified;
- npc.ReferenceHub.authManager._privUserId = userId == string.Empty ? $"Dummy@localhost" : userId;
- }
- }
- catch (Exception e)
- {
- Log.Debug($"Ignore: {e.Message}");
- }
-
- try
- {
- npc.ReferenceHub.roleManager.InitializeNewRole(RoleTypeId.None, RoleChangeReason.None);
- }
- catch (Exception e)
- {
- Log.Debug($"Ignore: {e.Message}");
- }
-
- FakeConnection fakeConnection = new(id);
- NetworkServer.AddPlayerForConnection(fakeConnection, newObject);
-
- npc.ReferenceHub.nicknameSync.Network_myNickSync = name;
- Dictionary.Add(newObject, npc);
+ Npc npc = new(DummyUtils.SpawnDummy(name));
Timing.CallDelayed(0.5f, () =>
{
- npc.Role.Set(role, SpawnReason.RoundStart, position is null ? RoleSpawnFlags.All : RoleSpawnFlags.AssignInventory);
-
- if (position is not null)
- npc.Position = position.Value;
+ npc.Role.Set(role);
+ npc.Position = position;
});
+ Dictionary.Add(npc.GameObject, npc);
return npc;
}
@@ -214,58 +268,11 @@ public static Npc Spawn(string name, RoleTypeId role, int id = 0, string userId
/// The name of the NPC.
/// The RoleTypeId of the NPC, defaulting to None.
/// Whether the NPC should be ignored by round ending checks.
- /// The userID of the NPC for authentication. Defaults to the Dedicated ID.
/// The position where the NPC should spawn. If null, the default spawn location is used.
/// The spawned.
- public static Npc Spawn(string name, RoleTypeId role = RoleTypeId.None, bool ignored = false, string userId = PlayerAuthenticationManager.DedicatedId, Vector3? position = null)
+ public static Npc Spawn(string name, RoleTypeId role = RoleTypeId.None, bool ignored = false, Vector3? position = null)
{
- GameObject newObject = UnityEngine.Object.Instantiate(Mirror.NetworkManager.singleton.playerPrefab);
-
- Npc npc = new(newObject)
- {
- IsNPC = true,
- };
-
- FakeConnection fakeConnection = new(npc.Id);
-
- try
- {
- if (userId == PlayerAuthenticationManager.DedicatedId)
- {
- npc.ReferenceHub.authManager.SyncedUserId = userId;
- try
- {
- npc.ReferenceHub.authManager.InstanceMode = ClientInstanceMode.DedicatedServer;
- }
- catch (Exception e)
- {
- Log.Debug($"Ignore: {e.Message}");
- }
- }
- else
- {
- npc.ReferenceHub.authManager.InstanceMode = ClientInstanceMode.Unverified;
- npc.ReferenceHub.authManager._privUserId = userId == string.Empty ? $"Dummy-{npc.Id}@localhost" : userId;
- }
- }
- catch (Exception e)
- {
- Log.Debug($"Ignore: {e.Message}");
- }
-
- try
- {
- npc.ReferenceHub.roleManager.InitializeNewRole(RoleTypeId.None, RoleChangeReason.None);
- }
- catch (Exception e)
- {
- Log.Debug($"Ignore: {e.Message}");
- }
-
- NetworkServer.AddPlayerForConnection(fakeConnection, newObject);
-
- npc.ReferenceHub.nicknameSync.Network_myNickSync = name;
- Dictionary.Add(newObject, npc);
+ Npc npc = new(DummyUtils.SpawnDummy(name));
Timing.CallDelayed(0.5f, () =>
{
@@ -278,16 +285,38 @@ public static Npc Spawn(string name, RoleTypeId role = RoleTypeId.None, bool ign
if (ignored)
Round.IgnoredPlayers.Add(npc.ReferenceHub);
+ Dictionary.Add(npc.GameObject, npc);
return npc;
}
///
/// Destroys all NPCs currently spawned.
///
- public static void DestroyAll()
+ public static void DestroyAll() => DummyUtils.DestroyAllDummies();
+
+ ///
+ /// Follow a specific player.
+ ///
+ /// the Player to follow.
+ public void Follow(Player player)
{
- foreach (Npc npc in List)
- npc.Destroy();
+ PlayerFollower follow = !GameObject.TryGetComponent(out PlayerFollower follower) ? GameObject.AddComponent() : follower;
+
+ follow.Init(player.ReferenceHub);
+ }
+
+ ///
+ /// Follow a specific player.
+ ///
+ /// the Player to follow.
+ /// the max distance the npc will go.
+ /// the min distance the npc will go.
+ /// the speed the npc will go.
+ public void Follow(Player player, float maxDistance, float minDistance, float speed = 30f)
+ {
+ PlayerFollower follow = !GameObject.TryGetComponent(out PlayerFollower follower) ? GameObject.AddComponent() : follower;
+
+ follow.Init(player.ReferenceHub, maxDistance, minDistance, speed);
}
///
@@ -298,11 +327,8 @@ public void Destroy()
try
{
Round.IgnoredPlayers.Remove(ReferenceHub);
- NetworkConnectionToClient conn = ReferenceHub.connectionToClient;
- ReferenceHub.OnDestroy();
- CustomNetworkManager.TypedSingleton.OnServerDisconnect(conn);
- Dictionary.Remove(GameObject);
- Object.Destroy(GameObject);
+ Dictionary.Remove(ReferenceHub.gameObject);
+ NetworkServer.Destroy(ReferenceHub.gameObject);
}
catch (Exception e)
{
diff --git a/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs b/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs
index df1fb0c6a..3db97dac8 100644
--- a/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/FirearmPickup.cs
@@ -9,7 +9,12 @@ namespace Exiled.API.Features.Pickups
{
using Exiled.API.Interfaces;
+ using InventorySystem.Items;
using InventorySystem.Items.Firearms;
+ using InventorySystem.Items.Firearms.Attachments;
+ using InventorySystem.Items.Firearms.Modules;
+
+ using UnityEngine;
using BaseFirearm = InventorySystem.Items.Firearms.FirearmPickup;
@@ -36,10 +41,11 @@ internal FirearmPickup(ItemType type)
: base(type)
{
Base = (BaseFirearm)((Pickup)this).Base;
- IsDistributed = true;
+ // TODO not finish
+ /*
if (type is ItemType.ParticleDisruptor && Status.Ammo == 0)
- Status = new FirearmStatus(5, FirearmStatusFlags.MagazineInserted, 0);
+ Status = new FirearmStatus(5, FirearmStatusFlags.MagazineInserted, 0);*/
}
///
@@ -48,54 +54,107 @@ internal FirearmPickup(ItemType type)
public new BaseFirearm Base { get; }
///
- /// Gets or sets a value indicating whether the pickup is already distributed.
+ /// Gets a value indicating whether the pickup is already distributed.
///
- public bool IsDistributed
- {
- get => Base.Distributed;
- set => Base.Distributed = value;
- }
+ public bool IsDistributed { get; internal set; }
///
- /// Gets or sets the .
+ /// Gets or sets a value indicating how much ammo can contain this .
///
- public FirearmStatus Status
- {
- get => Base.NetworkStatus;
- set => Base.NetworkStatus = value;
- }
+ public int MaxAmmo { get; set; }
///
- /// Gets or sets a value indicating how many ammo have this .
+ /// Gets or sets a value indicating how much ammo have this .
///
- public byte Ammo
+ public int Ammo
{
- get => Base.NetworkStatus.Ammo;
- set => Base.NetworkStatus = new(value, Base.NetworkStatus.Flags, Base.NetworkStatus.Attachments);
+ get
+ {
+ if (!AttachmentPreview.TryGetOrAddInstance(Type, out Firearm baseFirearm))
+ return 0;
+
+ Items.Firearm firearm = Items.Item.Get(baseFirearm);
+
+ ushort oldSerial = firearm.Serial;
+
+ firearm.Serial = Serial;
+
+ int ammo = firearm.PrimaryMagazine.Ammo;
+
+ firearm.Serial = oldSerial;
+
+ return ammo;
+ }
+
+ set
+ {
+ if (!AttachmentPreview.TryGetOrAddInstance(Type, out Firearm baseFirearm))
+ return;
+
+ Items.Firearm firearm = Items.Item.Get(baseFirearm);
+
+ ushort oldSerial = firearm.Serial;
+
+ firearm.Serial = Serial;
+
+ firearm.PrimaryMagazine.Ammo = value;
+
+ firearm.Serial = oldSerial;
+ }
}
///
- /// Gets or sets the .
+ /// Gets or sets a ammo drain per shoot.
///
- public FirearmStatusFlags Flags
- {
- get => Base.NetworkStatus.Flags;
- set => Base.NetworkStatus = new(Base.NetworkStatus.Ammo, value, Base.NetworkStatus.Attachments);
- }
+ ///
+ /// Always by default.
+ /// Applied on a high layer nether basegame ammo controllers.
+ ///
+ public int AmmoDrain { get; set; } = 1;
///
/// Gets or sets a value indicating whether the attachment code have this .
///
public uint Attachments
{
- get => Base.NetworkStatus.Attachments;
- set => Base.NetworkStatus = new(Base.NetworkStatus.Ammo, Base.NetworkStatus.Flags, value);
+ get => Base.Worldmodel.AttachmentCode;
+ set => Base.Worldmodel.Setup(Base.CurId, Base.Worldmodel.WorldmodelType, value);
+ }
+
+ ///
+ public override void Spawn()
+ {
+ base.Spawn();
+ if (!IsDistributed)
+ Base.OnDistributed();
}
///
/// Returns the FirearmPickup in a human readable format.
///
/// A string containing FirearmPickup related data.
- public override string ToString() => $"{Type} ({Serial}) [{Weight}] *{Scale}* |{IsDistributed}| -{Ammo}-";
+ public override string ToString() => $"{Type} ({Serial}) [{Weight}] *{Scale}* |{IsDistributed}| -{/*Ammo*/0}-";
+
+ ///
+ internal override void ReadItemInfo(Items.Item item)
+ {
+ Items.Firearm firearm = (Items.Firearm)item;
+ MaxAmmo = firearm.PrimaryMagazine.ConstantMaxAmmo;
+ AmmoDrain = firearm.AmmoDrain;
+ base.ReadItemInfo(item);
+ }
+
+ ///
+ protected override void InitializeProperties(ItemBase itemBase)
+ {
+ base.InitializeProperties(itemBase);
+ if (!(itemBase as Firearm).TryGetModule(out IPrimaryAmmoContainerModule magazine))
+ {
+ Log.Error($"firearm prefab {itemBase.ItemTypeId} doesnt have an primary magazine module(unexpected)");
+ return;
+ }
+
+ MaxAmmo = magazine.AmmoMax;
+ }
}
}
diff --git a/EXILED/Exiled.API/Features/Pickups/MicroHIDPickup.cs b/EXILED/Exiled.API/Features/Pickups/MicroHIDPickup.cs
index 4298fece5..255c32b6a 100644
--- a/EXILED/Exiled.API/Features/Pickups/MicroHIDPickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/MicroHIDPickup.cs
@@ -7,7 +7,9 @@
namespace Exiled.API.Features.Pickups
{
+ using Exiled.API.Features.Items;
using Exiled.API.Interfaces;
+ using InventorySystem.Items.MicroHID.Modules;
using BaseMicroHID = InventorySystem.Items.MicroHID.MicroHIDPickup;
@@ -40,15 +42,107 @@ internal MicroHIDPickup()
///
public new BaseMicroHID Base { get; }
+ ///
+ /// Gets the of this .
+ ///
+ public CycleController CycleController => Base._cycleController;
+
///
/// Gets or sets the MicroHID Energy Level.
///
public float Energy
{
- get => Base.NetworkEnergy;
- set => Base.NetworkEnergy = value;
+ get => EnergyManagerModule.GetEnergy(Serial);
+ set => EnergyManagerModule.SyncEnergy[Serial] = value;
+ }
+
+ ///
+ /// Gets or sets the .
+ ///
+ public MicroHidPhase State
+ {
+ get => CycleController.Phase;
+ set => CycleController.Phase = value;
}
+ ///
+ /// Gets or sets progress of winging up.
+ ///
+ /// A value between 0 and 1.
+ public float WindUpProgress
+ {
+ get => CycleController.ServerWindUpProgress;
+ set => CycleController.ServerWindUpProgress = value;
+ }
+
+ ///
+ /// Gets or sets the last received .
+ ///
+ public MicroHidFiringMode LastFiringMode
+ {
+ get => CycleController.LastFiringMode;
+ set => CycleController.LastFiringMode = value;
+ }
+
+ ///
+ /// Starts firing the MicroHID.
+ ///
+ /// Fire mode.
+ public void Fire(MicroHidFiringMode firingMode = MicroHidFiringMode.PrimaryFire)
+ {
+ switch (firingMode)
+ {
+ case MicroHidFiringMode.PrimaryFire:
+ if (TryGetFireController(MicroHidFiringMode.PrimaryFire, out PrimaryFireModeModule primaryFireModeModule))
+ primaryFireModeModule.ServerFire();
+ break;
+ case MicroHidFiringMode.ChargeFire:
+ if (TryGetFireController(MicroHidFiringMode.ChargeFire, out ChargeFireModeModule chargeFireModeModule))
+ chargeFireModeModule.ServerFire();
+ break;
+ default:
+ if (TryGetFireController(MicroHidFiringMode.BrokenFire, out BrokenFireModeModule brokenFireModeModule))
+ brokenFireModeModule.ServerFire();
+ break;
+ }
+ }
+
+ ///
+ /// Explodes the MicroHID.
+ ///
+ public void Explode()
+ {
+ if (TryGetFireController(MicroHidFiringMode.ChargeFire, out ChargeFireModeModule module))
+ module.ServerExplode();
+ }
+
+ ///
+ /// Tries to get a assosiated with the specified .
+ ///
+ /// Target firing mode.
+ /// Found module or null.
+ /// Type of module.
+ /// true if module was found, false otherwise.
+ public bool TryGetFireController(MicroHidFiringMode firingMode, out T module)
+ where T : FiringModeControllerModule
+ {
+ if (CycleController._firingModeControllers.Count == 0)
+ {
+ module = null;
+ return false;
+ }
+
+ module = (T)CycleController._firingModeControllers.Find(x => x.AssignedMode == firingMode);
+ return module != null;
+ }
+
+ ///
+ /// Tries to get a assosiated with the last .
+ ///
+ /// Found module or null.
+ /// true if module was found, false otherwise.
+ public bool TryGetLastFireController(out FiringModeControllerModule module) => TryGetFireController(LastFiringMode, out module);
+
///
/// Returns the MicroHIDPickup in a human readable format.
///
diff --git a/EXILED/Exiled.API/Features/Pickups/Pickup.cs b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
index 89e9df487..e4ed1b585 100644
--- a/EXILED/Exiled.API/Features/Pickups/Pickup.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Pickup.cs
@@ -128,18 +128,9 @@ internal Pickup(ItemType type)
public Room Room => Room.FindParentRoom(GameObject);
///
- /// Gets or sets the pickup's PhysicsModule.
+ /// Gets the pickup's PhysicsModule.
///
- public PickupStandardPhysics PhysicsModule
- {
- get => Base.PhysicsModule as PickupStandardPhysics;
- [Obsolete("Unsafe.")]
- set
- {
- Base.PhysicsModule.DestroyModule();
- Base.PhysicsModule = value;
- }
- }
+ public PickupStandardPhysics PhysicsModule => Base.PhysicsModule as PickupStandardPhysics;
///
/// Gets or sets the unique serial number for the item.
@@ -246,7 +237,7 @@ public PickupSyncInfo Info
///
/// Gets or sets the previous owner of this item.
///
- ///
+ ///
public Player PreviousOwner
{
get => Player.Get(Base.PreviousOwner.Hub);
@@ -269,7 +260,7 @@ public bool InUse
///
/// Gets or sets the pickup position.
///
- ///
+ ///
public Vector3 Position
{
get => Base.Position;
@@ -288,7 +279,7 @@ public RelativePosition RelativePosition
///
/// Gets or sets the pickup rotation.
///
- ///
+ ///
public Quaternion Rotation
{
get => Base.Rotation;
@@ -541,8 +532,8 @@ public static Pickup Create(ItemType type)
/// The rotation to spawn the .
/// An optional previous owner of the item.
/// The . See documentation of for more information on casting.
- ///
- public static Pickup CreateAndSpawn(ItemType type, Vector3 position, Quaternion rotation, Player previousOwner = null) => Create(type).Spawn(position, rotation, previousOwner);
+ ///
+ public static Pickup CreateAndSpawn(ItemType type, Vector3 position, Quaternion? rotation = null, Player previousOwner = null) => Create(type).Spawn(position, rotation, previousOwner);
///
/// Creates and spawns a .
@@ -553,23 +544,10 @@ public static Pickup Create(ItemType type)
/// An optional previous owner of the item.
/// The specified type.
/// The . See documentation of for more information on casting.
- ///
- public static Pickup CreateAndSpawn(ItemType type, Vector3 position, Quaternion rotation, Player previousOwner = null)
+ ///
+ public static Pickup CreateAndSpawn(ItemType type, Vector3 position, Quaternion? rotation = null, Player previousOwner = null)
where T : Pickup => CreateAndSpawn(type, position, rotation, previousOwner) as T;
- ///
- /// Spawns a .
- ///
- /// The too spawn.
- /// The position to spawn the at.
- /// The rotation to spawn the .
- /// An optional previous owner of the item.
- /// The Spawn.
- ///
- [Obsolete("Use pickup.Spawn(Vector3, Quaternion, Player) instead of this", true)]
- public static Pickup Spawn(Pickup pickup, Vector3 position, Quaternion rotation, Player previousOwner = null)
- => pickup.Spawn(position, rotation, previousOwner);
-
///
/// Returns the amount of time it will take for the provided to pick up this item, based on and active status effects.
///
@@ -589,7 +567,7 @@ public float PickupTimeForPlayer(Player player)
/// Spawns pickup on a server.
///
///
- public void Spawn()
+ public virtual void Spawn()
{
// condition for projectiles
if (!GameObject.activeSelf)
@@ -610,11 +588,11 @@ public void Spawn()
/// The rotation to spawn the .
/// An optional previous owner of the item.
/// The spawned .
- ///
- public Pickup Spawn(Vector3 position, Quaternion rotation, Player previousOwner = null)
+ ///
+ public Pickup Spawn(Vector3 position, Quaternion? rotation = null, Player previousOwner = null)
{
Position = position;
- Rotation = rotation;
+ Rotation = rotation ?? Quaternion.identity;
PreviousOwner = previousOwner;
Spawn();
diff --git a/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs b/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs
index e6bdb2614..17a0691b9 100644
--- a/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Projectiles/Projectile.cs
@@ -114,19 +114,6 @@ internal Projectile(ItemType type)
public static Projectile Create(ProjectileType projectiletype)
where T : Projectile => Create(projectiletype) as T;
- ///
- /// Spawns a .
- ///
- /// The too spawn.
- /// The position to spawn the at.
- /// The rotation to spawn the .
- /// Whether the should be in active state after spawn.
- /// An optional previous owner of the item.
- /// The Spawn.
- [Obsolete("Use pickup.Spawn(Vector3, Quaternion, Player) instead of this", true)]
- public static Projectile Spawn(Projectile pickup, Vector3 position, Quaternion rotation, bool shouldBeActive = true, Player previousOwner = null)
- => pickup.Spawn(position, rotation, shouldBeActive, previousOwner);
-
///
/// Creates and spawns a .
///
@@ -135,8 +122,8 @@ public static Projectile Spawn(Projectile pickup, Vector3 position, Quaternion r
/// The rotation to spawn the .
/// Whether the should be in active state after spawn.
/// An optional previous owner of the item.
- /// The . See documentation of for more information on casting.
- public static Projectile CreateAndSpawn(ProjectileType type, Vector3 position, Quaternion rotation, bool shouldBeActive = true, Player previousOwner = null) => Create(type).Spawn(position, rotation, shouldBeActive, previousOwner);
+ /// The . See documentation of for more information on casting.
+ public static Projectile CreateAndSpawn(ProjectileType type, Vector3 position, Quaternion? rotation = null, bool shouldBeActive = true, Player previousOwner = null) => Create(type).Spawn(position, rotation, shouldBeActive, previousOwner);
///
/// Creates and spawns a .
@@ -147,8 +134,8 @@ public static Projectile Spawn(Projectile pickup, Vector3 position, Quaternion r
/// Whether the should be in active state after spawn.
/// An optional previous owner of the item.
/// The specified type.
- /// The . See documentation of for more information on casting.
- public static Projectile CreateAndSpawn(ProjectileType type, Vector3 position, Quaternion rotation, bool shouldBeActive = true, Player previousOwner = null)
+ /// The . See documentation of for more information on casting.
+ public static Projectile CreateAndSpawn(ProjectileType type, Vector3 position, Quaternion? rotation = null, bool shouldBeActive = true, Player previousOwner = null)
where T : Projectile => CreateAndSpawn(type, position, rotation, shouldBeActive, previousOwner) as T;
///
@@ -164,10 +151,10 @@ public static Projectile CreateAndSpawn(ProjectileType type, Vector3 position
/// Whether the should be in active state after spawn.
/// An optional previous owner of the item.
/// The spawned .
- public Projectile Spawn(Vector3 position, Quaternion rotation, bool shouldBeActive = true, Player previousOwner = null)
+ public Projectile Spawn(Vector3 position, Quaternion? rotation = null, bool shouldBeActive = true, Player previousOwner = null)
{
Position = position;
- Rotation = rotation;
+ Rotation = rotation ?? Quaternion.identity;
PreviousOwner = previousOwner;
Spawn();
diff --git a/EXILED/Exiled.API/Features/Pickups/Projectiles/Scp018Projectile.cs b/EXILED/Exiled.API/Features/Pickups/Projectiles/Scp018Projectile.cs
index 1452a921d..f33d935a9 100644
--- a/EXILED/Exiled.API/Features/Pickups/Projectiles/Scp018Projectile.cs
+++ b/EXILED/Exiled.API/Features/Pickups/Projectiles/Scp018Projectile.cs
@@ -50,18 +50,9 @@ internal Scp018Projectile()
public new BaseScp018Projectile Base { get; }
///
- /// Gets or sets the pickup's PhysicsModule.
+ /// Gets the pickup's PhysicsModule.
///
- public new Scp018Physics PhysicsModule
- {
- get => Base.PhysicsModule as Scp018Physics;
- [Obsolete("Unsafe.", true)]
- set
- {
- Base.PhysicsModule.DestroyModule();
- Base.PhysicsModule = value;
- }
- }
+ public new Scp018Physics PhysicsModule => Base.PhysicsModule as Scp018Physics;
///
/// Gets or sets the pickup's max velocity.
diff --git a/EXILED/Exiled.API/Features/Player.cs b/EXILED/Exiled.API/Features/Player.cs
index 751bd9f80..778f94133 100644
--- a/EXILED/Exiled.API/Features/Player.cs
+++ b/EXILED/Exiled.API/Features/Player.cs
@@ -36,18 +36,18 @@ namespace Exiled.API.Features
using InventorySystem.Disarming;
using InventorySystem.Items;
using InventorySystem.Items.Armor;
- using InventorySystem.Items.Firearms;
using InventorySystem.Items.Firearms.Attachments;
- using InventorySystem.Items.Firearms.BasicMessages;
+ using InventorySystem.Items.Firearms.Modules;
+ using InventorySystem.Items.Firearms.ShotEvents;
using InventorySystem.Items.Usables;
using InventorySystem.Items.Usables.Scp330;
using MapGeneration.Distributors;
using MEC;
using Mirror;
using Mirror.LiteNetLib4Mirror;
- using NorthwoodLib;
using PlayerRoles;
using PlayerRoles.FirstPersonControl;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
using PlayerRoles.RoleAssign;
using PlayerRoles.Spectating;
using PlayerRoles.Voice;
@@ -136,7 +136,7 @@ public Player(GameObject gameObject)
///
/// Gets a list of all 's on the server.
///
- public static IReadOnlyCollection List => Dictionary.Values;
+ public static IReadOnlyCollection List => Dictionary.Values.Where(x => !x.IsNPC).ToList();
///
/// Gets a containing cached and their user ids.
@@ -158,7 +158,7 @@ public Player(GameObject gameObject)
public Dictionary> CustomRoleFriendlyFireMultiplier { get; set; } = DictionaryPool>.Pool.Get();
///
- /// Gets or sets a unique custom role that does not adbide to base game for this player. Used in conjunction with .
+ /// Gets or sets a unique custom role that does not abide to base game for this player. Used in conjunction with .
///
public string UniqueRole { get; set; } = string.Empty;
@@ -211,12 +211,6 @@ private set
///
public bool HasHint => CurrentHint != null;
- ///
- /// Gets the 's , can be null.
- ///
- [Obsolete("Use IVoiceRole::VoiceModule instead.")]
- public VoiceModuleBase VoiceModule => Role is Roles.IVoiceRole voiceRole ? voiceRole.VoiceModule : null;
-
///
/// Gets the 's , can be null.
///
@@ -260,12 +254,6 @@ public int Id
///
public string UserId => referenceHub.authManager.UserId;
- ///
- /// Gets or sets the player's custom user id.
- ///
- [Obsolete("Remove by NW", true)]
- public string CustomUserId { get; set; }
-
///
/// Gets the player's user id without the authentication.
///
@@ -308,9 +296,9 @@ public AuthenticationType AuthenticationType
public bool IsVerified { get; internal set; }
///
- /// Gets or sets a value indicating whether the player is a NPC.
+ /// Gets a value indicating whether the player is a NPC.
///
- public bool IsNPC { get; set; }
+ public bool IsNPC => ReferenceHub.IsDummy;
///
/// Gets a value indicating whether the player has an active CustomName.
@@ -359,7 +347,7 @@ public string CustomInfo
set
{
// NW Client check.
- if (value.Contains('<'))
+ if (value.Contains('<'))
{
foreach (string token in value.Split('<'))
{
@@ -591,7 +579,7 @@ public Role Role
get => role ??= Role.Create(RoleManager.CurrentRole);
internal set
{
- PreviousRole = role.Type;
+ PreviousRole = role?.Type ?? RoleTypeId.None;
role = value;
}
}
@@ -625,7 +613,7 @@ public ScpSpawnPreferences.SpawnPreferences ScpPreferences
///
/// Gets a value indicating whether the player is reloading a weapon.
///
- public bool IsReloading => CurrentItem is Firearm firearm && !firearm.Base.AmmoManagerModule.Standby;
+ public bool IsReloading => CurrentItem is Firearm firearm && !firearm.IsReloading;
///
/// Gets a value indicating whether the player is aiming with a weapon.
@@ -683,11 +671,16 @@ public ScpSpawnPreferences.SpawnPreferences ScpPreferences
public bool IsDead => Role?.IsDead ?? false;
///
- /// Gets a value indicating whether the player's is any NTF rank.
+ /// Gets a value indicating whether the player's is any Foundation Forces.
/// Equivalent to checking the player's .
///
- // TODO: Change logic for FacilityGuard in next major update
- public bool IsNTF => Role?.Team is Team.FoundationForces;
+ public bool IsFoundationForces => Role?.Team is Team.FoundationForces;
+
+ ///
+ /// Gets a value indicating whether the player's is any NTF rank and not a Facility Guard.
+ /// Equivalent to checking the player's .
+ ///
+ public bool IsNTF => Role?.Team is Team.FoundationForces && Role?.Type is not RoleTypeId.FacilityGuard;
///
/// Gets a value indicating whether the player's is any Chaos rank.
@@ -736,6 +729,15 @@ public bool IsBypassModeEnabled
set => ReferenceHub.serverRoles.BypassMode = value;
}
+ ///
+ /// Gets or sets the player's emotion.
+ ///
+ public EmotionPresetType Emotion
+ {
+ get => EmotionSync.GetEmotionPreset(ReferenceHub);
+ set => EmotionSync.ServerSetEmotionPreset(ReferenceHub, value);
+ }
+
///
/// Gets or sets a value indicating whether the player is muted.
///
@@ -826,7 +828,7 @@ public bool IsGodModeEnabled
///
/// Gets the player's unit name.
///
- public string UnitName => Role.Base is PlayerRoles.HumanRole humanRole ? UnitNameMessageHandler.GetReceived(humanRole.AssignedSpawnableTeam, humanRole.UnitNameId) : string.Empty;
+ public string UnitName => Role is HumanRole humanRole ? humanRole.UnitName : string.Empty;
///
/// Gets or sets the player's unit id.
@@ -1326,7 +1328,7 @@ public static Player Get(string args)
if (!player.IsVerified || player.Nickname is null)
continue;
- if (!player.Nickname.Contains(args, StringComparison.OrdinalIgnoreCase))
+ if (!player.Nickname.ToLower().Contains(args.ToLower()))
continue;
string secondString = player.Nickname;
@@ -1473,16 +1475,6 @@ public static Player Get(string args)
/// An representing the processed players.
public static IEnumerable GetProcessedData(ArraySegment args, int startIndex = 0) => GetProcessedData(args, startIndex, out string[] _);
- ///
- /// Adds a player's UserId to the list of reserved slots.
- ///
- /// This method does not permanently give a user a reserved slot. The slot will be removed if the reserved slots are reloaded.
- /// The UserId of the player to add.
- /// if the slot was successfully added, or if the provided UserId already has a reserved slot.
- ///
- // TODO: Remove this method
- public static bool AddReservedSlot(string userId) => ReservedSlot.Users.Add(userId);
-
///
/// Adds a player's UserId to the list of reserved slots.
///
@@ -1535,15 +1527,6 @@ public static bool AddToWhitelist(string userId, bool isPermanent)
///
public static void ReloadWhitelist() => WhiteList.Reload();
- ///
- /// Adds the player's UserId to the list of reserved slots.
- ///
- /// This method does not permanently give a user a reserved slot. The slot will be removed if the reserved slots are reloaded.
- /// if the slot was successfully added, or if the player already has a reserved slot.
- ///
- // TODO: Remove this method
- public bool GiveReservedSlot() => AddReservedSlot(UserId);
-
///
/// Adds a player's UserId to the list of reserved slots.
///
@@ -1788,9 +1771,12 @@ public bool ReloadWeapon()
{
if (CurrentItem is Firearm firearm)
{
- bool result = firearm.Base.AmmoManagerModule.ServerTryReload();
+ // TODO not finish
+ /*
+ bool result = firearm.Base.Ammo.ServerTryReload();
Connection.Send(new RequestMessage(firearm.Serial, RequestType.Reload));
return result;
+ */
}
return false;
@@ -2161,7 +2147,7 @@ public void Hurt(Player attacker, float amount, DamageType damageType = DamageTy
/// The throw force.
/// The armor penetration amount.
public void Hurt(Player attacker, float damage, Vector3 force = default, int armorPenetration = 0) =>
- Hurt(new ExplosionDamageHandler(attacker.Footprint, force, damage, armorPenetration));
+ Hurt(new ExplosionDamageHandler(attacker.Footprint, force, damage, armorPenetration, ExplosionType.Grenade));
///
/// Hurts the player.
@@ -2264,7 +2250,7 @@ public void Vaporize(Player attacker = null, string cassieAnnouncement = "")
if ((Role.Side != Side.Scp) && !string.IsNullOrEmpty(cassieAnnouncement))
Cassie.Message(cassieAnnouncement);
- Kill(new DisruptorDamageHandler(attacker?.Footprint ?? Footprint, -1));
+ Kill(new DisruptorDamageHandler(new DisruptorShotEvent(Item.Create(ItemType.ParticleDisruptor, attacker).Base as InventorySystem.Items.Firearms.Firearm, DisruptorActionModule.FiringState.FiringSingle), Vector3.up, -1));
}
///
@@ -2465,17 +2451,6 @@ public ushort GetAmmoLimit(AmmoType type, bool ignoreArmor = false)
return InventorySystem.Configs.InventoryLimits.GetAmmoLimit(type.GetItemType(), referenceHub);
}
- ///
- /// Gets the maximum amount of ammo the player can hold, given the ammo .
- ///
- /// The of the ammo to check.
- /// The maximum amount of ammo this player can carry.
- [Obsolete("Use Player::GetAmmoLimit(AmmoType, bool) instead.")]
- public int GetAmmoLimit(AmmoType type)
- {
- return (int)InventorySystem.Configs.InventoryLimits.GetAmmoLimit(type.GetItemType(), referenceHub);
- }
-
///
/// Gets the maximum amount of ammo the player can hold, given the ammo .
/// This limit will scale with the armor the player is wearing.
@@ -2532,15 +2507,6 @@ public void ResetAmmoLimit(AmmoType ammoType)
/// If the player has a custom limit for the specific .
public bool HasCustomAmmoLimit(AmmoType ammoType) => CustomAmmoLimits.ContainsKey(ammoType);
- ///
- /// Gets the maximum amount of an the player can hold, based on the armor the player is wearing, as well as server configuration.
- ///
- /// The to check.
- /// The maximum amount of items in the category that the player can hold.
- [Obsolete("Use Player::GetCategoryLimit(ItemCategory, bool) instead.")]
- public int GetCategoryLimit(ItemCategory category) =>
- InventorySystem.Configs.InventoryLimits.GetCategoryLimit(category, referenceHub);
-
///
/// Gets the maximum amount of an the player can hold, based on the armor the player is wearing, as well as server configuration.
///
@@ -2668,16 +2634,6 @@ public Item AddItem(ItemType itemType)
return item;
}
- ///
- /// Adds an item of the specified type with default durability(ammo/charge) and no mods to the player's inventory.
- ///
- /// The item to be added.
- /// The attachments to be added to the item.
- /// The given to the player.
- [Obsolete("Use AddItem(ItemType) or AddItem(FirearmType, IEnumerable)", true)]
- public Item AddItem(ItemType itemType, IEnumerable identifiers = null)
- => itemType.GetFirearmType() is FirearmType.None ? AddItem(itemType) : AddItem(itemType.GetFirearmType(), identifiers);
-
///
/// Adds an firearm of the specified type with default durability(ammo/charge) and no mods to the player's inventory.
///
@@ -2695,12 +2651,15 @@ public Item AddItem(FirearmType firearmType, IEnumerable i
else if (Preferences is not null && Preferences.TryGetValue(firearmType, out AttachmentIdentifier[] attachments))
firearm.Base.ApplyAttachmentsCode(attachments.GetAttachmentsCode(), true);
+ // TODO Not finish
+ /*
FirearmStatusFlags flags = FirearmStatusFlags.MagazineInserted;
if (firearm.Attachments.Any(a => a.Name == AttachmentName.Flashlight))
flags |= FirearmStatusFlags.FlashlightEnabled;
firearm.Base.Status = new FirearmStatus(firearm.MaxAmmo, flags, firearm.Base.GetCurrentAttachmentsCode());
+ */
}
AddItem(item);
@@ -2726,17 +2685,6 @@ public IEnumerable AddItem(ItemType itemType, int amount)
return items;
}
- ///
- /// Adds the amount of items of the specified type with default durability(ammo/charge) and no mods to the player's inventory.
- ///
- /// The item to be added.
- /// The amount of items to be added.
- /// The attachments to be added to the item.
- /// An containing the items given.
- [Obsolete("Use AddItem(ItemType, int) or AddItem(FirearmType, int, IEnumerable)", true)]
- public IEnumerable AddItem(ItemType itemType, int amount, IEnumerable identifiers)
- => itemType.GetFirearmType() is FirearmType.None ? AddItem(itemType, amount) : AddItem(itemType.GetFirearmType(), amount, identifiers);
-
///
/// Adds the amount of firearms of the specified type with default durability(ammo/charge) and no mods to the player's inventory.
///
@@ -2776,22 +2724,6 @@ public IEnumerable AddItem(IEnumerable items)
return returnedItems;
}
- ///
- /// Adds the list of items of the specified type with default durability(ammo/charge) and no mods to the player's inventory.
- ///
- /// The of and of to be added.
- /// An containing the items given.
- [Obsolete("Use AddItem(Dictionary>) instead of this", true)]
- public IEnumerable AddItem(Dictionary> items)
- {
- List returnedItems = new(items.Count);
-
- foreach (KeyValuePair> item in items)
- returnedItems.Add(AddItem(item.Key, item.Value));
-
- return returnedItems;
- }
-
///
/// Adds the list of items of the specified type with default durability(ammo/charge) and no mods to the player's inventory.
///
@@ -2847,8 +2779,9 @@ public void AddItem(Firearm item, IEnumerable identifiers)
/// Adds an item to the player's inventory.
///
/// The of the item to be added.
+ /// The reason the item was added.
/// The that was added.
- public Item AddItem(Pickup pickup) => Item.Get(Inventory.ServerAddItem(pickup.Type, pickup.Serial, pickup.Base));
+ public Item AddItem(Pickup pickup, ItemAddReason addReason = ItemAddReason.Undefined) => Item.Get(Inventory.ServerAddItem(pickup.Type, addReason, pickup.Serial, pickup.Base));
///
/// Adds an item to the player's inventory.
@@ -2858,7 +2791,7 @@ public void AddItem(Firearm item, IEnumerable identifiers)
/// The that was added.
public Item AddItem(FirearmPickup pickup, IEnumerable identifiers)
{
- Firearm firearm = Item.Get(Inventory.ServerAddItem(pickup.Type, pickup.Serial, pickup.Base));
+ Firearm firearm = Item.Get(Inventory.ServerAddItem(pickup.Type, ItemAddReason.Undefined, pickup.Serial, pickup.Base));
if (identifiers is not null)
firearm.AddAttachment(identifiers);
@@ -2871,12 +2804,14 @@ public Item AddItem(FirearmPickup pickup, IEnumerable iden
///
/// The item to be added.
/// The object of the item.
+ /// The reason the item was added.
/// The that was added.
- public Item AddItem(ItemBase itemBase, Item item = null)
+ public Item AddItem(ItemBase itemBase, Item item = null, ItemAddReason addReason = ItemAddReason.AdminCommand)
{
try
{
item ??= Item.Get(itemBase);
+ item.AddReason = addReason;
Inventory.UserInventory.Items[item.Serial] = itemBase;
@@ -2900,23 +2835,6 @@ public Item AddItem(ItemBase itemBase, Item item = null)
return null;
}
- ///
- /// Adds the of items to the player's inventory.
- ///
- /// The item to be added.
- /// The amount of items to be added.
- [Obsolete("Removed this method can't be functional")]
- public void AddItem(Item item, int amount) => _ = item;
-
- ///
- /// Adds the of items to the player's inventory.
- ///
- /// The firearm to be added.
- /// The amount of items to be added.
- /// The attachments to be added to the item.
- [Obsolete("Removed this method can't be functional")]
- public void AddItem(Firearm firearm, int amount, IEnumerable identifiers) => _ = firearm;
-
///
/// Adds the list of items to the player's inventory.
///
@@ -3293,13 +3211,6 @@ public void EnableEffect(EffectType type, float duration = 0f, bool addDurationI
public bool EnableEffect(EffectType type, byte intensity, float duration = 0f, bool addDurationIfActive = false)
=> TryGetEffect(type, out StatusEffectBase statusEffect) && EnableEffect(statusEffect, intensity, duration, addDurationIfActive);
- ///
- /// Enables a status effect on the player.
- ///
- /// The to enable.
- [Obsolete("Use SyncEffect(Effect) instead of this")]
- public void EnableEffect(Effect effect) => SyncEffect(effect);
-
///
/// Syncs the status effect on the player.
///
@@ -3359,13 +3270,6 @@ public void EnableEffects(IEnumerable types, float duration = 0f, bo
}
}
- ///
- /// Enables a of on the player.
- ///
- /// The of to enable.
- [Obsolete("Use SyncEffects(IEnumerable) instead of this")]
- public void EnableEffects(IEnumerable effects) => SyncEffects(effects);
-
///
/// Syncs a of on the player.
///
@@ -3785,7 +3689,7 @@ public void SetCooldownItem(float time, ItemType itemType)
///
/// Explode the player.
///
- public void Explode() => ExplosionUtils.ServerExplode(ReferenceHub);
+ public void Explode() => ExplosionUtils.ServerExplode(ReferenceHub, ExplosionType.Grenade);
///
/// Explode the player.
@@ -3800,6 +3704,37 @@ public void SetCooldownItem(float time, ItemType itemType)
/// The projectile that will create the effect.
public void ExplodeEffect(ProjectileType projectileType) => Map.ExplodeEffect(Position, projectileType);
+ ///
+ public override bool Equals(object obj)
+ {
+ Player player = obj as Player;
+ return (object)player != null && ReferenceHub == player.ReferenceHub;
+ }
+
+ ///
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ ///
+ /// Returns whether the two players are the same.
+ ///
+ /// The first player instance.
+ /// The second player instance.
+ /// if the values are equal.
+#pragma warning disable SA1201
+ public static bool operator ==(Player player1, Player player2) => player1?.Equals(player2) ?? player2 is null;
+
+ ///
+ /// Returns whether the two players are different.
+ ///
+ /// The first player instance.
+ /// The second player instance.
+ /// if the values are not equal.
+ public static bool operator !=(Player player1, Player player2) => !(player1 == player2);
+#pragma warning restore SA1201
+
///
/// Converts the player in a human-readable format.
///
diff --git a/EXILED/Exiled.API/Features/PrefabHelper.cs b/EXILED/Exiled.API/Features/PrefabHelper.cs
index 4fe664cc5..82180ac9a 100644
--- a/EXILED/Exiled.API/Features/PrefabHelper.cs
+++ b/EXILED/Exiled.API/Features/PrefabHelper.cs
@@ -9,8 +9,6 @@ namespace Exiled.API.Features
{
using System;
using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
using System.Reflection;
using Exiled.API.Enums;
@@ -23,18 +21,21 @@ namespace Exiled.API.Features
///
public static class PrefabHelper
{
- private static readonly Dictionary Stored = new();
+ ///
+ /// A containing all and their corresponding .
+ ///
+ internal static readonly Dictionary Prefabs = new(Enum.GetValues(typeof(PrefabType)).Length);
///
- /// Gets a dictionary of to .
+ /// Gets a of and their corresponding .
///
- public static ReadOnlyDictionary PrefabToGameObject => new(Stored);
+ public static IReadOnlyDictionary PrefabToGameObject => Prefabs;
///
- /// Gets the prefab attribute of a prefab type.
+ /// Gets the from a .
///
- /// The prefab type.
- /// The .
+ /// The .
+ /// The corresponding .
public static PrefabAttribute GetPrefabAttribute(this PrefabType prefabType)
{
Type type = prefabType.GetType();
@@ -42,64 +43,75 @@ public static PrefabAttribute GetPrefabAttribute(this PrefabType prefabType)
}
///
- /// Gets the prefab of the specified .
+ /// Gets the of the specified .
///
- /// The to get prefab of.
- /// The to get.
- /// Returns the prefab component as {T}.
- public static T GetPrefab(PrefabType type)
- where T : Component
+ /// The .
+ /// Returns the .
+ public static GameObject GetPrefab(PrefabType prefabType)
{
- if (!Stored.TryGetValue(type, out GameObject gameObject) || !gameObject.TryGetComponent(out T component))
- return null;
+ if (Prefabs.TryGetValue(prefabType, out GameObject prefab))
+ return prefab;
- return component;
+ return null;
}
///
- /// Spawns a prefab on server.
+ /// Tries to get the of the specified .
///
- /// The prefab type.
- /// The position to spawn the prefab.
- /// The rotation of the prefab.
- /// The instantied.
- public static GameObject Spawn(PrefabType prefabType, Vector3 position = default, Quaternion rotation = default)
+ /// The .
+ /// The of the .
+ /// Returns true if the was found.
+ public static bool TryGetPrefab(PrefabType prefabType, out GameObject gameObject)
{
- if (!Stored.TryGetValue(prefabType, out GameObject gameObject))
- return null;
- GameObject newGameObject = UnityEngine.Object.Instantiate(gameObject, position, rotation);
- NetworkServer.Spawn(newGameObject);
- return newGameObject;
+ gameObject = GetPrefab(prefabType);
+ return gameObject is not null;
}
///
- /// Spawns a prefab on server.
+ /// Gets a from the of the specified .
///
- /// The prefab type.
- /// The position to spawn the prefab.
- /// The rotation of the prefab.
+ /// The .
/// The type.
- /// The instantied.
- public static T Spawn(PrefabType prefabType, Vector3 position = default, Quaternion rotation = default)
+ /// Returns the .
+ public static T GetPrefab(PrefabType prefabType)
where T : Component
{
- T obj = UnityEngine.Object.Instantiate(GetPrefab(prefabType), position, rotation);
- NetworkServer.Spawn(obj.gameObject);
- return obj;
+ if (Prefabs.TryGetValue(prefabType, out GameObject prefab) && prefab.TryGetComponent(out T component))
+ return component;
+
+ return null;
}
///
- /// Loads all prefabs.
+ /// Spawns the of the specified .
///
- internal static void LoadPrefabs()
+ /// The .
+ /// The position where the will spawn.
+ /// The rotation of the .
+ /// Returns the instantied.
+ public static GameObject Spawn(PrefabType prefabType, Vector3 position = default, Quaternion? rotation = null)
{
- Stored.Clear();
+ if (!TryGetPrefab(prefabType, out GameObject gameObject))
+ return null;
- foreach (PrefabType prefabType in EnumUtils.Values)
- {
- PrefabAttribute attribute = prefabType.GetPrefabAttribute();
- Stored.Add(prefabType, NetworkClient.prefabs.FirstOrDefault(prefab => prefab.Key == attribute.AssetId || prefab.Value.name.Contains(attribute.Name)).Value);
- }
+ GameObject newGameObject = UnityEngine.Object.Instantiate(gameObject, position, rotation ?? Quaternion.identity);
+ NetworkServer.Spawn(newGameObject);
+ return newGameObject;
+ }
+
+ ///
+ /// Spawns the of the specified .
+ ///
+ /// The .
+ /// The position where the will spawn.
+ /// The rotation of the .
+ /// The type.
+ /// Returns the of the .
+ public static T Spawn(PrefabType prefabType, Vector3 position = default, Quaternion? rotation = null)
+ where T : Component
+ {
+ GameObject gameObject = Spawn(prefabType, position, rotation);
+ return gameObject?.GetComponent();
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Ragdoll.cs b/EXILED/Exiled.API/Features/Ragdoll.cs
index d27c076da..8cde5d8cb 100644
--- a/EXILED/Exiled.API/Features/Ragdoll.cs
+++ b/EXILED/Exiled.API/Features/Ragdoll.cs
@@ -117,7 +117,7 @@ public DamageHandlerBase DamageHandler
///
/// Gets a value indicating whether the ragdoll has been already cleaned up.
///
- public bool IsFrozen => Base._frozen;
+ public bool IsFrozen => Base.Frozen;
///
/// Gets or sets a value indicating whether the ragdoll can be cleaned up.
@@ -358,8 +358,8 @@ public static Ragdoll CreateAndSpawn(RagdollData networkInfo)
/// The rotation of the ragdoll.
/// The optional owner of the ragdoll.
/// The ragdoll.
- public static Ragdoll CreateAndSpawn(RoleTypeId roleType, string name, DamageHandlerBase damageHandler, Vector3 position, Quaternion rotation, Player owner = null)
- => CreateAndSpawn(new(owner?.ReferenceHub ?? Server.Host.ReferenceHub, damageHandler, roleType, position, rotation, name, NetworkTime.time));
+ public static Ragdoll CreateAndSpawn(RoleTypeId roleType, string name, DamageHandlerBase damageHandler, Vector3 position, Quaternion? rotation = null, Player owner = null)
+ => CreateAndSpawn(new(owner?.ReferenceHub ?? Server.Host.ReferenceHub, damageHandler, roleType, position, rotation ?? Quaternion.identity, name, NetworkTime.time));
///
/// Creates and spawns a new ragdoll.
@@ -371,7 +371,7 @@ public static Ragdoll CreateAndSpawn(RoleTypeId roleType, string name, DamageHan
/// The rotation of the ragdoll.
/// The optional owner of the ragdoll.
/// The ragdoll.
- public static Ragdoll CreateAndSpawn(RoleTypeId roleType, string name, string deathReason, Vector3 position, Quaternion rotation, Player owner = null)
+ public static Ragdoll CreateAndSpawn(RoleTypeId roleType, string name, string deathReason, Vector3 position, Quaternion? rotation = null, Player owner = null)
=> CreateAndSpawn(roleType, name, new CustomReasonDamageHandler(deathReason), position, rotation, owner);
///
diff --git a/EXILED/Exiled.API/Features/Recontainer.cs b/EXILED/Exiled.API/Features/Recontainer.cs
index 6ebf128c3..17f59c97d 100644
--- a/EXILED/Exiled.API/Features/Recontainer.cs
+++ b/EXILED/Exiled.API/Features/Recontainer.cs
@@ -193,7 +193,16 @@ public static bool IsContainmentSequenceSuccessful
///
/// Begins the overcharge procedure.
///
- public static void BeginOvercharge() => Base.BeginOvercharge();
+ /// Make than is call after the .
+ public static void BeginOvercharge(bool endOvercharge = true)
+ {
+ Base.BeginOvercharge();
+ if (endOvercharge)
+ {
+ Base._delayStopwatch.Stop();
+ Base._unlockStopwatch.Start();
+ }
+ }
///
/// Ends the overcharge procedure.
diff --git a/EXILED/Exiled.API/Features/Respawn.cs b/EXILED/Exiled.API/Features/Respawn.cs
index 9ac5d6812..82282435c 100644
--- a/EXILED/Exiled.API/Features/Respawn.cs
+++ b/EXILED/Exiled.API/Features/Respawn.cs
@@ -13,8 +13,11 @@ namespace Exiled.API.Features
using CustomPlayerEffects;
using Enums;
+ using Extensions;
using PlayerRoles;
using Respawning;
+ using Respawning.Waves;
+ using Respawning.Waves.Generic;
using UnityEngine;
///
@@ -25,6 +28,16 @@ public static class Respawn
private static GameObject ntfHelicopterGameObject;
private static GameObject chaosCarGameObject;
+ ///
+ /// Gets the of paused 's.
+ ///
+ public static List PausedWaves { get; } = new();
+
+ ///
+ /// Gets the containing faction influence.
+ ///
+ public static Dictionary FactionInfluence => FactionInfluenceManager.Influence;
+
///
/// Gets the NTF Helicopter's .
///
@@ -54,174 +67,340 @@ public static GameObject ChaosVan
}
///
- /// Gets or sets the next known that will spawn.
+ /// Gets the next known that will spawn.
+ ///
+ /// This returns SpawnableFaction.None unless a respawn has already started.
+ public static SpawnableFaction NextKnownSpawnableFaction => WaveManager._nextWave is not null ? WaveManager._nextWave.GetSpawnableFaction() : SpawnableFaction.None;
+
+ ///
+ /// Gets the current state of the .
///
- public static SpawnableTeamType NextKnownTeam
+ public static WaveQueueState CurrentState => WaveManager.State;
+
+ ///
+ /// Gets a value indicating whether the respawn process for a is currently in progress..
+ ///
+ public static bool IsSpawning => WaveManager.State == WaveQueueState.WaveSpawning;
+
+ ///
+ /// Gets or sets a value indicating whether spawn protection is enabled.
+ ///
+ public static bool ProtectionEnabled
{
- get => RespawnManager.Singleton.NextKnownTeam;
- set => RespawnManager.Singleton.NextKnownTeam = value;
+ get => SpawnProtected.IsProtectionEnabled;
+ set => SpawnProtected.IsProtectionEnabled = value;
}
///
- /// Gets or sets the amount of seconds before the next respawn phase will occur.
+ /// Gets or sets the spawn protection time, in seconds.
///
- public static float TimeUntilNextPhase
+ public static float ProtectionTime
{
- get => RespawnManager.Singleton._timeForNextSequence - (float)RespawnManager.Singleton._stopwatch.Elapsed.TotalSeconds;
- set => RespawnManager.Singleton._timeForNextSequence = (float)RespawnManager.Singleton._stopwatch.Elapsed.TotalSeconds + value;
+ get => SpawnProtected.SpawnDuration;
+ set => SpawnProtected.SpawnDuration = value;
}
///
- /// Gets a indicating the amount of time before the next respawn wave will occur.
+ /// Gets or sets a value indicating whether spawn protected players can shoot.
///
- public static TimeSpan TimeUntilSpawnWave => TimeSpan.FromSeconds(TimeUntilNextPhase);
+ public static bool ProtectedCanShoot
+ {
+ get => SpawnProtected.CanShoot;
+ set => SpawnProtected.CanShoot = value;
+ }
///
- /// Gets a indicating the moment in UTC time the next respawn wave will occur.
+ /// Gets a of s that have spawn protection.
///
- public static DateTime NextTeamTime => DateTime.UtcNow.AddSeconds(TimeUntilSpawnWave.TotalSeconds);
+ public static List ProtectedTeams => SpawnProtected.ProtectedTeams;
///
- /// Gets a value indicating whether a team is currently being spawned or the animations are playing for a team.
+ /// Tries to get a .
///
- public static bool IsSpawning => RespawnManager.Singleton._curSequence is RespawnManager.RespawnSequencePhase.PlayingEntryAnimations or RespawnManager.RespawnSequencePhase.SpawningSelectedTeam;
+ /// The found .
+ /// Type of .
+ /// true if was successfully found. Otherwise, false.
+ ///
+ public static bool TryGetWaveBase(out T spawnableWaveBase)
+ where T : SpawnableWaveBase => WaveManager.TryGet(out spawnableWaveBase);
///
- /// Gets or sets the amount of spawn tickets belonging to the Chaos Insurgency.
+ /// Tries to get a .
///
- ///
- public static float ChaosTickets
+ /// A determining which wave to search for.
+ /// The found .
+ /// true if was successfully found. Otherwise, false.
+ ///
+ public static bool TryGetWaveBase(SpawnableFaction spawnableFaction, out SpawnableWaveBase spawnableWaveBase)
{
- get => RespawnTokensManager.Counters[0].Amount;
- set => RespawnTokensManager.ModifyTokens(SpawnableTeamType.ChaosInsurgency, value);
+ spawnableWaveBase = WaveManager.Waves.Find(x => x.GetSpawnableFaction() == spawnableFaction);
+ return spawnableWaveBase is not null;
}
///
- /// Gets or sets the amount of spawn tickets belonging to the NTF.
+ /// Tries to get an of .
///
- ///
- public static float NtfTickets
+ /// A determining which waves to search for.
+ /// The containing found 's if there are any, otherwise null.
+ /// true if was successfully found. Otherwise, false.
+ ///
+ public static bool TryGetWaveBases(Faction faction, out IEnumerable spawnableWaveBases)
{
- get => RespawnTokensManager.Counters[1].Amount;
- set => RespawnTokensManager.ModifyTokens(SpawnableTeamType.NineTailedFox, value);
+ List spawnableWaves = new();
+ spawnableWaves.AddRange(WaveManager.Waves.Where(x => x.TargetFaction == faction));
+
+ if (spawnableWaves.IsEmpty())
+ {
+ spawnableWaveBases = null;
+ return false;
+ }
+
+ spawnableWaveBases = spawnableWaves;
+ return true;
}
///
- /// Gets or sets a value indicating whether spawn protection is enabled.
+ /// Advances the respawn timer for s.
///
- public static bool ProtectionEnabled
+ /// The whose 's timers are to be advanced.
+ /// Number of seconds to advance the timers by.
+ /// This advances the timer for both the normal and mini wave.
+ public static void AdvanceTimer(Faction faction, float seconds) => WaveManager.AdvanceTimer(faction, seconds);
+
+ ///
+ /// Advances the respawn timer for s.
+ ///
+ /// The whose 's timers are to be advanced.
+ /// A representing the amount of time to advance the timers by.
+ /// This advances the timer for both the normal and mini wave.
+ public static void AdvanceTimer(Faction faction, TimeSpan time) => AdvanceTimer(faction, (float)time.TotalSeconds);
+
+ ///
+ /// Advances the respawn timer for s.
+ ///
+ /// The whose 's timer is to be advanced.
+ /// Number of seconds to advance the timers by.
+ public static void AdvanceTimer(SpawnableFaction spawnableFaction, float seconds)
{
- get => SpawnProtected.IsProtectionEnabled;
- set => SpawnProtected.IsProtectionEnabled = value;
+ foreach (SpawnableWaveBase spawnableWaveBase in WaveManager.Waves)
+ {
+ TimeBasedWave timeBasedWave = (TimeBasedWave)spawnableWaveBase;
+ if (timeBasedWave.GetSpawnableFaction() == spawnableFaction)
+ {
+ timeBasedWave.Timer.AddTime(Mathf.Abs(seconds));
+ }
+ }
}
///
- /// Gets or sets the spawn protection time, in seconds.
+ /// Advances the respawn timer for s.
///
- public static float ProtectionTime
+ /// The whose 's timer is to be advanced.
+ /// A representing the amount of time to advance the timers by.
+ public static void AdvanceTimer(SpawnableFaction spawnableFaction, TimeSpan time) => AdvanceTimer(spawnableFaction, (float)time.TotalSeconds);
+
+ ///
+ /// Play the spawn effect of a .
+ ///
+ /// The whose effect should be played.
+ public static void PlayEffect(SpawnableWaveBase wave)
{
- get => SpawnProtected.SpawnDuration;
- set => SpawnProtected.SpawnDuration = value;
+ WaveUpdateMessage.ServerSendUpdate(wave, UpdateMessageFlags.Trigger);
}
///
- /// Gets or sets a value indicating whether spawn protected players can shoot.
+ /// Summons the NTF chopper.
///
- public static bool ProtectedCanShoot
+ public static void SummonNtfChopper()
{
- get => SpawnProtected.CanShoot;
- set => SpawnProtected.CanShoot = value;
+ if (TryGetWaveBase(SpawnableFaction.NtfWave, out SpawnableWaveBase wave))
+ PlayEffect(wave);
}
///
- /// Gets a of that have spawn protection.
+ /// Summons the Chaos Insurgency van.
///
- public static List ProtectedTeams => SpawnProtected.ProtectedTeams;
+ /// This will also trigger Music effect.
+ ///
+ public static void SummonChaosInsurgencyVan()
+ {
+ if (TryGetWaveBase(SpawnableFaction.ChaosWave, out SpawnableWaveBase wave))
+ PlayEffect(wave);
+ }
///
- /// Play an effect when a certain class spawns.
+ /// Grants tokens to a given 's s.
///
- /// The effect to be played.
- public static void PlayEffect(byte effect) => PlayEffects(new[] { effect });
+ /// The to whose s to grant tokens.
+ /// The amount of tokens to grant.
+ /// true if tokens were successfully granted to an , otherwise false.
+ public static bool GrantTokens(Faction faction, int amount)
+ {
+ if (TryGetWaveBases(faction, out IEnumerable waveBases))
+ {
+ foreach (ILimitedWave limitedWave in waveBases.OfType())
+ {
+ limitedWave.RespawnTokens += amount;
+ }
+
+ return true;
+ }
+
+ return false;
+ }
///
- /// Play an effect when a certain class spawns.
+ /// Removes tokens from a given 's s.
///
- /// The effect to be played.
- public static void PlayEffect(RespawnEffectType effect) => PlayEffects(new[] { effect });
+ /// The from whose s to remove tokens.
+ /// The amount of tokens to remove.
+ /// true if tokens were successfully removed from an , otherwise false.
+ public static bool RemoveTokens(Faction faction, int amount)
+ {
+ if (TryGetWaveBases(faction, out IEnumerable waveBases))
+ {
+ foreach (ILimitedWave limitedWave in waveBases.OfType())
+ {
+ limitedWave.RespawnTokens = Math.Max(0, limitedWave.RespawnTokens - amount);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
///
- /// Play effects when a certain class spawns.
+ /// Modifies tokens of a given 's s by a given amount.
///
- /// The effects to be played.
- public static void PlayEffects(byte[] effects)
+ /// The whose s' tokens are to be modified.
+ /// The amount of tokens to add/remove.
+ /// true if tokens were successfully modified for an , otherwise false.
+ public static bool ModifyTokens(Faction faction, int amount)
{
- foreach (RespawnEffectsController controller in RespawnEffectsController.AllControllers)
- controller?.RpcPlayEffects(effects);
+ if (TryGetWaveBases(faction, out IEnumerable waveBases))
+ {
+ foreach (ILimitedWave limitedWave in waveBases.OfType())
+ {
+ limitedWave.RespawnTokens = amount;
+ }
+
+ return true;
+ }
+
+ return false;
}
///
- /// Play effects when a certain class spawns.
+ /// Tries to get the tokens of a given 's .
///
- /// The effects to be played.
- public static void PlayEffects(RespawnEffectType[] effects) => PlayEffects(effects.Select(effect => (byte)effect).ToArray());
+ /// The from whose to get the tokens.
+ /// The amount of tokens an has, if one was found, otherwise 0.
+ /// true if an was successfully found, otherwise false.
+ public static bool TryGetTokens(SpawnableFaction spawnableFaction, out int tokens)
+ {
+ if (TryGetWaveBase(spawnableFaction, out SpawnableWaveBase waveBase) && waveBase is ILimitedWave limitedWave)
+ {
+ tokens = limitedWave.RespawnTokens;
+ return true;
+ }
+
+ tokens = 0;
+ return false;
+ }
///
- /// Summons the NTF chopper.
+ /// Sets the amount of tokens of an of the given .
///
- public static void SummonNtfChopper() => PlayEffects(new[] { RespawnEffectType.SummonNtfChopper });
+ /// The whose 's tokens to set.
+ /// The amount of tokens to set.
+ /// true if tokens were successfully set for an , otherwise false.
+ public static bool SetTokens(SpawnableFaction spawnableFaction, int amount)
+ {
+ if (TryGetWaveBase(spawnableFaction, out SpawnableWaveBase waveBase) && waveBase is ILimitedWave limitedWave)
+ {
+ limitedWave.RespawnTokens = amount;
+ return true;
+ }
+
+ return false;
+ }
///
- /// Summons the van.
+ /// Starts the spawn sequence of the given .
///
- /// Whether to play the Chaos Insurgency spawn music.
- public static void SummonChaosInsurgencyVan(bool playMusic = true)
+ /// The whose wave to spawn.
+ /// Whether the wave should be a mini wave or not.
+ public static void ForceWave(Faction faction, bool isMini = false)
{
- PlayEffects(
- playMusic
- ? new[]
- {
- RespawnEffectType.PlayChaosInsurgencyMusic,
- RespawnEffectType.SummonChaosInsurgencyVan,
- }
- : new[]
- {
- RespawnEffectType.SummonChaosInsurgencyVan,
- });
+ if (faction.TryGetSpawnableFaction(out SpawnableFaction spawnableFaction, isMini))
+ {
+ ForceWave(spawnableFaction);
+ }
}
///
- /// Grants tickets to a .
+ /// Starts the spawn sequence of the given .
///
- /// The to grant tickets to.
- /// The amount of tickets to grant.
- public static void GrantTickets(SpawnableTeamType team, float amount) => RespawnTokensManager.GrantTokens(team, Math.Max(0, amount));
+ /// The whose wave to spawn.
+ public static void ForceWave(SpawnableFaction spawnableFaction)
+ {
+ if (TryGetWaveBase(spawnableFaction, out SpawnableWaveBase spawnableWaveBase))
+ {
+ ForceWave(spawnableWaveBase);
+ }
+ }
///
- /// Removes tickets from a .
+ /// Starts the spawn sequence of the given .
///
- /// The to remove tickets from.
- /// The amount of tickets to remove.
- public static void RemoveTickets(SpawnableTeamType team, float amount) => RespawnTokensManager.RemoveTokens(team, Math.Max(0, amount));
+ /// The to spawn.
+ public static void ForceWave(SpawnableWaveBase spawnableWaveBase)
+ {
+ WaveManager.Spawn(spawnableWaveBase);
+ }
///
- /// Modify tickets from a .
+ /// Pauses respawn waves by removing them from WaveManager.Waves and storing them in .
///
- /// The to modify tickets from.
- /// The amount of tickets to modify.
- public static void ModifyTickets(SpawnableTeamType team, float amount) => RespawnTokensManager.ModifyTokens(team, amount);
+ ///
+ public static void PauseWaves()
+ {
+ PausedWaves.Clear();
+ PausedWaves.AddRange(WaveManager.Waves);
+ WaveManager.Waves.Clear();
+ }
///
- /// Forces a spawn of the given .
+ /// Resumes respawn waves by filling WaveManager.Waves with values stored in .
///
- /// The to spawn.
- /// Whether effects will be played with the spawn.
- public static void ForceWave(SpawnableTeamType team, bool playEffects = false)
+ ///
+ /// This also clears .
+ public static void ResumeWaves()
{
- if (playEffects)
- RespawnEffectsController.ExecuteAllEffects(RespawnEffectsController.EffectType.Selection, team);
+ WaveManager.Waves.Clear();
+ WaveManager.Waves.AddRange(PausedWaves);
+ PausedWaves.Clear();
+ }
- RespawnManager.Singleton.ForceSpawnTeam(team);
+ ///
+ /// Restarts respawn waves by clearing WaveManager.Waves and filling it with new values..
+ ///
+ ///
+ /// This also clears .
+ public static void RestartWaves()
+ {
+ WaveManager.Waves.Clear();
+ WaveManager.Waves.AddRange(new List { new ChaosMiniWave(), new ChaosSpawnWave(), new NtfMiniWave(), new NtfSpawnWave() });
+ PausedWaves.Clear();
}
+
+ ///
+ /// Tries to get the influence value of a given .
+ ///
+ /// The whose influence to get.
+ /// The amount of influence a faction has.
+ /// Whether an entry was successfully found.
+ public static bool TryGetFactionInfluence(Faction faction, out float influence) => FactionInfluence.TryGetValue(faction, out influence);
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Roles/DestroyedRole.cs b/EXILED/Exiled.API/Features/Roles/DestroyedRole.cs
new file mode 100644
index 000000000..42e6cfe34
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Roles/DestroyedRole.cs
@@ -0,0 +1,36 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Roles
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+ using System.Threading.Tasks;
+
+ using PlayerRoles;
+ using PlayerRoles.Voice;
+
+ ///
+ /// Defines a role that represents players with destroyed role.
+ ///
+ internal class DestroyedRole : Role
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// the base .
+ internal DestroyedRole(PlayerRoleBase baseRole)
+ : base(baseRole)
+ {
+ }
+
+ ///
+ public override RoleTypeId Type { get; } = RoleTypeId.Destroyed;
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Roles/HumanRole.cs b/EXILED/Exiled.API/Features/Roles/HumanRole.cs
index 830f7844e..8a238a3e7 100644
--- a/EXILED/Exiled.API/Features/Roles/HumanRole.cs
+++ b/EXILED/Exiled.API/Features/Roles/HumanRole.cs
@@ -32,19 +32,10 @@ internal HumanRole(HumanGameRole baseRole)
///
public override RoleTypeId Type => Base.RoleTypeId;
- ///
- /// Gets or sets the .
- ///
- public SpawnableTeamType SpawnableTeamType
- {
- get => Base.AssignedSpawnableTeam;
- set => Base.AssignedSpawnableTeam = value;
- }
-
///
/// Gets the player's unit name.
///
- public string UnitName => UnitNameMessageHandler.GetReceived(Base.AssignedSpawnableTeam, Base.UnitNameId);
+ public string UnitName => NamingRulesManager.ClientFetchReceived(Team, UnitNameId);
///
/// Gets or sets the .
diff --git a/EXILED/Exiled.API/Features/Roles/Role.cs b/EXILED/Exiled.API/Features/Roles/Role.cs
index 6edc4f409..ef6d8dcea 100644
--- a/EXILED/Exiled.API/Features/Roles/Role.cs
+++ b/EXILED/Exiled.API/Features/Roles/Role.cs
@@ -18,6 +18,7 @@ namespace Exiled.API.Features.Roles
using PlayerRoles.PlayableScps.Scp049.Zombies;
using UnityEngine;
+ using DestroyedGameRole = PlayerRoles.DestroyedRole;
using FilmmakerGameRole = PlayerRoles.Filmmaker.FilmmakerRole;
using HumanGameRole = PlayerRoles.HumanRole;
using NoneGameRole = PlayerRoles.NoneRole;
@@ -113,6 +114,11 @@ protected Role(PlayerRoleBase baseRole)
///
public bool IsValid => Owner != null && Owner.IsConnected && Base == Owner.RoleManager.CurrentRole;
+ ///
+ /// Gets the life identifier for the role.
+ ///
+ public int LifeIdentifier => Base.UniqueLifeIdentifier;
+
///
/// Gets a random spawn position of this role.
///
@@ -228,6 +234,7 @@ public virtual void Set(RoleTypeId newRole, SpawnReason reason, RoleSpawnFlags s
HumanGameRole humanRole => new HumanRole(humanRole),
FilmmakerGameRole filmmakerRole => new FilmMakerRole(filmmakerRole),
NoneGameRole noneRole => new NoneRole(noneRole),
+ DestroyedGameRole destroyedRole => new DestroyedRole(destroyedRole),
_ => null,
};
}
diff --git a/EXILED/Exiled.API/Features/Roles/Scp079Role.cs b/EXILED/Exiled.API/Features/Roles/Scp079Role.cs
index 2798eb50d..2480ca3d8 100644
--- a/EXILED/Exiled.API/Features/Roles/Scp079Role.cs
+++ b/EXILED/Exiled.API/Features/Roles/Scp079Role.cs
@@ -593,7 +593,7 @@ public void ActivateTesla(bool consumeEnergy = true)
Scp079Camera cam = CurrentCameraSync.CurrentCamera;
RewardManager.MarkRoom(cam.Room);
- if (!TeslaGateController.Singleton.TeslaGates.TryGetFirst(x => RoomIdUtils.IsTheSameRoom(cam.Position, x.transform.position), out global::TeslaGate teslaGate))
+ if (!global::TeslaGate.AllGates.TryGetFirst(x => RoomIdUtils.IsTheSameRoom(cam.Position, x.transform.position), out global::TeslaGate teslaGate))
return;
if (consumeEnergy)
diff --git a/EXILED/Exiled.API/Features/Roles/Scp106Role.cs b/EXILED/Exiled.API/Features/Roles/Scp106Role.cs
index 24ff42992..067ee6964 100644
--- a/EXILED/Exiled.API/Features/Roles/Scp106Role.cs
+++ b/EXILED/Exiled.API/Features/Roles/Scp106Role.cs
@@ -13,7 +13,6 @@ namespace Exiled.API.Features.Roles
using PlayerRoles;
using PlayerRoles.PlayableScps;
using PlayerRoles.PlayableScps.HumeShield;
- using PlayerRoles.PlayableScps.Scp049;
using PlayerRoles.PlayableScps.Scp106;
using PlayerRoles.Subroutines;
using PlayerStatsSystem;
@@ -125,8 +124,12 @@ public float Vigor
///
public bool IsSubmerged
{
- get => Base.IsSubmerged;
- set => HuntersAtlasAbility.SetSubmerged(value);
+ get => HuntersAtlasAbility._syncSubmerged;
+ set
+ {
+ HuntersAtlasAbility._syncSubmerged = value;
+ HuntersAtlasAbility.ServerSendRpc(true);
+ }
}
///
@@ -149,11 +152,6 @@ public bool IsSubmerged
///
public float SinkholeCurrentTime => SinkholeController.ElapsedToggle;
- ///
- /// Gets a value indicating the normalized state of the sinkhole.
- ///
- public float SinkholeNormalizedState => SinkholeController.NormalizedState;
-
///
/// Gets a value indicating whether SCP-106 is currently in the middle of an animation.
///
@@ -169,63 +167,14 @@ public bool IsSubmerged
///
public bool SinkholeState
{
- get => SinkholeController.State;
- set => SinkholeController.State = value;
+ get => StalkAbility.StalkActive;
+ set => StalkAbility.ServerSetStalk(value);
}
///
/// Gets the sinkhole target duration.
///
- public float SinkholeTargetDuration => SinkholeController.TargetDuration;
-
- ///
- /// Gets the speed multiplier of the sinkhole.
- ///
- public float SinkholeSpeedMultiplier => SinkholeController.SpeedMultiplier;
-
- // TODO: ReAdd Setter but before making an propper way to overwrite NW constant only when the propperty has been used
-#pragma warning disable SA1623 // Property summary documentation should match accessors
-#pragma warning disable SA1202
- ///
- /// Gets or sets how mush cost the Ability Stalk will cost per tick when being stationary.
- ///
- internal float VigorStalkCostStationary { get; } = Scp106StalkAbility.VigorStalkCostStationary;
-
- ///
- /// Gets or sets how mush cost the Ability Stalk will cost per tick when moving.
- ///
- internal float VigorStalkCostMoving { get; } = Scp106StalkAbility.VigorStalkCostMoving;
-
- ///
- /// Gets or sets how mush vigor will be regenerate while moving per seconds.
- ///
- internal float VigorRegeneration { get; } = Scp106StalkAbility.VigorRegeneration;
-
- ///
- /// Gets or sets the duration of Corroding effect.
- ///
- internal float CorrodingTime { get; } = Scp106Attack.CorrodingTime;
-
- ///
- /// Gets or sets how mush vigor Scp106 will gain when being reward for having caught a player.
- ///
- internal float VigorCaptureReward { get; } = Scp106Attack.VigorCaptureReward;
-
- ///
- /// Gets or sets how mush reduction cooldown Scp106 will gain when being reward for having caught a player.
- ///
- internal float CooldownReductionReward { get; } = Scp106Attack.CooldownReductionReward;
-
- ///
- /// Gets or sets the cooldown duration of it's Sinkhole ability's.
- ///
- internal float SinkholeCooldownDuration { get; } = Scp106SinkholeController.CooldownDuration;
-
- ///
- /// Gets or sets how mush vigor it's ability Hunter Atlas will cost per meter.
- ///
- internal float HuntersAtlasCostPerMeter { get; } = Scp106HuntersAtlasAbility.CostPerMeter;
-#pragma warning restore SA1623 // Property summary documentation should match accessors
+ public float SinkholeTargetDuration => SinkholeController.TargetTransitionDuration;
///
/// Gets or sets how mush damage Scp106 will dealt when attacking a player.
@@ -254,10 +203,10 @@ public float CaptureCooldown
///
public float RemainingSinkholeCooldown
{
- get => SinkholeController.Cooldown.Remaining;
+ get => SinkholeController._submergeCooldown.Remaining;
set
{
- SinkholeController.Cooldown.Remaining = value;
+ SinkholeController._submergeCooldown.Remaining = value;
SinkholeController.ServerSendRpc(true);
}
}
@@ -267,8 +216,8 @@ public float RemainingSinkholeCooldown
///
public bool IsStalking
{
- get => StalkAbility.IsActive;
- set => StalkAbility.IsActive = value;
+ get => StalkAbility.StalkActive;
+ set => StalkAbility.ServerSetStalk(value);
}
///
@@ -294,7 +243,7 @@ public bool UsePortal(Vector3 position, float cost = 0f)
return false;
HuntersAtlasAbility._estimatedCost = cost;
- HuntersAtlasAbility.SetSubmerged(true);
+ HuntersAtlasAbility._syncSubmerged = true;
return true;
}
@@ -303,22 +252,24 @@ public bool UsePortal(Vector3 position, float cost = 0f)
/// Send a player to the pocket dimension.
///
/// The to send.
- public void CapturePlayer(Player player) // Convert to bool.
+ /// If the player will be capture.
+ public bool CapturePlayer(Player player)
{
if (player is null)
- return;
+ return false;
Attack._targetHub = player.ReferenceHub;
DamageHandlerBase handler = new ScpDamageHandler(Attack.Owner, AttackDamage, DeathTranslations.PocketDecay);
if (!Attack._targetHub.playerStats.DealDamage(handler))
- return;
+ return false;
Attack.SendCooldown(Attack._hitCooldown);
- Vigor += VigorCaptureReward;
+ Vigor += Scp106Attack.VigorCaptureReward;
Attack.ReduceSinkholeCooldown();
Hitmarker.SendHitmarkerDirectly(Attack.Owner, 1f);
player.EnableEffect(EffectType.PocketCorroding);
+ return true;
}
///
diff --git a/EXILED/Exiled.API/Features/Roles/Scp3114Role.cs b/EXILED/Exiled.API/Features/Roles/Scp3114Role.cs
index 05a28e0f8..ab157b92c 100644
--- a/EXILED/Exiled.API/Features/Roles/Scp3114Role.cs
+++ b/EXILED/Exiled.API/Features/Roles/Scp3114Role.cs
@@ -7,7 +7,6 @@
namespace Exiled.API.Features.Roles
{
- using System;
using System.Collections.Generic;
using Exiled.API.Enums;
@@ -158,22 +157,12 @@ public RoleTypeId StolenRole
}
}
- ///
- /// Gets or sets the SCP-3114's Ragdoll used for it's FakeIdentity.
- ///
- [Obsolete("Ragdoll in Role now has other meaning. Use IdentityRagdoll instead.")]
- public new Ragdoll Ragdoll
- {
- get => IdentityRagdoll;
- set => IdentityRagdoll = value;
- }
-
///
/// Gets or sets the SCP-3114's Ragdoll used for it's FakeIdentity.
///
public Ragdoll IdentityRagdoll
{
- get => Ragdoll.Get(Identity.CurIdentity.Ragdoll);
+ get => Features.Ragdoll.Get(Identity.CurIdentity.Ragdoll);
set
{
Identity.CurIdentity.Ragdoll = value?.Base;
diff --git a/EXILED/Exiled.API/Features/Room.cs b/EXILED/Exiled.API/Features/Room.cs
index fafb1d418..f0440ad64 100644
--- a/EXILED/Exiled.API/Features/Room.cs
+++ b/EXILED/Exiled.API/Features/Room.cs
@@ -395,7 +395,7 @@ public void UnlockAll()
/// Returns the Room in a human-readable format.
///
/// A string containing Room-related data.
- public override string ToString() => $"{Type} ({Zone}) [{Doors.Count}] *{Cameras.Count}* |{TeslaGate != null}|";
+ public override string ToString() => $"{Type} ({Zone}) [{Doors?.Count}] *{Cameras?.Count}* |{TeslaGate != null}|";
///
/// Factory method to create and add a component to a Transform.
@@ -412,62 +412,73 @@ private static RoomType FindType(GameObject gameObject)
// Try to remove brackets if they exist.
return gameObject.name.RemoveBracketsOnEndOfName() switch
{
- "LCZ_Armory" => RoomType.LczArmory,
- "LCZ_Curve" => RoomType.LczCurve,
- "LCZ_Straight" => RoomType.LczStraight,
- "LCZ_330" => RoomType.Lcz330,
- "LCZ_914" => RoomType.Lcz914,
- "LCZ_Crossing" => RoomType.LczCrossing,
- "LCZ_TCross" => RoomType.LczTCross,
+ "PocketWorld" => RoomType.Pocket,
+ "Outside" => RoomType.Surface,
"LCZ_Cafe" => RoomType.LczCafe,
- "LCZ_Plants" => RoomType.LczPlants,
"LCZ_Toilets" => RoomType.LczToilets,
+ "LCZ_TCross" => RoomType.LczTCross,
"LCZ_Airlock" => RoomType.LczAirlock,
- "LCZ_173" => RoomType.Lcz173,
- "LCZ_ClassDSpawn" => RoomType.LczClassDSpawn,
+ "LCZ_ChkpA" => RoomType.LczCheckpointA,
"LCZ_ChkpB" => RoomType.LczCheckpointB,
+ "LCZ_Plants" => RoomType.LczPlants,
+ "LCZ_Straight" => RoomType.LczStraight,
+ "LCZ_Armory" => RoomType.LczArmory,
+ "LCZ_Crossing" => RoomType.LczCrossing,
+ "LCZ_Curve" => RoomType.LczCurve,
+ "LCZ_173" => RoomType.Lcz173,
+ "LCZ_330" => RoomType.Lcz330,
"LCZ_372" => RoomType.LczGlassBox,
- "LCZ_ChkpA" => RoomType.LczCheckpointA,
- "HCZ_079" => RoomType.Hcz079,
- "HCZ_Room3ar" => RoomType.HczArmory,
+ "LCZ_914" => RoomType.Lcz914,
+ "LCZ_ClassDSpawn" => RoomType.LczClassDSpawn,
+ "HCZ_Nuke" => RoomType.HczNuke,
+ "HCZ_TArmory" => RoomType.HczArmory,
+ "HCZ_MicroHID_New" => RoomType.HczHid,
+ "HCZ_Crossroom_Water" => RoomType.HczCrossRoomWater,
"HCZ_Testroom" => RoomType.HczTestRoom,
- "HCZ_Hid" => RoomType.HczHid,
"HCZ_049" => RoomType.Hcz049,
- "HCZ_Crossing" => RoomType.HczCrossing,
- "HCZ_106" => RoomType.Hcz106,
- "HCZ_Nuke" => RoomType.HczNuke,
- "HCZ_Tesla" => RoomType.HczTesla,
- "HCZ_Servers" => RoomType.HczServers,
- "HCZ_Room3" => RoomType.HczTCross,
- "HCZ_457" => RoomType.Hcz096,
+ "HCZ_079" => RoomType.Hcz079,
+ "HCZ_096" => RoomType.Hcz096,
+ "HCZ_106_Rework" => RoomType.Hcz106,
+ "HCZ_939" => RoomType.Hcz939,
+ "HCZ_Tesla_Rework" => RoomType.HczTesla,
"HCZ_Curve" => RoomType.HczCurve,
+ "HCZ_Crossing" => RoomType.HczCrossing,
+ "HCZ_Intersection" => RoomType.HczIntersection,
+ "HCZ_Intersection_Junk" => RoomType.HczIntersectionJunk,
+ "HCZ_Corner_Deep" => RoomType.HczCornerDeep,
"HCZ_Straight" => RoomType.HczStraight,
- "EZ_Endoof" => RoomType.EzVent,
- "EZ_Intercom" => RoomType.EzIntercom,
+ "HCZ_Straight_C" => RoomType.HczStraightC,
+ "HCZ_Straight_PipeRoom"=> RoomType.HczStraightPipeRoom,
+ "HCZ_Straight Variant" => RoomType.HczStraightVariant,
+ "HCZ_ChkpA" => RoomType.HczElevatorA,
+ "HCZ_ChkpB" => RoomType.HczElevatorB,
"EZ_GateA" => RoomType.EzGateA,
- "EZ_PCs_small" => RoomType.EzDownstairsPcs,
+ "EZ_GateB" => RoomType.EzGateB,
+ "EZ_ThreeWay" => RoomType.EzTCross,
+ "EZ_Crossing" => RoomType.EzCrossing,
"EZ_Curve" => RoomType.EzCurve,
"EZ_PCs" => RoomType.EzPcs,
- "EZ_Crossing" => RoomType.EzCrossing,
+ "EZ_upstairs" => RoomType.EzUpstairsPcs,
+ "EZ_Intercom" => RoomType.EzIntercom,
+ "EZ_Smallrooms2" => RoomType.EzSmallrooms,
+ "EZ_PCs_small" => RoomType.EzDownstairsPcs,
+ "EZ_Chef" => RoomType.EzChef,
+ "EZ_Endoof" => RoomType.EzVent,
"EZ_CollapsedTunnel" => RoomType.EzCollapsedTunnel,
- "EZ_Smallrooms2" => RoomType.EzConference,
+ "EZ_Smallrooms1" => RoomType.EzConference,
"EZ_Straight" => RoomType.EzStraight,
+ "EZ_StraightColumn" => RoomType.EzStraightColumn,
"EZ_Cafeteria" => RoomType.EzCafeteria,
- "EZ_upstairs" => RoomType.EzUpstairsPcs,
- "EZ_GateB" => RoomType.EzGateB,
"EZ_Shelter" => RoomType.EzShelter,
- "EZ_ThreeWay" => RoomType.EzTCross,
- "PocketWorld" => RoomType.Pocket,
- "Outside" => RoomType.Surface,
- "HCZ_939" => RoomType.Hcz939,
- "EZ Part" => RoomType.EzCheckpointHallway,
- "HCZ_ChkpA" => RoomType.HczElevatorA,
- "HCZ_ChkpB" => RoomType.HczElevatorB,
- "HCZ Part" => gameObject.transform.parent.name switch
+ "EZ_HCZ_Checkpoint Part" => gameObject.transform.position.z switch
{
- "HCZ_EZ_Checkpoint (A)" => RoomType.HczEzCheckpointA,
- "HCZ_EZ_Checkpoint (B)" => RoomType.HczEzCheckpointB,
- _ => RoomType.Unknown
+ > 80 => RoomType.EzCheckpointHallwayA,
+ _ => RoomType.EzCheckpointHallwayB,
+ },
+ "HCZ_EZ_Checkpoint Part" => gameObject.transform.position.z switch
+ {
+ > 80 => RoomType.HczEzCheckpointA,
+ _ => RoomType.HczEzCheckpointB
},
_ => RoomType.Unknown,
};
@@ -477,6 +488,9 @@ private static ZoneType FindZone(GameObject gameObject)
{
Transform transform = gameObject.transform;
+ if (gameObject.name == "PocketWorld")
+ return ZoneType.Pocket;
+
return transform.parent?.name.RemoveBracketsOnEndOfName() switch
{
"HeavyRooms" => ZoneType.HeavyContainment,
@@ -493,14 +507,14 @@ private void InternalCreate()
RoomIdentifierToRoom.Add(Identifier, this);
Zone = FindZone(gameObject);
-#if Debug
- if (Type is RoomType.Unknown)
- Log.Error($"[ZONETYPE UNKNOWN] {this}");
+#if DEBUG
+ if (Zone is ZoneType.Unspecified)
+ Log.Error($"[ZONETYPE UNKNOWN] {this} Zone : {Identifier?.Zone}");
#endif
Type = FindType(gameObject);
-#if Debug
+#if DEBUG
if (Type is RoomType.Unknown)
- Log.Error($"[ROOMTYPE UNKNOWN] {this}");
+ Log.Error($"[ROOMTYPE UNKNOWN] {this} Name : {gameObject?.name} Shape : {Identifier?.Shape}");
#endif
RoomLightControllersValue.AddRange(gameObject.GetComponentsInChildren());
diff --git a/EXILED/Exiled.API/Features/Round.cs b/EXILED/Exiled.API/Features/Round.cs
index 81a6ccca3..b6ee2b35f 100644
--- a/EXILED/Exiled.API/Features/Round.cs
+++ b/EXILED/Exiled.API/Features/Round.cs
@@ -44,17 +44,17 @@ public static class Round
///
/// Gets a value indicating whether the round is started.
///
- public static bool IsStarted => ReferenceHub.LocalHub?.characterClassManager.RoundStarted ?? false;
+ public static bool IsStarted => ReferenceHub.TryGetHostHub(out ReferenceHub hub) && hub.characterClassManager.RoundStarted;
///
/// Gets a value indicating whether the round in progress.
///
- public static bool InProgress => ReferenceHub.LocalHub != null && RoundSummary.RoundInProgress();
+ public static bool InProgress => !IsEnded && RoundSummary.RoundInProgress();
///
/// Gets a value indicating whether the round is ended.
///
- public static bool IsEnded => RoundSummary.singleton._roundEnded;
+ public static bool IsEnded => RoundSummary._singletonSet && RoundSummary.singleton._roundEnded;
///
/// Gets a value indicating whether the round is lobby.
@@ -68,12 +68,12 @@ public static class Round
public static RoundSummary.SumInfo_ClassList LastClassList { get; internal set; }
///
- /// Gets or sets a value indicating the amount of Chaos Targets remaining.
+ /// Gets or sets a value indicating the amount of Extra Targets remaining.
///
- public static int ChaosTargetCount
+ public static int ExtraTargetCount
{
- get => RoundSummary.singleton.Network_chaosTargetCount;
- set => RoundSummary.singleton.Network_chaosTargetCount = value;
+ get => RoundSummary.singleton.Network_extraTargets;
+ set => RoundSummary.singleton.Network_extraTargets = value;
}
///
@@ -122,14 +122,9 @@ public static int Kills
}
///
- /// Gets or sets the number of surviving SCPs.
+ /// Gets the number of surviving SCPs.
///
- public static int SurvivingSCPs
- {
- get => RoundSummary.SurvivingSCPs;
- [Obsolete("This value is rewritten by NW every time it's used", true)]
- set => RoundSummary.SurvivingSCPs = value;
- }
+ public static int SurvivingSCPs => RoundSummary.SurvivingSCPs;
///
/// Gets or sets the number of kills made by SCPs.
diff --git a/EXILED/Exiled.API/Features/Server.cs b/EXILED/Exiled.API/Features/Server.cs
index af596f631..c79d0c4c1 100644
--- a/EXILED/Exiled.API/Features/Server.cs
+++ b/EXILED/Exiled.API/Features/Server.cs
@@ -267,14 +267,6 @@ public static bool ShutdownRedirect(ushort redirectPort)
return true;
}
- ///
- /// Runs a server command.
- ///
- /// The command to be run.
- /// The running the command.
- [Obsolete("Use Server.ExecuteCommand() instead.")]
- public static void RunCommand(string command, CommandSender sender = null) => GameCore.Console.singleton.TypeCommand(command, sender);
-
///
/// Executes a server command.
///
diff --git a/EXILED/Exiled.API/Features/Toys/AdminToy.cs b/EXILED/Exiled.API/Features/Toys/AdminToy.cs
index 71cbc8557..01f54e8d2 100644
--- a/EXILED/Exiled.API/Features/Toys/AdminToy.cs
+++ b/EXILED/Exiled.API/Features/Toys/AdminToy.cs
@@ -98,7 +98,7 @@ public Quaternion Rotation
set
{
AdminToyBase.transform.rotation = value;
- AdminToyBase.NetworkRotation = new LowPrecisionQuaternion(value);
+ AdminToyBase.NetworkRotation = value;
}
}
@@ -155,6 +155,7 @@ public static AdminToy Get(AdminToyBase adminToyBase)
LightSourceToy lightSourceToy => new Light(lightSourceToy),
PrimitiveObjectToy primitiveObjectToy => new Primitive(primitiveObjectToy),
ShootingTarget shootingTarget => new ShootingTargetToy(shootingTarget),
+ SpeakerToy speakerToy => new Speaker(speakerToy),
_ => throw new System.NotImplementedException()
};
}
diff --git a/EXILED/Exiled.API/Features/Toys/Light.cs b/EXILED/Exiled.API/Features/Toys/Light.cs
index b1361a4c6..757480e90 100644
--- a/EXILED/Exiled.API/Features/Toys/Light.cs
+++ b/EXILED/Exiled.API/Features/Toys/Light.cs
@@ -7,7 +7,6 @@
namespace Exiled.API.Features.Toys
{
- using System;
using System.Linq;
using AdminToys;
@@ -32,6 +31,11 @@ internal Light(LightSourceToy lightSourceToy)
Base = lightSourceToy;
}
+ ///
+ /// Gets the prefab.
+ ///
+ public static LightSourceToy Prefab => PrefabHelper.GetPrefab(PrefabType.LightSourceToy);
+
///
/// Gets the base .
///
@@ -55,6 +59,33 @@ public float Range
set => Base.NetworkLightRange = value;
}
+ ///
+ /// Gets or sets the angle of the light.
+ ///
+ public float SpotAngle
+ {
+ get => Base.NetworkSpotAngle;
+ set => Base.NetworkSpotAngle = value;
+ }
+
+ ///
+ /// Gets or sets the inner angle of the light.
+ ///
+ public float InnerSpotAngle
+ {
+ get => Base.NetworkInnerSpotAngle;
+ set => Base.NetworkInnerSpotAngle = value;
+ }
+
+ ///
+ /// Gets or sets the shadow strength of the light.
+ ///
+ public float ShadowStrength
+ {
+ get => Base.NetworkShadowStrength;
+ set => Base.NetworkShadowStrength = value;
+ }
+
///
/// Gets or sets the color of the primitive.
///
@@ -67,10 +98,19 @@ public Color Color
///
/// Gets or sets a value indicating whether the light should cause shadows from other objects.
///
- public bool ShadowEmission
+ public LightShape LightShape
+ {
+ get => Base.NetworkLightShape;
+ set => Base.NetworkLightShape = value;
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the light should cause shadows from other objects.
+ ///
+ public LightType LightType
{
- get => Base.NetworkLightShadows;
- set => Base.NetworkLightShadows = value;
+ get => Base.NetworkLightType;
+ set => Base.NetworkLightType = value;
}
///
@@ -95,11 +135,12 @@ public static Light Create(Vector3? position = null, Vector3? rotation = null, V
/// The new .
public static Light Create(Vector3? position /*= null*/, Vector3? rotation /*= null*/, Vector3? scale /*= null*/, bool spawn /*= true*/, Color? color /*= null*/)
{
- Light light = new(UnityEngine.Object.Instantiate(ToysHelper.LightBaseObject));
-
- light.Position = position ?? Vector3.zero;
- light.Rotation = Quaternion.Euler(rotation ?? Vector3.zero);
- light.Scale = scale ?? Vector3.one;
+ Light light = new(UnityEngine.Object.Instantiate(Prefab))
+ {
+ Position = position ?? Vector3.zero,
+ Rotation = Quaternion.Euler(rotation ?? Vector3.zero),
+ Scale = scale ?? Vector3.one,
+ };
if (spawn)
light.Spawn();
@@ -116,8 +157,8 @@ public static Light Create(Vector3? position /*= null*/, Vector3? rotation /*= n
/// The corresponding instance.
public static Light Get(LightSourceToy lightSourceToy)
{
- AdminToy adminToy = Map.Toys.FirstOrDefault(x => x.AdminToyBase == lightSourceToy);
- return adminToy is not null ? adminToy as Light : new Light(lightSourceToy);
+ AdminToy adminToy = List.FirstOrDefault(x => x.AdminToyBase == lightSourceToy);
+ return adminToy is not null ? adminToy as Light : new(lightSourceToy);
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Toys/Primitive.cs b/EXILED/Exiled.API/Features/Toys/Primitive.cs
index b90588d8f..9ca95036d 100644
--- a/EXILED/Exiled.API/Features/Toys/Primitive.cs
+++ b/EXILED/Exiled.API/Features/Toys/Primitive.cs
@@ -31,6 +31,11 @@ public class Primitive : AdminToy, IWrapper
internal Primitive(PrimitiveObjectToy toyAdminToyBase)
: base(toyAdminToyBase, AdminToyType.PrimitiveObject) => Base = toyAdminToyBase;
+ ///
+ /// Gets the prefab.
+ ///
+ public static PrimitiveObjectToy Prefab => PrefabHelper.GetPrefab(PrefabType.PrimitiveObjectToy);
+
///
/// Gets the base .
///
@@ -115,17 +120,16 @@ public static Primitive Create(PrimitiveType primitiveType = PrimitiveType.Spher
/// The new .
public static Primitive Create(Vector3? position /*= null*/, Vector3? rotation /*= null*/, Vector3? scale /*= null*/, bool spawn /*= true*/, Color? color /*= null*/)
{
- Primitive primitive = new(Object.Instantiate(ToysHelper.PrimitiveBaseObject));
+ Primitive primitive = new(Object.Instantiate(Prefab));
primitive.Position = position ?? Vector3.zero;
primitive.Rotation = Quaternion.Euler(rotation ?? Vector3.zero);
primitive.Scale = scale ?? Vector3.one;
+ primitive.Color = color ?? Color.gray;
if (spawn)
primitive.Spawn();
- primitive.Color = color ?? Color.gray;
-
return primitive;
}
@@ -141,18 +145,18 @@ public static Primitive Create(Vector3? position /*= null*/, Vector3? rotation /
/// The new .
public static Primitive Create(PrimitiveType primitiveType /*= PrimitiveType.Sphere*/, Vector3? position /*= null*/, Vector3? rotation /*= null*/, Vector3? scale /*= null*/, bool spawn /*= true*/, Color? color /*= null*/)
{
- Primitive primitive = new(Object.Instantiate(ToysHelper.PrimitiveBaseObject));
+ Primitive primitive = new(Object.Instantiate(Prefab));
primitive.Position = position ?? Vector3.zero;
primitive.Rotation = Quaternion.Euler(rotation ?? Vector3.zero);
primitive.Scale = scale ?? Vector3.one;
- if (spawn)
- primitive.Spawn();
-
primitive.Base.NetworkPrimitiveType = primitiveType;
primitive.Color = color ?? Color.gray;
+ if (spawn)
+ primitive.Spawn();
+
return primitive;
}
@@ -169,19 +173,19 @@ public static Primitive Create(PrimitiveType primitiveType /*= PrimitiveType.Sph
/// The new .
public static Primitive Create(PrimitiveType primitiveType /*= PrimitiveType.Sphere*/, PrimitiveFlags flags, Vector3? position /*= null*/, Vector3? rotation /*= null*/, Vector3? scale /*= null*/, bool spawn /*= true*/, Color? color /*= null*/)
{
- Primitive primitive = new(Object.Instantiate(ToysHelper.PrimitiveBaseObject));
+ Primitive primitive = new(Object.Instantiate(Prefab));
primitive.Position = position ?? Vector3.zero;
primitive.Rotation = Quaternion.Euler(rotation ?? Vector3.zero);
primitive.Scale = scale ?? Vector3.one;
primitive.Flags = flags;
- if (spawn)
- primitive.Spawn();
-
primitive.Base.NetworkPrimitiveType = primitiveType;
primitive.Color = color ?? Color.gray;
+ if (spawn)
+ primitive.Spawn();
+
return primitive;
}
@@ -192,20 +196,20 @@ public static Primitive Create(PrimitiveType primitiveType /*= PrimitiveType.Sph
/// The new .
public static Primitive Create(PrimitiveSettings primitiveSettings)
{
- Primitive primitive = new(Object.Instantiate(ToysHelper.PrimitiveBaseObject));
+ Primitive primitive = new(Object.Instantiate(Prefab));
primitive.Position = primitiveSettings.Position;
primitive.Rotation = Quaternion.Euler(primitiveSettings.Rotation);
primitive.Scale = primitiveSettings.Scale;
primitive.Flags = primitiveSettings.Flags;
- if (primitiveSettings.Spawn)
- primitive.Spawn();
-
primitive.Base.NetworkPrimitiveType = primitiveSettings.PrimitiveType;
primitive.Color = primitiveSettings.Color;
primitive.IsStatic = primitiveSettings.IsStatic;
+ if (primitiveSettings.Spawn)
+ primitive.Spawn();
+
return primitive;
}
@@ -216,8 +220,8 @@ public static Primitive Create(PrimitiveSettings primitiveSettings)
/// The corresponding instance.
public static Primitive Get(PrimitiveObjectToy primitiveObjectToy)
{
- AdminToy adminToy = Map.Toys.FirstOrDefault(x => x.AdminToyBase == primitiveObjectToy);
- return adminToy is not null ? adminToy as Primitive : new Primitive(primitiveObjectToy);
+ AdminToy adminToy = List.FirstOrDefault(x => x.AdminToyBase == primitiveObjectToy);
+ return adminToy is not null ? adminToy as Primitive : new(primitiveObjectToy);
}
}
}
diff --git a/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs b/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs
index 70bcf6f12..2951459bc 100644
--- a/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs
+++ b/EXILED/Exiled.API/Features/Toys/ShootingTargetToy.cs
@@ -46,6 +46,21 @@ internal ShootingTargetToy(ShootingTarget target)
Type = TypeLookup.TryGetValue(Base.gameObject.name.Substring(0, Base.gameObject.name.Length - 7), out ShootingTargetType type) ? type : ShootingTargetType.Unknown;
}
+ ///
+ /// Gets the prefab for Sport Shooting Target.
+ ///
+ public static ShootingTarget SportShootingTargetPrefab => PrefabHelper.GetPrefab(PrefabType.SportTarget);
+
+ ///
+ /// Gets the prefab for DBoy Shooting Target.
+ ///
+ public static ShootingTarget DboyShootingTargetPrefab => PrefabHelper.GetPrefab(PrefabType.DBoyTarget);
+
+ ///
+ /// Gets the prefab for Binary Shooting Target.
+ ///
+ public static ShootingTarget BinaryShootingTargetPrefab => PrefabHelper.GetPrefab(PrefabType.BinaryTarget);
+
///
/// Gets the base-game for this target.
///
@@ -165,19 +180,19 @@ public static ShootingTargetToy Create(ShootingTargetType type, Vector3? positio
{
case ShootingTargetType.ClassD:
{
- shootingTargetToy = new ShootingTargetToy(Object.Instantiate(ToysHelper.DboyShootingTargetObject));
+ shootingTargetToy = new(Object.Instantiate(DboyShootingTargetPrefab));
break;
}
case ShootingTargetType.Binary:
{
- shootingTargetToy = new ShootingTargetToy(Object.Instantiate(ToysHelper.BinaryShootingTargetObject));
+ shootingTargetToy = new(Object.Instantiate(BinaryShootingTargetPrefab));
break;
}
default:
{
- shootingTargetToy = new ShootingTargetToy(Object.Instantiate(ToysHelper.SportShootingTargetObject));
+ shootingTargetToy = new(Object.Instantiate(SportShootingTargetPrefab));
break;
}
}
@@ -199,8 +214,8 @@ public static ShootingTargetToy Create(ShootingTargetType type, Vector3? positio
/// The corresponding instance.
public static ShootingTargetToy Get(ShootingTarget shootingTarget)
{
- AdminToy adminToy = Map.Toys.FirstOrDefault(x => x.AdminToyBase == shootingTarget);
- return adminToy is not null ? adminToy as ShootingTargetToy : new ShootingTargetToy(shootingTarget);
+ AdminToy adminToy = List.FirstOrDefault(x => x.AdminToyBase == shootingTarget);
+ return adminToy is not null ? adminToy as ShootingTargetToy : new(shootingTarget);
}
///
diff --git a/EXILED/Exiled.API/Features/Toys/Speaker.cs b/EXILED/Exiled.API/Features/Toys/Speaker.cs
new file mode 100644
index 000000000..2ca0b2907
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Toys/Speaker.cs
@@ -0,0 +1,144 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Toys
+{
+ using System.Collections.Generic;
+
+ using AdminToys;
+ using Enums;
+ using Exiled.API.Interfaces;
+ using UnityEngine;
+ using VoiceChat.Networking;
+ using VoiceChat.Playbacks;
+
+ ///
+ /// A wrapper class for .
+ ///
+ public class Speaker : AdminToy, IWrapper
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The of the toy.
+ internal Speaker(SpeakerToy speakerToy)
+ : base(speakerToy, AdminToyType.Speaker) => Base = speakerToy;
+
+ ///
+ /// Gets the prefab.
+ ///
+ public static SpeakerToy Prefab => PrefabHelper.GetPrefab(PrefabType.SpeakerToy);
+
+ ///
+ /// Gets the base .
+ ///
+ public SpeakerToy Base { get; }
+
+ ///
+ /// Gets or sets the volume of the audio source.
+ ///
+ ///
+ /// A representing the volume level of the audio source,
+ /// where 0.0 is silent and 1.0 is full volume.
+ ///
+ public float Volume
+ {
+ get => Base.NetworkVolume;
+ set => Base.NetworkVolume = Mathf.Clamp01(value);
+ }
+
+ ///
+ /// Gets or sets a value indicating whether the audio source is spatialized.
+ ///
+ ///
+ /// A where true means the audio source is spatial, allowing
+ /// for 3D audio positioning relative to the listener; false means it is non-spatial.
+ ///
+ public bool IsSpatial
+ {
+ get => Base.NetworkIsSpatial;
+ set => Base.NetworkIsSpatial = value;
+ }
+
+ ///
+ /// Gets or sets the maximum distance at which the audio source can be heard.
+ ///
+ ///
+ /// A representing the maximum hearing distance for the audio source.
+ /// Beyond this distance, the audio will not be audible.
+ ///
+ public float MaxDistance
+ {
+ get => Base.NetworkMaxDistance;
+ set => Base.NetworkMaxDistance = value;
+ }
+
+ ///
+ /// Gets or sets the minimum distance at which the audio source reaches full volume.
+ ///
+ ///
+ /// A representing the distance from the source at which the audio is heard at full volume.
+ /// Within this range, volume will not decrease with proximity.
+ ///
+ public float MinDistance
+ {
+ get => Base.NetworkMinDistance;
+ set => Base.NetworkMinDistance = value;
+ }
+
+ ///
+ /// Gets or sets the controller ID of speaker.
+ ///
+ public byte ControllerId
+ {
+ get => Base.NetworkControllerId;
+ set => Base.NetworkControllerId = value;
+ }
+
+ ///
+ /// Creates a new .
+ ///
+ /// The position of the .
+ /// The rotation of the .
+ /// The scale of the .
+ /// Whether the should be initially spawned.
+ /// The new .
+ public static Speaker Create(Vector3? position, Vector3? rotation, Vector3? scale, bool spawn)
+ {
+ Speaker speaker = new(UnityEngine.Object.Instantiate(Prefab))
+ {
+ Position = position ?? Vector3.zero,
+ Rotation = Quaternion.Euler(rotation ?? Vector3.zero),
+ Scale = scale ?? Vector3.one,
+ };
+
+ if (spawn)
+ speaker.Spawn();
+
+ return speaker;
+ }
+
+ ///
+ /// Plays audio through this speaker.
+ ///
+ /// An instance.
+ /// Targets who will hear the audio. If null, audio will be sent to all players.
+ public static void Play(AudioMessage message, IEnumerable targets = null)
+ {
+ foreach (Player target in targets ?? Player.List)
+ target.Connection.Send(message);
+ }
+
+ ///
+ /// Plays audio through this speaker.
+ ///
+ /// Audio samples.
+ /// The length of the samples array.
+ /// Targets who will hear the audio. If null, audio will be sent to all players.
+ public void Play(byte[] samples, int? length = null, IEnumerable targets = null) => Play(new AudioMessage(ControllerId, samples, length ?? samples.Length), targets);
+ }
+}
diff --git a/EXILED/Exiled.API/Features/Toys/ToysHelper.cs b/EXILED/Exiled.API/Features/Toys/ToysHelper.cs
deleted file mode 100644
index 5ebcfc42f..000000000
--- a/EXILED/Exiled.API/Features/Toys/ToysHelper.cs
+++ /dev/null
@@ -1,142 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright (c) ExMod Team. All rights reserved.
-// Licensed under the CC BY-SA 3.0 license.
-//
-// -----------------------------------------------------------------------
-
-namespace Exiled.API.Features.Toys
-{
- using AdminToys;
-
- using Mirror;
-
- using UnityEngine;
-
- ///
- /// A helper class for interacting with toys.
- ///
- public static class ToysHelper
- {
- private static PrimitiveObjectToy primitiveBaseObject;
- private static LightSourceToy lightBaseObject;
- private static ShootingTarget sportShootingTargetObject;
- private static ShootingTarget dboyShootingTargetObject;
- private static ShootingTarget binaryShootingTargetObject;
-
- ///
- /// Gets the base to instantiate when creating a new primitive.
- ///
- public static PrimitiveObjectToy PrimitiveBaseObject
- {
- get
- {
- if (primitiveBaseObject is null)
- {
- foreach (GameObject gameObject in NetworkClient.prefabs.Values)
- {
- if (gameObject.TryGetComponent(out PrimitiveObjectToy component))
- {
- primitiveBaseObject = component;
- break;
- }
- }
- }
-
- return primitiveBaseObject;
- }
- }
-
- ///
- /// Gets the base to instantiate when creating a new light.
- ///
- public static LightSourceToy LightBaseObject
- {
- get
- {
- if (lightBaseObject is null)
- {
- foreach (GameObject gameObject in NetworkClient.prefabs.Values)
- {
- if (gameObject.TryGetComponent(out LightSourceToy component))
- {
- lightBaseObject = component;
- break;
- }
- }
- }
-
- return lightBaseObject;
- }
- }
-
- ///
- /// Gets the base to instantiate when creating a new sport shooting target.
- ///
- public static ShootingTarget SportShootingTargetObject
- {
- get
- {
- if (sportShootingTargetObject is null)
- {
- foreach (GameObject gameObject in NetworkClient.prefabs.Values)
- {
- if ((gameObject.name == "sportTargetPrefab") && gameObject.TryGetComponent(out ShootingTarget shootingTarget))
- {
- sportShootingTargetObject = shootingTarget;
- break;
- }
- }
- }
-
- return sportShootingTargetObject;
- }
- }
-
- ///
- /// Gets the base to instantiate when creating a new dboy shooting target.
- ///
- public static ShootingTarget DboyShootingTargetObject
- {
- get
- {
- if (dboyShootingTargetObject is null)
- {
- foreach (GameObject gameObject in NetworkClient.prefabs.Values)
- {
- if ((gameObject.name == "dboyTargetPrefab") && gameObject.TryGetComponent(out ShootingTarget shootingTarget))
- {
- dboyShootingTargetObject = shootingTarget;
- break;
- }
- }
- }
-
- return dboyShootingTargetObject;
- }
- }
-
- ///
- /// Gets the base to instantiate when creating a new binary shooting target.
- ///
- public static ShootingTarget BinaryShootingTargetObject
- {
- get
- {
- if (binaryShootingTargetObject is null)
- {
- foreach (GameObject gameObject in NetworkClient.prefabs.Values)
- {
- if ((gameObject.name == "binaryTargetPrefab") && gameObject.TryGetComponent(out ShootingTarget shootingTarget))
- {
- binaryShootingTargetObject = shootingTarget;
- break;
- }
- }
- }
-
- return binaryShootingTargetObject;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Warhead.cs b/EXILED/Exiled.API/Features/Warhead.cs
index 52ecea92e..a7369cfab 100644
--- a/EXILED/Exiled.API/Features/Warhead.cs
+++ b/EXILED/Exiled.API/Features/Warhead.cs
@@ -113,7 +113,7 @@ public static WarheadStatus Status
///
/// Gets a value indicating whether the warhead has already been detonated.
///
- public static bool IsDetonated => Controller._alreadyDetonated;
+ public static bool IsDetonated => Controller.AlreadyDetonated;
///
/// Gets a value indicating whether the warhead detonation is in progress.
diff --git a/EXILED/Exiled.API/Features/Waves/TimedWave.cs b/EXILED/Exiled.API/Features/Waves/TimedWave.cs
new file mode 100644
index 000000000..346bcd6c1
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Waves/TimedWave.cs
@@ -0,0 +1,198 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Waves
+{
+ using System.Collections.Generic;
+ using System.Linq;
+
+ using Exiled.API.Enums;
+ using PlayerRoles;
+ using Respawning;
+ using Respawning.Announcements;
+ using Respawning.Waves;
+
+ ///
+ /// Represents a timed wave.
+ ///
+ public class TimedWave
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ /// The that this class should be based off of.
+ ///
+ public TimedWave(TimeBasedWave wave) => Base = wave;
+
+ ///
+ /// Gets the base .
+ ///
+ public TimeBasedWave Base { get; }
+
+ ///
+ /// Gets the name of the wave timer.
+ ///
+ public string Name => Base.GetType().Name;
+
+ ///
+ /// Gets a value indicating whether the wave is a mini wave.
+ ///
+ public bool IsMiniWave => Base is IMiniWave;
+
+ ///
+ /// Gets the wave timer instance.
+ ///
+ public WaveTimer Timer => new(Base.Timer);
+
+ ///
+ /// Gets the faction of this wave.
+ ///
+ public Faction Faction => Base.TargetFaction;
+
+ ///
+ /// Gets the team of this wave.
+ ///
+ public Team Team => Base.TargetFaction.GetSpawnableTeam();
+
+ ///
+ /// Gets the spawnable faction for this wave.
+ ///
+ public SpawnableFaction SpawnableFaction => Faction switch
+ {
+ Faction.FoundationStaff when IsMiniWave => SpawnableFaction.NtfMiniWave,
+ Faction.FoundationStaff => SpawnableFaction.NtfWave,
+ Faction.FoundationEnemy when IsMiniWave => SpawnableFaction.ChaosMiniWave,
+ _ => SpawnableFaction.ChaosWave
+ };
+
+ ///
+ /// Gets the maximum amount of people that can spawn in this wave.
+ ///
+ public int MaxAmount => Base.MaxWaveSize;
+
+ ///
+ /// Gets the for this wave.
+ ///
+ /// Wave must implement .
+ public WaveAnnouncementBase Announcement => Base is IAnnouncedWave announcedWave ? announcedWave.Announcement : null;
+
+ ///
+ /// Get the timed waves for the specified faction.
+ ///
+ ///
+ /// The faction to get the waves for.
+ ///
+ ///
+ /// The waves if found.
+ ///
+ ///
+ /// A value indicating whether the wave were found.
+ ///
+ public static bool TryGetTimedWaves(Faction faction, out List waves)
+ {
+ List spawnableWaveBases = WaveManager.Waves.Where(w => w is TimeBasedWave wave && wave.TargetFaction == faction).ToList();
+ if(!spawnableWaveBases.Any())
+ {
+ waves = null;
+ return false;
+ }
+
+ waves = spawnableWaveBases.Select(w => new TimedWave((TimeBasedWave)w)).ToList();
+ return true;
+ }
+
+ ///
+ /// Get the timed waves for the specified faction.
+ ///
+ /// The faction to get the waves for.
+ /// The waves if found.
+ /// A value indicating whether the wave were found.
+ public static bool TryGetTimedWaves(Team team, out List waves)
+ {
+ List spawnableWaveBases = WaveManager.Waves.Where(w => w is TimeBasedWave wave && wave.TargetFaction.GetSpawnableTeam() == team).ToList();
+ if(!spawnableWaveBases.Any())
+ {
+ waves = null;
+ return false;
+ }
+
+ waves = spawnableWaveBases.Select(w => new TimedWave((TimeBasedWave)w)).ToList();
+ return true;
+ }
+
+ ///
+ /// Get the timed wave for the specified type.
+ ///
+ ///
+ /// The wave type to get.
+ ///
+ ///
+ /// The type of wave to get. Must be a . I.e. or .
+ ///
+ ///
+ /// A value indicating whether the wave was found.
+ ///
+ public static bool TryGetTimedWave(out TimedWave wave)
+ where T : TimeBasedWave
+ {
+ foreach (SpawnableWaveBase waveBase in WaveManager.Waves)
+ {
+ if (waveBase is not TimeBasedWave timeWave || timeWave.GetType() != typeof(T))
+ continue;
+
+ wave = new TimedWave(timeWave);
+ return true;
+ }
+
+ wave = null;
+ return false;
+ }
+
+ ///
+ /// Get all timed waves.
+ ///
+ ///
+ /// A list of all timed waves.
+ ///
+ public static List GetTimedWaves()
+ {
+ List waves = new();
+ foreach (SpawnableWaveBase wave in WaveManager.Waves)
+ {
+ if (wave is TimeBasedWave timeBasedWave)
+ {
+ waves.Add(new TimedWave(timeBasedWave));
+ }
+ }
+
+ return waves;
+ }
+
+ ///
+ /// Destroys this wave.
+ ///
+ public void Destroy() => Base.Destroy();
+
+ ///
+ /// Populates this wave with the specified amount of roles.
+ ///
+ ///
+ /// The queue to populate.
+ ///
+ ///
+ /// The amount of people to populate.
+ ///
+ public void PopulateQueue(Queue queue, int amount) => Base.PopulateQueue(queue, amount);
+
+ ///
+ /// Plays the announcement for this wave.
+ ///
+ /// Wave must implement .
+ public void PlayAnnouncement() => Announcement?.PlayAnnouncement();
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Waves/WaveTimer.cs b/EXILED/Exiled.API/Features/Waves/WaveTimer.cs
new file mode 100644
index 000000000..b99f2cf2b
--- /dev/null
+++ b/EXILED/Exiled.API/Features/Waves/WaveTimer.cs
@@ -0,0 +1,193 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.API.Features.Waves
+{
+ using System;
+
+ using System.Collections.Generic;
+
+ using System.Linq;
+
+ using PlayerRoles;
+
+ using Respawning;
+
+ using Respawning.Waves;
+
+ ///
+ /// Represents a wave timer.
+ ///
+ public class WaveTimer
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that this class should be based off of.
+ public WaveTimer(Respawning.Waves.WaveTimer wave) => Base = wave;
+
+ ///
+ /// Gets the base .
+ ///
+ public Respawning.Waves.WaveTimer Base { get; }
+
+ ///
+ /// Gets the name of the wave timer.
+ ///
+ public string Name => Base._wave.GetType().Name;
+
+ ///
+ /// Gets a value indicating whether the wave is a mini wave.
+ ///
+ public bool IsMiniWave => Base._wave is IMiniWave;
+
+ ///
+ /// Gets the amount of time left before the wave spawns.
+ ///
+ public TimeSpan TimeLeft => TimeSpan.FromSeconds(Base.TimeLeft);
+
+ ///
+ /// Gets the amount of time passed since the last wave spawned.
+ ///
+ public TimeSpan TimePassed => TimeSpan.FromSeconds(Base.TimePassed);
+
+ ///
+ /// Gets the amount of time left before this wave unpause.
+ ///
+ public TimeSpan PauseTimeLeft => TimeSpan.FromSeconds(Base.PauseTimeLeft);
+
+ ///
+ /// Gets the amount of time this wave has been paused for.
+ ///
+ public TimeSpan PausedFor => TimeSpan.FromSeconds(Base._pauseTimer);
+
+ ///
+ /// Gets a value indicating whether this wave is paused.
+ ///
+ public bool IsPaused => Base.IsPaused;
+
+ ///
+ /// Gets a value indicating whether this wave is ready to spawn.
+ ///
+ public bool IsReady => Base.IsReadyToSpawn;
+
+ ///
+ /// Gets a value indicating whether this wave is out of respawns.
+ ///
+ public bool IsRespawnable => !Base.IsOutOfRespawns;
+
+ ///
+ /// Gets the default amount of time between a respawn of this wave.
+ ///
+ public float DefaultSpawnInterval => Base.DefaultSpawnInterval;
+
+ ///
+ /// Gets the actual amount of time between a respawn of this wave.
+ ///
+ public float SpawnInterval => Base.SpawnIntervalSeconds;
+
+ ///
+ /// Get the wave timers for the specified faction.
+ ///
+ /// The faction.
+ /// The waves, if any.
+ /// A bool indicating if waves were found.
+ public static bool TryGetWaveTimers(Faction faction, out List waves)
+ {
+ if (!TimedWave.TryGetTimedWaves(faction, out List timedWaves))
+ {
+ waves = null;
+ return false;
+ }
+
+ waves = timedWaves.Select(wave => wave.Timer).ToList();
+ return true;
+ }
+
+ ///
+ /// Get the wave timers for the specified faction.
+ ///
+ /// The team.
+ /// The waves, if any.
+ /// A bool indicating if waves were found.
+ public static bool TryGetWaveTimers(Team team, out List waves)
+ {
+ if (!TimedWave.TryGetTimedWaves(team, out List timedWaves))
+ {
+ waves = null;
+ return false;
+ }
+
+ waves = timedWaves.Select(wave => wave.Timer).ToList();
+ return true;
+ }
+
+ ///
+ /// Gets all wave timers.
+ ///
+ /// A list of all wave timers.
+ public static List GetWaveTimers()
+ {
+ return TimedWave.GetTimedWaves().Select(l => l.Timer).ToList();
+ }
+
+ ///
+ /// Destroys this wave timer.
+ ///
+ public void Destroy() => Base.Destroy();
+
+ ///
+ /// Pauses this wave timer.
+ ///
+ ///
+ /// The amount of time to pause this wave timer for.
+ ///
+ public void Pause(float seconds) => Base.Pause(seconds);
+
+ ///
+ /// Unpauses this wave timer.
+ ///
+ public void Unpause() => Base.Pause(0);
+
+ ///
+ /// Resets this wave timer.
+ ///
+ ///
+ /// A value indicating whether the should be reset.
+ ///
+ public void Reset(bool resetInterval = true) => Base.Reset(resetInterval);
+
+ ///
+ /// Update the timer.
+ ///
+ public void Update() => Base.Update();
+
+ ///
+ /// Add time to the wave timer.
+ ///
+ ///
+ /// The amount of time to add in seconds.
+ ///
+ public void AddTime(float seconds) => Base.AddTime(seconds);
+
+ ///
+ /// Set the amount of time before the wave spawns.
+ ///
+ ///
+ /// The amount of time before the wave spawns.
+ ///
+ public void SetTime(TimeSpan time) => SetTime((float)time.TotalSeconds);
+
+ ///
+ /// Set the amount of time before the wave spawns.
+ ///
+ ///
+ /// The amount of time before the wave spawns, in seconds.
+ ///
+ public void SetTime(float seconds) => Base.SetTime(seconds);
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.API/Features/Window.cs b/EXILED/Exiled.API/Features/Window.cs
index 19e978148..a84767e1e 100644
--- a/EXILED/Exiled.API/Features/Window.cs
+++ b/EXILED/Exiled.API/Features/Window.cs
@@ -38,9 +38,9 @@ internal Window(BreakableWindow window, Room room)
Base = window;
Room = room;
Type = GetGlassType();
-#if Debug
+#if DEBUG
if (Type is GlassType.Unknown)
- Log.Error($"[GLASSTYPE UNKNOWN] {this}");
+ Log.Error($"[GLASSTYPE UNKNOWN] {this} BASE = {Base}");
#endif
}
@@ -132,10 +132,10 @@ public bool DisableScpDamage
///
/// Gets or sets a value indicating whether this window is broken.
///
- public BreakableWindow.BreakableWindowStatus SyncStatus
+ public bool SyncStatus
{
- get => Base.NetworksyncStatus;
- set => Base.NetworksyncStatus = value;
+ get => Base.prevStatus;
+ set => Base.prevStatus = value;
}
///
@@ -220,7 +220,7 @@ public void DamageWindow(float amount, DamageHandlerBase handler)
RoomType.LczGlassBox => GlassType.GR18,
RoomType.LczPlants => GlassType.Plants,
RoomType.Hcz049 => GlassType.Scp049,
- RoomType.Hcz079 => Recontainer.Base._activatorGlass == Base ? GlassType.Scp079Trigger : GlassType.Scp079,
+ RoomType.Hcz079 => Base._preventScpDamage ? GlassType.Scp079Trigger : GlassType.Scp079,
RoomType.HczHid => GlassType.MicroHid,
RoomType.HczTestRoom => GlassType.TestRoom,
RoomType.HczEzCheckpointA => GlassType.HczEzCheckpointA,
diff --git a/EXILED/Exiled.API/Interfaces/IDamageableDoor.cs b/EXILED/Exiled.API/Interfaces/IDamageableDoor.cs
index d5de3d106..f98eebde9 100644
--- a/EXILED/Exiled.API/Interfaces/IDamageableDoor.cs
+++ b/EXILED/Exiled.API/Interfaces/IDamageableDoor.cs
@@ -39,6 +39,11 @@ public interface IDamageableDoor
///
public DoorDamageType IgnoredDamage { get; set; }
+ ///
+ /// Repair the door.
+ ///
+ public void Repair();
+
///
/// Damages the door.
///
diff --git a/EXILED/Exiled.API/Interfaces/IWrapper.cs b/EXILED/Exiled.API/Interfaces/IWrapper.cs
index 56667c836..c2ee03b01 100644
--- a/EXILED/Exiled.API/Interfaces/IWrapper.cs
+++ b/EXILED/Exiled.API/Interfaces/IWrapper.cs
@@ -7,14 +7,11 @@
namespace Exiled.API.Interfaces
{
- using UnityEngine;
-
///
/// Defines the contract for classes that wrap a base-game object.
///
/// The base-game class that is being wrapped.
public interface IWrapper
- where T : MonoBehaviour
{
///
/// Gets the base that this class is wrapping.
diff --git a/EXILED/Exiled.CreditTags/Exiled.CreditTags.csproj b/EXILED/Exiled.CreditTags/Exiled.CreditTags.csproj
index adc9595c8..9382489fb 100644
--- a/EXILED/Exiled.CreditTags/Exiled.CreditTags.csproj
+++ b/EXILED/Exiled.CreditTags/Exiled.CreditTags.csproj
@@ -43,6 +43,4 @@
if [[ ! -z "$EXILED_DEV_REFERENCES" ]]; then cp "$(OutputPath)$(AssemblyName).dll" "$EXILED_DEV_REFERENCES/Plugins/"; fi
-
-
diff --git a/EXILED/Exiled.CustomItems/API/EventArgs/OwnerEscapingEventArgs.cs b/EXILED/Exiled.CustomItems/API/EventArgs/OwnerEscapingEventArgs.cs
index 1c81585fa..2fc89ef33 100644
--- a/EXILED/Exiled.CustomItems/API/EventArgs/OwnerEscapingEventArgs.cs
+++ b/EXILED/Exiled.CustomItems/API/EventArgs/OwnerEscapingEventArgs.cs
@@ -30,20 +30,7 @@ public class OwnerEscapingEventArgs : EscapingEventArgs
///
/// The instance.
public OwnerEscapingEventArgs(Item item, EscapingEventArgs ev)
- : this(item, ev.Player, ev.NewRole, ev.EscapeScenario, ev.RespawnTickets)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- ///
- ///
- ///
- public OwnerEscapingEventArgs(Item item, Player player, RoleTypeId newRole, EscapeScenario escapeScenario, KeyValuePair respawnTickets = default)
- : base(player, newRole, escapeScenario, respawnTickets)
+ : base(ev.Player, ev.NewRole, ev.EscapeScenario)
{
Item = item;
}
diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs b/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs
index bf3c48d37..48d725ce7 100644
--- a/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs
+++ b/EXILED/Exiled.CustomItems/API/Features/CustomGrenade.cs
@@ -94,7 +94,7 @@ public virtual Pickup Throw(Vector3 position, float force, float weight, float f
NetworkServer.Spawn(thrownProjectile.gameObject);
thrownProjectile.InfoReceivedHook(default, newInfo);
if (thrownProjectile.TryGetComponent(out Rigidbody component))
- throwable.Base.PropelBody(component, throwable.Base.FullThrowSettings.StartTorque, ThrowableNetworkHandler.GetLimitedVelocity(velocity), force, throwable.Base.FullThrowSettings.UpwardsFactor);
+ throwable.Base.PropelBody(component, throwable.Base.FullThrowSettings.StartTorque, ThrowableNetworkHandler.GetLimitedVelocity(velocity));
thrownProjectile.ServerActivate();
return Pickup.Get(thrownProjectile);
diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs
index feba8be32..5eea6969b 100644
--- a/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs
+++ b/EXILED/Exiled.CustomItems/API/Features/CustomItem.cs
@@ -53,7 +53,6 @@ namespace Exiled.CustomItems.API.Features
///
public abstract class CustomItem
{
- private static Dictionary typeLookupTable = new();
private static Dictionary stringLookupTable = new();
private static Dictionary idLookupTable = new();
@@ -121,19 +120,6 @@ public virtual ItemType Type
[YamlIgnore]
public virtual bool ShouldMessageOnGban { get; } = false;
- ///
- /// Gets a with a specific ID.
- ///
- /// The ID.
- /// The matching the search, if not registered.
- [Obsolete("Use Get(uint) instead.", true)]
- public static CustomItem? Get(int id)
- {
- if (!idLookupTable.ContainsKey((uint)id))
- idLookupTable.Add((uint)id, Registered.FirstOrDefault(i => i.Id == id));
- return idLookupTable[(uint)id];
- }
-
///
/// Gets a with a specific ID.
///
@@ -159,16 +145,11 @@ public virtual ItemType Type
}
///
- /// Gets a with a specific type.
+ /// Retrieves a collection of instances that match a specified type.
///
/// The type.
- /// The matching the search, if not registered.
- public static CustomItem? Get(Type t)
- {
- if (!typeLookupTable.ContainsKey(t))
- typeLookupTable.Add(t, Registered.FirstOrDefault(i => i.GetType() == t));
- return typeLookupTable[t];
- }
+ /// An containing all registered of the specified type.
+ public static IEnumerable Get(Type t) => Registered.Where(i => i.GetType() == t);
///
/// Tries to get a with a specific ID.
@@ -201,16 +182,16 @@ public static bool TryGet(string name, out CustomItem? customItem)
}
///
- /// Tries to get a with a specific type.
+ /// Attempts to retrieve a collection of instances of a specified type.
///
/// The of the item to look for.
- /// The found , if not registered.
- /// Returns a value indicating whether the was found.
- public static bool TryGet(Type t, out CustomItem? customItem)
+ /// An output parameter that will contain the found instances, or an empty collection if none are registered.
+ /// A boolean value indicating whether any instances of the specified type were found.
+ public static bool TryGet(Type t, out IEnumerable customItems)
{
- customItem = Get(t);
+ customItems = Get(t);
- return customItem is not null;
+ return customItems.Any();
}
///
@@ -345,23 +326,6 @@ public static bool TryGive(Player player, uint id, bool displayMessage = true)
return true;
}
- ///
- /// Gives to a specific a specic .
- ///
- /// The to give the item to.
- /// The of the item to give.
- /// Indicates a value whether will be called when the player receives the or not.
- /// Returns a value indicating if the player was given the or not.
- public static bool TryGive(Player player, Type t, bool displayMessage = true)
- {
- if (!TryGet(t, out CustomItem? item))
- return false;
-
- item?.Give(player, displayMessage);
-
- return true;
- }
-
///
/// Registers all the 's present in the current assembly.
///
@@ -619,20 +583,17 @@ public virtual uint Spawn(IEnumerable spawnPoints, uint limit)
spawned++;
-#pragma warning disable CS0618 // Type or member is obsolete \\ TODO: REMOVE THIS
- if (spawnPoint is DynamicSpawnPoint dynamicSpawnPoint && dynamicSpawnPoint.Location == SpawnLocationType.InsideLocker)
+ /*if (spawnPoint is DynamicSpawnPoint dynamicSpawnPoint && dynamicSpawnPoint.Location == SpawnLocationType.InsideLocker)
{
for (int i = 0; i < 50; i++)
{
- if (Map.Lockers is null)
+ if (Exiled.API.Features.Lockers.Locker.List is null)
{
Log.Debug($"{nameof(Spawn)}: Locker list is null.");
continue;
}
- Locker locker =
- Map.Lockers[
- Loader.Random.Next(Map.Lockers.Count)];
+ Locker locker = Exiled.API.Features.Lockers.Locker.Random();
if (locker is null)
{
@@ -683,8 +644,20 @@ public virtual uint Spawn(IEnumerable spawnPoints, uint limit)
}
Log.Debug($"Spawned {Name} at {spawnPoint.Position} ({spawnPoint.Name})");
+ }*/
+
+ Pickup? pickup = Spawn(spawnPoint.Position);
+
+ if (pickup == null)
+ continue;
+
+ if (spawnPoint is LockerSpawnPoint)
+ pickup.IsLocked = true;
+
+ if (pickup.Is(out Exiled.API.Features.Pickups.FirearmPickup firearmPickup) && this is CustomWeapon customWeapon)
+ {
+ // set MaxAmmo if synced TODO
}
-#pragma warning restore CS0618 // Type or member is obsolete
}
return spawned;
@@ -725,7 +698,7 @@ public virtual void Give(Player player, Item item, bool displayMessage = true)
{
try
{
- Log.Debug($"{Name}.{nameof(Give)}: Item Serial: {item.Serial} Ammo: {(item is Firearm firearm ? firearm.Ammo : -1)}");
+ Log.Debug($"{Name}.{nameof(Give)}: Item Serial: {item.Serial} Ammo: {(item is Firearm firearm ? firearm.MagazineAmmo : -1)}");
player.AddItem(item);
@@ -761,7 +734,6 @@ public virtual void Give(Player player, Item item, bool displayMessage = true)
///
public virtual void Init()
{
- typeLookupTable.Add(GetType(), this);
stringLookupTable.Add(Name, this);
idLookupTable.Add(Id, this);
@@ -775,7 +747,6 @@ public virtual void Destroy()
{
UnsubscribeEvents();
- typeLookupTable.Remove(GetType());
stringLookupTable.Remove(Name);
idLookupTable.Remove(Id);
}
@@ -1002,7 +973,7 @@ protected virtual void ShowSelectedMessage(Player player)
private void OnInternalOwnerChangingRole(ChangingRoleEventArgs ev)
{
- if (ev.Reason == SpawnReason.Escaped)
+ if (ev.Reason is SpawnReason.Escaped or SpawnReason.Destroyed)
return;
foreach (Item item in ev.Player.Items.ToList())
diff --git a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs
index 8151b4d55..dea5aec5c 100644
--- a/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs
+++ b/EXILED/Exiled.CustomItems/API/Features/CustomWeapon.cs
@@ -76,8 +76,8 @@ public override ItemType Type
if (!Attachments.IsEmpty())
firearm.AddAttachment(Attachments);
- firearm.Ammo = ClipSize;
- firearm.MaxAmmo = ClipSize;
+ firearm.MagazineAmmo = ClipSize;
+ firearm.MaxMagazineAmmo = ClipSize;
Pickup? pickup = firearm.CreatePickup(position);
@@ -104,8 +104,8 @@ public override ItemType Type
if (!Attachments.IsEmpty())
firearm.AddAttachment(Attachments);
- byte ammo = firearm.Ammo;
- firearm.MaxAmmo = ClipSize;
+ int ammo = firearm.MagazineAmmo;
+ firearm.MaxMagazineAmmo = ClipSize;
Log.Debug($"{nameof(Name)}.{nameof(Spawn)}: Spawning weapon with {ammo} ammo.");
Pickup? pickup = firearm.CreatePickup(position);
pickup.Scale = Scale;
@@ -130,8 +130,8 @@ public override void Give(Player player, bool displayMessage = true)
if (!Attachments.IsEmpty())
firearm.AddAttachment(Attachments);
- firearm.Ammo = ClipSize;
- firearm.MaxAmmo = ClipSize;
+ firearm.MagazineAmmo = ClipSize;
+ firearm.MaxMagazineAmmo = ClipSize;
}
Log.Debug($"{nameof(Give)}: Adding {item.Serial} to tracker.");
@@ -214,7 +214,7 @@ private void OnInternalReloading(ReloadingWeaponEventArgs ev)
Log.Debug($"{nameof(Name)}.{nameof(OnInternalReloading)}: Continuing with internal reload..");
ev.IsAllowed = false;
- byte remainingClip = ((Firearm)ev.Player.CurrentItem).Ammo;
+ int remainingClip = ((Firearm)ev.Player.CurrentItem).MagazineAmmo;
if (remainingClip >= ClipSize)
return;
@@ -229,7 +229,7 @@ private void OnInternalReloading(ReloadingWeaponEventArgs ev)
return;
}
- ev.Player.Connection.Send(new RequestMessage(ev.Firearm.Serial, RequestType.Reload));
+ ev.Firearm.Reload();
byte amountToReload = (byte)Math.Min(ClipSize - remainingClip, ev.Player.Ammo[ammoType.GetItemType()]);
@@ -241,9 +241,9 @@ private void OnInternalReloading(ReloadingWeaponEventArgs ev)
ev.Player.Ammo[ammoType.GetItemType()] -= amountToReload;
ev.Player.Inventory.SendAmmoNextFrame = true;
- ((Firearm)ev.Player.CurrentItem).Ammo = (byte)(((Firearm)ev.Player.CurrentItem).Ammo + amountToReload);
+ ((Firearm)ev.Player.CurrentItem).MagazineAmmo = (byte)(((Firearm)ev.Player.CurrentItem).MagazineAmmo + amountToReload);
- Log.Debug($"{ev.Player.Nickname} ({ev.Player.UserId}) [{ev.Player.Role}] reloaded a {Name} ({Id}) [{Type} ({((Firearm)ev.Player.CurrentItem).Ammo}/{ClipSize})]!");
+ Log.Debug($"{ev.Player.Nickname} ({ev.Player.UserId}) [{ev.Player.Role}] reloaded a {Name} ({Id}) [{Type} ({((Firearm)ev.Player.CurrentItem).MagazineAmmo}/{ClipSize})]!");
}
private void OnInternalShooting(ShootingEventArgs ev)
diff --git a/EXILED/Exiled.CustomItems/Commands/Give.cs b/EXILED/Exiled.CustomItems/Commands/Give.cs
index 31151934a..cc63ed222 100644
--- a/EXILED/Exiled.CustomItems/Commands/Give.cs
+++ b/EXILED/Exiled.CustomItems/Commands/Give.cs
@@ -18,6 +18,8 @@ namespace Exiled.CustomItems.Commands
using Exiled.Permissions.Extensions;
using RemoteAdmin;
+ using UnityStandardAssets.Effects;
+ using Utils;
///
/// The command to give a player an item.
@@ -97,22 +99,27 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s
response = $"Custom item {item?.Name} given to all players who can receive them ({eligiblePlayers.Count} players)";
return true;
default:
- if (Player.Get(identifier) is not { } player)
- {
- response = $"Unable to find player: {identifier}.";
- return false;
- }
+ break;
+ }
- if (!CheckEligible(player))
- {
- response = "Player cannot receive custom items!";
- return false;
- }
+ IEnumerable list = Player.GetProcessedData(arguments, 1);
+
+ if (list.IsEmpty())
+ {
+ response = "Cannot find player! Try using the player ID!";
+ return false;
+ }
+ foreach (Player player in list)
+ {
+ if (CheckEligible(player))
+ {
item?.Give(player);
- response = $"{item?.Name} given to {player.Nickname} ({player.UserId})";
- return true;
+ }
}
+
+ response = $"{item?.Name} given to {list.Count()} players!";
+ return true;
}
///
@@ -120,4 +127,4 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s
///
private bool CheckEligible(Player player) => player.IsAlive && !player.IsCuffed && (player.Items.Count < 8);
}
-}
\ No newline at end of file
+}
diff --git a/EXILED/Exiled.CustomRoles/API/Features/ActiveAbility.cs b/EXILED/Exiled.CustomRoles/API/Features/ActiveAbility.cs
index de4869800..cadc7c63f 100644
--- a/EXILED/Exiled.CustomRoles/API/Features/ActiveAbility.cs
+++ b/EXILED/Exiled.CustomRoles/API/Features/ActiveAbility.cs
@@ -227,14 +227,6 @@ protected virtual void AbilityEnded(Player player)
{
}
- ///
- /// Called when the ability is successfully used.
- ///
- /// The using the ability.
- [Obsolete("The Keypress Activator will already do this, you do not need to call this unless you are overwriting the keypress activator.", true)]
- protected virtual void ShowMessage(Player player) =>
- player.ShowHint(string.Format(CustomRoles.Instance!.Config.UsedAbilityHint.Content, Name, Description), CustomRoles.Instance.Config.UsedAbilityHint.Duration);
-
///
/// Called when the ability is selected.
///
diff --git a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs
index 56f3e5895..b8217fb41 100644
--- a/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs
+++ b/EXILED/Exiled.CustomRoles/API/Features/CustomRole.cs
@@ -926,6 +926,9 @@ private void OnInternalSpawning(SpawningEventArgs ev)
private void OnInternalChangingRole(ChangingRoleEventArgs ev)
{
+ if(ev.Reason == SpawnReason.Destroyed)
+ return;
+
if (Check(ev.Player) && ((ev.NewRole == RoleTypeId.Spectator && !KeepRoleOnDeath) || (ev.NewRole != RoleTypeId.Spectator && ev.NewRole != Role && !KeepRoleOnChangingRole)))
{
RemoveRole(ev.Player);
diff --git a/EXILED/Exiled.CustomRoles/Commands/Give.cs b/EXILED/Exiled.CustomRoles/Commands/Give.cs
index ed52669f8..4eb357feb 100644
--- a/EXILED/Exiled.CustomRoles/Commands/Give.cs
+++ b/EXILED/Exiled.CustomRoles/Commands/Give.cs
@@ -19,6 +19,7 @@ namespace Exiled.CustomRoles.Commands
using Exiled.Permissions.Extensions;
using RemoteAdmin;
+ using Utils;
///
/// The command to give a role to player(s).
@@ -96,16 +97,24 @@ public bool Execute(ArraySegment arguments, ICommandSender sender, out s
ListPool.Pool.Return(players);
return true;
default:
- if (Player.Get(identifier) is not Player ply)
- {
- response = $"Unable to find a player: {identifier}";
- return false;
- }
-
- role.AddRole(ply);
- response = $"{role.Name} given to {ply.Nickname}.";
- return true;
+ break;
+ }
+
+ IEnumerable list = Player.GetProcessedData(arguments, 1);
+ if (list.IsEmpty())
+ {
+ response = "Cannot find player! Try using the player ID!";
+ return false;
}
+
+ foreach (Player player in list)
+ {
+ role.AddRole(player);
+ }
+
+ response = $"Customrole {role.Name} given to {list.Count()} players!";
+
+ return true;
}
catch (Exception e)
{
diff --git a/EXILED/Exiled.Events/EventArgs/Interfaces/IItemEvent.cs b/EXILED/Exiled.Events/EventArgs/Interfaces/IItemEvent.cs
index 5e838badd..c2fcb61da 100644
--- a/EXILED/Exiled.Events/EventArgs/Interfaces/IItemEvent.cs
+++ b/EXILED/Exiled.Events/EventArgs/Interfaces/IItemEvent.cs
@@ -12,7 +12,7 @@ namespace Exiled.Events.EventArgs.Interfaces
///
/// Event args used for all related events.
///
- public interface IItemEvent : IExiledEvent
+ public interface IItemEvent : IPlayerEvent
{
///
/// Gets the triggering the event.
diff --git a/EXILED/Exiled.Events/EventArgs/Interfaces/IScp1344Event.cs b/EXILED/Exiled.Events/EventArgs/Interfaces/IScp1344Event.cs
new file mode 100644
index 000000000..c2009ae7d
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Interfaces/IScp1344Event.cs
@@ -0,0 +1,22 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Interfaces
+{
+ using Exiled.API.Features.Items;
+
+ ///
+ /// Event args used for all related events.
+ ///
+ public interface IScp1344Event : IItemEvent
+ {
+ ///
+ /// Gets the triggering the event.
+ ///
+ public Scp1344 Scp1344 { get; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Item/ChargingJailbirdEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Item/ChargingJailbirdEventArgs.cs
index 7e4d21b1c..342d4b311 100644
--- a/EXILED/Exiled.Events/EventArgs/Item/ChargingJailbirdEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Item/ChargingJailbirdEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Item
{
- using System;
-
using Exiled.API.Features;
using Exiled.API.Features.Items;
using Exiled.Events.EventArgs.Interfaces;
@@ -16,7 +14,7 @@ namespace Exiled.Events.EventArgs.Item
///
/// Contains all information before a player charges a .
///
- public class ChargingJailbirdEventArgs : IPlayerEvent, IItemEvent, IDeniableEvent
+ public class ChargingJailbirdEventArgs : IItemEvent
{
///
/// Initializes a new instance of the class.
@@ -49,13 +47,8 @@ public ChargingJailbirdEventArgs(ReferenceHub player, InventorySystem.Items.Item
public Item Item => Jailbird;
///
- /// Gets or sets a value indicating whether the Jailbird can be charged.
+ /// Gets a value indicating whether the Jailbird can be charged.
///
- public bool IsAllowed
- {
- get;
- [Obsolete("This event cannot be denied as it will cause desync.")]
- set;
- }
+ public bool IsAllowed { get; }
}
}
diff --git a/EXILED/Exiled.Events/EventArgs/Item/SwingingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Item/SwingingEventArgs.cs
index 0a63b6c9b..0d97d9da1 100644
--- a/EXILED/Exiled.Events/EventArgs/Item/SwingingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Item/SwingingEventArgs.cs
@@ -14,7 +14,7 @@ namespace Exiled.Events.EventArgs.Item
///
/// Contains all information before a player swings a .
///
- public class SwingingEventArgs : IPlayerEvent, IItemEvent, IDeniableEvent
+ public class SwingingEventArgs : IItemEvent, IDeniableEvent
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.Events/EventArgs/Map/AnnouncingChaosEntranceEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/AnnouncingChaosEntranceEventArgs.cs
new file mode 100644
index 000000000..e0e7fb893
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Map/AnnouncingChaosEntranceEventArgs.cs
@@ -0,0 +1,46 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Map
+{
+ using System.Text;
+
+ using Exiled.API.Features.Waves;
+ using Exiled.Events.EventArgs.Interfaces;
+ using Respawning.Announcements;
+
+ ///
+ /// Contains all information before Chaos wave entrance.
+ ///
+ public class AnnouncingChaosEntranceEventArgs : IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public AnnouncingChaosEntranceEventArgs(WaveAnnouncementBase announcement, StringBuilder builder)
+ {
+ Wave = TimedWave.GetTimedWaves().Find(x => x.Announcement == announcement);
+ Words = builder;
+ }
+
+ ///
+ /// Gets the entering wave.
+ ///
+ public TimedWave Wave { get; }
+
+ ///
+ /// Gets the of the words that C.A.S.S.I.E will say.
+ /// It doesn't affect the subtitle part that will be sent to the client.
+ ///
+ public StringBuilder Words { get; }
+
+ ///
+ public bool IsAllowed { get; set; } = true;
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Map/AnnouncingNtfEntranceEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/AnnouncingNtfEntranceEventArgs.cs
index f961a19de..40a9fd315 100644
--- a/EXILED/Exiled.Events/EventArgs/Map/AnnouncingNtfEntranceEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Map/AnnouncingNtfEntranceEventArgs.cs
@@ -7,7 +7,9 @@
namespace Exiled.Events.EventArgs.Map
{
+ using Exiled.API.Features.Waves;
using Interfaces;
+ using Respawning.Announcements;
///
/// Contains all information before C.A.S.S.I.E announces the NTF entrance.
@@ -17,26 +19,23 @@ public class AnnouncingNtfEntranceEventArgs : IDeniableEvent
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public AnnouncingNtfEntranceEventArgs(int scpsLeft, string unitName, int unitNumber, bool isAllowed = true)
+ ///
+ ///
+ ///
+ ///
+ public AnnouncingNtfEntranceEventArgs(WaveAnnouncementBase announcement, int scpsLeft, string unitName, int unitNumber)
{
+ Wave = TimedWave.GetTimedWaves().Find(x => x.Announcement == announcement);
ScpsLeft = scpsLeft;
UnitName = unitName;
UnitNumber = unitNumber;
- IsAllowed = isAllowed;
}
+ ///
+ /// Gets the entering wave.
+ ///
+ public TimedWave Wave { get; }
+
///
/// Gets or sets the number of SCPs left.
///
@@ -55,6 +54,6 @@ public AnnouncingNtfEntranceEventArgs(int scpsLeft, string unitName, int unitNum
///
/// Gets or sets a value indicating whether the NTF spawn will be announced by C.A.S.S.I.E.
///
- public bool IsAllowed { get; set; }
+ public bool IsAllowed { get; set; } = true;
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Map/ChangedIntoGrenadeEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/ChangedIntoGrenadeEventArgs.cs
index d1f4cd82a..94f5b93a3 100644
--- a/EXILED/Exiled.Events/EventArgs/Map/ChangedIntoGrenadeEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Map/ChangedIntoGrenadeEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Map
{
- using System;
-
using Exiled.API.Features.Pickups;
using Exiled.API.Features.Pickups.Projectiles;
using Exiled.Events.EventArgs.Interfaces;
@@ -26,8 +24,8 @@ public class ChangedIntoGrenadeEventArgs : IExiledEvent
/// The .
public ChangedIntoGrenadeEventArgs(TimedGrenadePickup pickup, ThrownProjectile projectile)
{
- Pickup = (GrenadePickup)API.Features.Pickups.Pickup.Get(pickup);
- Projectile = (Projectile)API.Features.Pickups.Pickup.Get(projectile);
+ Pickup = API.Features.Pickups.Pickup.Get(pickup);
+ Projectile = API.Features.Pickups.Pickup.Get(projectile);
}
///
@@ -39,11 +37,5 @@ public ChangedIntoGrenadeEventArgs(TimedGrenadePickup pickup, ThrownProjectile p
/// Gets a value indicating the projectile that spawned.
///
public Projectile Projectile { get; }
-
- ///
- /// Gets or sets a value indicating how long the fuse of the changed grenade will be.
- ///
- [Obsolete("Use Projectile.Is(Projectile, out TimeGrenadeProjectile timeGrenadeProjectile) ? timeGrenadeProjectile.FuseTime : 0 instead of this", true)]
- public double FuseTime { get; set; }
}
}
diff --git a/EXILED/Exiled.Events/EventArgs/Map/ExplodingGrenadeEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/ExplodingGrenadeEventArgs.cs
index 6bd4343a1..27b0bc165 100644
--- a/EXILED/Exiled.Events/EventArgs/Map/ExplodingGrenadeEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Map/ExplodingGrenadeEventArgs.cs
@@ -39,7 +39,7 @@ public ExplodingGrenadeEventArgs(Footprint thrower, Vector3 position, ExplosionG
Player = Player.Get(thrower.Hub);
Projectile = Pickup.Get(grenade);
Position = position;
- TargetsToAffect = ListPool.Pool.Get();
+ TargetsToAffect = HashSetPool.Pool.Get();
if (Projectile.Base is not ExplosionGrenade)
return;
@@ -59,8 +59,7 @@ public ExplodingGrenadeEventArgs(Footprint thrower, Vector3 position, ExplosionG
{
if (Server.FriendlyFire || IndividualFriendlyFire.CheckFriendlyFirePlayer(thrower, hub))
{
- if (!TargetsToAffect.Contains(player))
- TargetsToAffect.Add(player);
+ TargetsToAffect.Add(player);
}
}
@@ -69,8 +68,7 @@ public ExplodingGrenadeEventArgs(Footprint thrower, Vector3 position, ExplosionG
{
if (Server.FriendlyFire || thrower.Hub == Server.Host.ReferenceHub || HitboxIdentity.IsEnemy(thrower.Role, hub.roleManager.CurrentRole.RoleTypeId))
{
- if (!TargetsToAffect.Contains(player))
- TargetsToAffect.Add(player);
+ TargetsToAffect.Add(player);
}
}
@@ -94,12 +92,12 @@ public ExplodingGrenadeEventArgs(Footprint thrower, Vector3 position, ExplosionG
///
///
///
- public ExplodingGrenadeEventArgs(Player thrower, EffectGrenade grenade, List targetsToAffect, bool isAllowed = true)
+ public ExplodingGrenadeEventArgs(Player thrower, EffectGrenade grenade, HashSet targetsToAffect, bool isAllowed = true)
{
Player = thrower ?? Server.Host;
Projectile = Pickup.Get(grenade);
Position = Projectile.Position;
- TargetsToAffect = ListPool.Pool.Get(targetsToAffect ?? new());
+ TargetsToAffect = HashSetPool.Pool.Get(targetsToAffect ?? new HashSet());
IsAllowed = isAllowed;
}
@@ -108,7 +106,7 @@ public ExplodingGrenadeEventArgs(Player thrower, EffectGrenade grenade, List
~ExplodingGrenadeEventArgs()
{
- ListPool.Pool.Return(TargetsToAffect);
+ HashSetPool.Pool.Return(TargetsToAffect);
}
///
@@ -119,7 +117,7 @@ public ExplodingGrenadeEventArgs(Player thrower, EffectGrenade grenade, List
/// Gets the players who could be affected by the grenade, if any, and the damage that be dealt.
///
- public List TargetsToAffect { get; }
+ public HashSet TargetsToAffect { get; }
///
/// Gets the grenade that is exploding.
diff --git a/EXILED/Exiled.Events/EventArgs/Map/FillingLockerEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/FillingLockerEventArgs.cs
index 794aae85f..66043379d 100644
--- a/EXILED/Exiled.Events/EventArgs/Map/FillingLockerEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Map/FillingLockerEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Map
{
- using System;
-
using Exiled.API.Features.Lockers;
using Exiled.API.Features.Pickups;
using Exiled.Events.EventArgs.Interfaces;
@@ -40,12 +38,6 @@ public FillingLockerEventArgs(ItemPickupBase pickupBase, LockerChamber lockerCha
///
public Pickup Pickup { get; }
- ///
- /// Gets a value indicating the target locker chamber.
- ///
- [Obsolete("Use Chamber instead.")]
- public LockerChamber LockerChamber => Chamber.Base;
-
///
/// Gets a locker which is containing .
///
diff --git a/EXILED/Exiled.Events/EventArgs/Map/PlacingBloodEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/PlacingBloodEventArgs.cs
deleted file mode 100644
index 673b51915..000000000
--- a/EXILED/Exiled.Events/EventArgs/Map/PlacingBloodEventArgs.cs
+++ /dev/null
@@ -1,64 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright (c) ExMod Team. All rights reserved.
-// Licensed under the CC BY-SA 3.0 license.
-//
-// -----------------------------------------------------------------------
-
-namespace Exiled.Events.EventArgs.Map
-{
- using API.Features;
-
- using Interfaces;
-
- using UnityEngine;
-
- ///
- /// Contains all information before placing a blood decal.
- ///
- public class PlacingBloodEventArgs : IPlayerEvent, IDeniableEvent
- {
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public PlacingBloodEventArgs(Player player, Player target, RaycastHit hit, bool isAllowed = true)
- {
- Player = player;
- Target = target;
- Position = hit.point;
- IsAllowed = isAllowed;
- }
-
- ///
- /// Gets the who's placing the blood.
- ///
- public Player Player { get; }
-
- ///
- /// Gets the target's instance.
- ///
- public Player Target { get; }
-
- ///
- /// Gets or sets the blood placing position.
- ///
- public Vector3 Position { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the blood can be placed.
- ///
- public bool IsAllowed { get; set; }
- }
-}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Map/PlacingBulletHoleEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/PlacingBulletHoleEventArgs.cs
index 2e8fed7e3..8a066fbaf 100644
--- a/EXILED/Exiled.Events/EventArgs/Map/PlacingBulletHoleEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Map/PlacingBulletHoleEventArgs.cs
@@ -8,7 +8,7 @@
namespace Exiled.Events.EventArgs.Map
{
using API.Features;
-
+ using Exiled.API.Features.Items;
using Interfaces;
using UnityEngine;
@@ -16,20 +16,21 @@ namespace Exiled.Events.EventArgs.Map
///
/// Contains all information before placing a bullet hole decal.
///
- public class PlacingBulletHoleEventArgs : IPlayerEvent, IDeniableEvent
+ public class PlacingBulletHoleEventArgs : IFirearmEvent, IPlayerEvent, IDeniableEvent
{
///
/// Initializes a new instance of the class.
///
- ///
- ///
+ ///
+ ///
///
///
///
///
- public PlacingBulletHoleEventArgs(Player owner, RaycastHit hit)
+ public PlacingBulletHoleEventArgs(Item firearm, RaycastHit hit)
{
- Player = owner;
+ Firearm = firearm.As();
+ Player = Firearm.Owner;
Position = hit.point;
Rotation = Quaternion.LookRotation(hit.normal);
}
@@ -53,5 +54,11 @@ public PlacingBulletHoleEventArgs(Player owner, RaycastHit hit)
/// Gets the decal owner.
///
public Player Player { get; }
+
+ ///
+ public Firearm Firearm { get; }
+
+ ///
+ public Item Item => Firearm;
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Map/SpawningTeamVehicleEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Map/SpawningTeamVehicleEventArgs.cs
index 16b31daac..2e455ff30 100644
--- a/EXILED/Exiled.Events/EventArgs/Map/SpawningTeamVehicleEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Map/SpawningTeamVehicleEventArgs.cs
@@ -9,6 +9,7 @@ namespace Exiled.Events.EventArgs.Map
{
using Exiled.Events.EventArgs.Interfaces;
using Respawning;
+ using Respawning.Waves;
///
/// Contains all information before the server spawns a team's respawn vehicle.
@@ -24,7 +25,7 @@ public class SpawningTeamVehicleEventArgs : IDeniableEvent
///
///
///
- public SpawningTeamVehicleEventArgs(SpawnableTeamType team, bool isAllowed = true)
+ public SpawningTeamVehicleEventArgs(SpawnableWaveBase team, bool isAllowed = true)
{
Team = team;
IsAllowed = isAllowed;
@@ -33,7 +34,7 @@ public SpawningTeamVehicleEventArgs(SpawnableTeamType team, bool isAllowed = tru
///
/// Gets or sets which vehicle should spawn.
///
- public SpawnableTeamType Team { get; set; }
+ public SpawnableWaveBase Team { get; set; }
///
/// Gets or sets a value indicating whether the vehicle can be spawned.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/AimingDownSightEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/AimingDownSightEventArgs.cs
index 79cf3c5cb..945295631 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/AimingDownSightEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/AimingDownSightEventArgs.cs
@@ -12,33 +12,27 @@ namespace Exiled.Events.EventArgs.Player
using Interfaces;
+ using FirearmBase = InventorySystem.Items.Firearms.Firearm;
+
///
/// Contains all information when a player aims.
///
- // TODO: remove stupid AdsIn/AdsOut propetry, and let exists only one
public class AimingDownSightEventArgs : IPlayerEvent, IFirearmEvent
{
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
///
///
///
///
///
///
- ///
- ///
- ///
- public AimingDownSightEventArgs(Player player, Firearm firearm, bool adsIn, bool adsOut)
+ public AimingDownSightEventArgs(FirearmBase firearm, bool adsIn)
{
- Firearm = firearm;
- Player = player;
+ Firearm = Item.Get(firearm);
+ Player = Firearm.Owner;
AdsIn = adsIn;
- AdsOut = adsOut;
}
///
@@ -46,11 +40,6 @@ public AimingDownSightEventArgs(Player player, Firearm firearm, bool adsIn, bool
///
public bool AdsIn { get; }
- ///
- /// Gets a value indicating whether the player is aiming down sight out.
- ///
- public bool AdsOut { get; }
-
///
/// Gets the used to trigger the aim action.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangedEmotionEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangedEmotionEventArgs.cs
new file mode 100644
index 000000000..cd5e3447a
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangedEmotionEventArgs.cs
@@ -0,0 +1,38 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Player
+{
+ using Exiled.API.Features;
+ using Exiled.Events.EventArgs.Interfaces;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
+
+ ///
+ /// Contains all the information after the player's emotion.
+ ///
+ public class ChangedEmotionEventArgs : IPlayerEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public ChangedEmotionEventArgs(ReferenceHub hub, EmotionPresetType emotionPresetType)
+ {
+ Player = Player.Get(hub);
+ EmotionPresetType = emotionPresetType;
+ }
+
+ ///
+ /// Gets the player's emotion.
+ ///
+ public EmotionPresetType EmotionPresetType { get; }
+
+ ///
+ public Player Player { get; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangedItemEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangedItemEventArgs.cs
index 44f032779..238125690 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ChangedItemEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangedItemEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Player
{
- using System;
-
using API.Features;
using API.Features.Items;
@@ -19,7 +17,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information after a player's held item changes.
///
- public class ChangedItemEventArgs : IPlayerEvent, IItemEvent
+ public class ChangedItemEventArgs : IItemEvent
{
///
/// Initializes a new instance of the class.
@@ -42,12 +40,6 @@ public ChangedItemEventArgs(Player player, ItemBase oldItem)
///
public Item OldItem { get; }
- ///
- /// Gets the new item.
- ///
- [Obsolete("Use ev.Item instead of this")]
- public Item NewItem => Item;
-
///
/// Gets the new item.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangingDisruptorModeEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangingDisruptorModeEventArgs.cs
new file mode 100644
index 000000000..68fe52816
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangingDisruptorModeEventArgs.cs
@@ -0,0 +1,45 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Player
+{
+ using Exiled.API.Enums;
+ using Exiled.API.Features;
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+
+ ///
+ /// Contains all information before disruptor's mode is changed.
+ ///
+ public class ChangingDisruptorModeEventArgs : IFirearmEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public ChangingDisruptorModeEventArgs(Item firearm, bool mode)
+ {
+ Firearm = firearm.As();
+ NewMode = mode ? DisruptorMode.Disintegrator : DisruptorMode.BurstFire;
+ }
+
+ ///
+ public Item Item => Firearm;
+
+ ///
+ public Firearm Firearm { get; }
+
+ ///
+ /// Gets a new disruptor's fire mode.
+ ///
+ public DisruptorMode NewMode { get; }
+
+ ///
+ public Player Player => Item.Owner;
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangingEmotionEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangingEmotionEventArgs.cs
new file mode 100644
index 000000000..759f1fa9e
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangingEmotionEventArgs.cs
@@ -0,0 +1,50 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Player
+{
+ using Exiled.API.Features;
+ using Exiled.Events.EventArgs.Interfaces;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
+
+ ///
+ /// Contains all the information before the player's emotion changes.
+ ///
+ public class ChangingEmotionEventArgs : IDeniableEvent, IPlayerEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ChangingEmotionEventArgs(ReferenceHub hub, EmotionPresetType newEmotionPresetType, EmotionPresetType oldEmotionPresetType, bool isAllowed = true)
+ {
+ Player = Player.Get(hub);
+ NewEmotionPresetType = newEmotionPresetType;
+ OldEmotionPresetType = oldEmotionPresetType;
+ IsAllowed = isAllowed;
+ }
+
+ ///
+ public bool IsAllowed { get; set; }
+
+ ///
+ /// Gets the old player's emotion.
+ ///
+ public EmotionPresetType OldEmotionPresetType { get; }
+
+ ///
+ /// Gets or sets the new player's emotion.
+ ///
+ public EmotionPresetType NewEmotionPresetType { get; set; }
+
+ ///
+ public Player Player { get; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangingMicroHIDStateEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangingMicroHIDStateEventArgs.cs
index 038724137..f472a7096 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ChangingMicroHIDStateEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangingMicroHIDStateEventArgs.cs
@@ -7,42 +7,35 @@
namespace Exiled.Events.EventArgs.Player
{
+ using System;
+
using API.Features;
using API.Features.Items;
-
using Interfaces;
-
using InventorySystem.Items.MicroHID;
+ using InventorySystem.Items.MicroHID.Modules;
///
/// Contains all information before MicroHID state is changed.
///
- public class ChangingMicroHIDStateEventArgs : IPlayerEvent, IDeniableEvent
+ public class ChangingMicroHIDStateEventArgs : IDeniableEvent, IItemEvent
{
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
///
///
///
- ///
- ///
- ///
- ///
- ///
+ ///
+ ///
///
///
///
///
- public ChangingMicroHIDStateEventArgs(Player player, MicroHIDItem microHID, HidState oldState, HidState newState, bool isAllowed = true)
+ public ChangingMicroHIDStateEventArgs(Item microHID, MicroHidPhase newPhase, bool isAllowed = true)
{
- Player = player;
- MicroHID = Item.Get(microHID);
- OldState = oldState;
- NewState = newState;
+ MicroHID = microHID.As();
+ NewPhase = newPhase;
IsAllowed = isAllowed;
}
@@ -51,24 +44,20 @@ public ChangingMicroHIDStateEventArgs(Player player, MicroHIDItem microHID, HidS
///
public MicroHid MicroHID { get; }
- ///
- /// Gets the old MicroHID state.
- ///
- public HidState OldState { get; }
-
///
/// Gets or sets the new MicroHID state.
///
- public HidState NewState { get; set; }
+ public MicroHidPhase NewPhase { get; set; }
///
/// Gets or sets a value indicating whether the MicroHID state can be changed.
///
public bool IsAllowed { get; set; }
- ///
- /// Gets the player who's using the MicroHID.
- ///
- public Player Player { get; }
+ ///
+ public Item Item => MicroHID;
+
+ ///
+ public Player Player => MicroHID.Owner;
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangingMoveStateEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangingMoveStateEventArgs.cs
index 3be8dd579..36d524015 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ChangingMoveStateEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangingMoveStateEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Player
{
- using System;
-
using API.Features;
using Interfaces;
@@ -18,7 +16,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information before changing movement state.
///
- public class ChangingMoveStateEventArgs : IPlayerEvent, IDeniableEvent
+ public class ChangingMoveStateEventArgs : IPlayerEvent
{
///
/// Initializes a new instance of the class.
@@ -32,16 +30,11 @@ public class ChangingMoveStateEventArgs : IPlayerEvent, IDeniableEvent
///
///
///
- ///
- ///
- ///
- public ChangingMoveStateEventArgs(Player player, PlayerMovementState oldState, PlayerMovementState newState, bool isAllowed = true)
+ public ChangingMoveStateEventArgs(Player player, PlayerMovementState oldState, PlayerMovementState newState)
{
Player = player;
OldState = oldState;
-#pragma warning disable CS0618
NewState = newState;
-#pragma warning restore CS0618
}
///
@@ -55,21 +48,8 @@ public ChangingMoveStateEventArgs(Player player, PlayerMovementState oldState, P
public PlayerMovementState OldState { get; }
///
- /// Gets or sets the new state.
- ///
- // TODO: remove setter
- public PlayerMovementState NewState
- {
- get;
- [Obsolete("Setter was removed due to desync problems.")]
- set;
- }
-
- ///
- /// Gets or sets a value indicating whether the player can change the movement state.
+ /// Gets the new state.
///
- // TODO: remove
- [Obsolete("Property was removed due to desync problems.")]
- public bool IsAllowed { get; set; } = true;
+ public PlayerMovementState NewState { get; }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ChangingRadioPresetEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ChangingRadioPresetEventArgs.cs
index b48a8b764..c00696a75 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ChangingRadioPresetEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ChangingRadioPresetEventArgs.cs
@@ -21,7 +21,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information before radio preset is changed.
///
- public class ChangingRadioPresetEventArgs : IPlayerEvent, IItemEvent, IDeniableEvent
+ public class ChangingRadioPresetEventArgs : IItemEvent, IDeniableEvent
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/DroppingItemEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/DroppingItemEventArgs.cs
index 4ff31bde6..cf15df90d 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/DroppingItemEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/DroppingItemEventArgs.cs
@@ -19,7 +19,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information before a player drops an item.
///
- public class DroppingItemEventArgs : IPlayerEvent, IItemEvent, IDeniableEvent
+ public class DroppingItemEventArgs : IItemEvent, IDeniableEvent
{
private bool isAllowed = true;
diff --git a/EXILED/Exiled.Events/EventArgs/Player/DryfiringWeaponEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/DryfiringWeaponEventArgs.cs
index 26a4fb91d..2073d6267 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/DryfiringWeaponEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/DryfiringWeaponEventArgs.cs
@@ -12,6 +12,8 @@ namespace Exiled.Events.EventArgs.Player
using Interfaces;
+ using BaseFirearm = InventorySystem.Items.Firearms.Firearm;
+
///
/// Contains all information before a player's weapon is dryfired.
///
@@ -20,26 +22,19 @@ public class DryfiringWeaponEventArgs : IPlayerEvent, IFirearmEvent, IDeniableEv
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
///
///
///
- ///
- ///
- ///
- public DryfiringWeaponEventArgs(Player player, Firearm firearm, bool isAllowed = true)
+ public DryfiringWeaponEventArgs(BaseFirearm firearm)
{
- Firearm = firearm;
- Player = player;
- IsAllowed = isAllowed;
+ Firearm = Item.Get(firearm);
+ Player = Firearm.Owner;
}
///
/// Gets or sets a value indicating whether the weapon can be dryfired.
///
- public bool IsAllowed { get; set; }
+ public bool IsAllowed { get; set; } = true;
///
/// Gets the being dryfired.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/DyingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/DyingEventArgs.cs
index 2ac0a0695..9919ac089 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/DyingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/DyingEventArgs.cs
@@ -7,7 +7,6 @@
namespace Exiled.Events.EventArgs.Player
{
- using System;
using System.Collections.Generic;
using System.Linq;
@@ -45,14 +44,9 @@ public DyingEventArgs(Player target, DamageHandlerBase damageHandler)
}
///
- /// Gets or sets the list of items to be dropped.
+ /// Gets the list of items to be dropped.
///
- public List ItemsToDrop
- {
- get;
- [Obsolete("This setter has been deprecated")]
- set;
- }
+ public List ItemsToDrop { get; }
///
/// Gets the dying player.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/EscapedEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/EscapedEventArgs.cs
index 9f74663cd..71df7a008 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/EscapedEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/EscapedEventArgs.cs
@@ -8,14 +8,11 @@
namespace Exiled.Events.EventArgs.Player
{
using System;
- using System.Collections.Generic;
using Exiled.API.Enums;
using Exiled.API.Features;
using Exiled.API.Features.Roles;
using Exiled.Events.EventArgs.Interfaces;
- using PlayerRoles;
- using Respawning;
///
/// Contains all information after player has escaped.
@@ -28,13 +25,10 @@ public class EscapedEventArgs : IPlayerEvent
///
///
///
- /// , .
- public EscapedEventArgs(Player player, EscapeScenario escapeScenario, Role role, KeyValuePair kvp)
+ public EscapedEventArgs(Player player, EscapeScenario escapeScenario, Role role)
{
Player = player;
EscapeScenario = escapeScenario;
- Team = kvp.Key;
- Tickets = kvp.Value;
OldRole = role;
EscapeTime = (int)Math.Ceiling(role.ActiveTime.TotalSeconds);
}
@@ -47,16 +41,6 @@ public EscapedEventArgs(Player player, EscapeScenario escapeScenario, Role role,
///
public EscapeScenario EscapeScenario { get; }
- ///
- /// Gets the that gained tickets for this escape.
- ///
- public SpawnableTeamType Team { get; }
-
- ///
- /// Gets the amount of tickets gained for this escape.
- ///
- public float Tickets { get; }
-
///
/// Gets the previous role for this player.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/EscapingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/EscapingEventArgs.cs
index b8076e288..a10eea692 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/EscapingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/EscapingEventArgs.cs
@@ -42,52 +42,6 @@ public EscapingEventArgs(Player player, RoleTypeId newRole, EscapeScenario escap
IsAllowed = escapeScenario is not EscapeScenario.CustomEscape;
}
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public EscapingEventArgs(Player player, RoleTypeId newRole, EscapeScenario escapeScenario, KeyValuePair respawnTickets)
- : this(player, newRole, escapeScenario)
- {
- RespawnTickets = respawnTickets;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- /// A that will be initialized with.
- ///
- ///
- /// A that will be initialized with.
- ///
- public EscapingEventArgs(Player player, RoleTypeId newRole, EscapeScenario escapeScenario, SpawnableTeamType teamToGrantTickets, float ticketsToGrant)
- : this(player, newRole, escapeScenario)
- {
- if (teamToGrantTickets != SpawnableTeamType.None)
- RespawnTickets = new KeyValuePair(teamToGrantTickets, ticketsToGrant);
- }
-
///
/// Gets the player who's escaping.
///
@@ -103,12 +57,6 @@ public EscapingEventArgs(Player player, RoleTypeId newRole, EscapeScenario escap
///
public EscapeScenario EscapeScenario { get; set; }
- ///
- /// Gets or sets the RespawnTickets that will represent the amount of tickets granted to a specific after the player escapes.
- ///
- ///
- public KeyValuePair RespawnTickets { get; set; }
-
///
/// Gets or sets a value indicating whether the player can escape.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/InteractingElevatorEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/InteractingElevatorEventArgs.cs
index b8bda532d..5a3edb3ad 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/InteractingElevatorEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/InteractingElevatorEventArgs.cs
@@ -28,14 +28,18 @@ public class InteractingElevatorEventArgs : IPlayerEvent, IDeniableEvent
///
///
///
+ ///
+ ///
+ ///
///
///
///
- public InteractingElevatorEventArgs(Player player, ElevatorChamber elevator, bool isAllowed = true)
+ public InteractingElevatorEventArgs(Player player, ElevatorChamber elevator, bool isCalledFromInside, bool isAllowed = true)
{
Player = player;
Lift = Lift.Get(elevator);
Elevator = elevator;
+ IsCalledFromInside = isCalledFromInside;
IsAllowed = isAllowed;
}
@@ -54,6 +58,11 @@ public InteractingElevatorEventArgs(Player player, ElevatorChamber elevator, boo
///
public bool IsAllowed { get; set; }
+ ///
+ /// Gets a value indicating whether the player as interact with the elevator from the inside.
+ ///
+ public bool IsCalledFromInside { get; }
+
///
/// Gets the player who's interacting with the elevator.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/InteractingLockerEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/InteractingLockerEventArgs.cs
index 2be075af6..b7cc7f3b5 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/InteractingLockerEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/InteractingLockerEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Player
{
- using System;
-
using API.Features;
using Exiled.API.Features.Lockers;
using Interfaces;
@@ -36,23 +34,11 @@ public class InteractingLockerEventArgs : IPlayerEvent, IDeniableEvent
public InteractingLockerEventArgs(Player player, MapGeneration.Distributors.Locker locker, byte colliderId, bool isAllowed)
{
Player = player;
- InteractingLocker = API.Features.Lockers.Locker.Get(locker);
- InteractingChamber = API.Features.Lockers.Chamber.Get(locker.Chambers[colliderId]);
+ InteractingLocker = Locker.Get(locker);
+ InteractingChamber = Chamber.Get(locker.Chambers[colliderId]);
IsAllowed = isAllowed;
}
- ///
- /// Gets the instance.
- ///
- [Obsolete("Use InteractingLocker instead.")]
- public MapGeneration.Distributors.Locker Locker => InteractingLocker.Base;
-
- ///
- /// Gets the interacting chamber.
- ///
- [Obsolete("Use InteractingChamber instead.")]
- public MapGeneration.Distributors.LockerChamber Chamber => InteractingChamber.Base;
-
///
/// Gets the locker which is containing .
///
@@ -63,12 +49,6 @@ public InteractingLockerEventArgs(Player player, MapGeneration.Distributors.Lock
///
public Chamber InteractingChamber { get; }
- ///
- /// Gets the chamber id.
- ///
- [Obsolete("Use Chamber::Id instead.")]
- public byte ChamberId => InteractingChamber.Id;
-
///
/// Gets or sets a value indicating whether the player can interact with the locker.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ItemAddedEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ItemAddedEventArgs.cs
index 68c5aca0d..694188c1c 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ItemAddedEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ItemAddedEventArgs.cs
@@ -17,7 +17,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information after adding an item to a player's inventory.
///
- public class ItemAddedEventArgs : IPlayerEvent, IItemEvent, IPickupEvent
+ public class ItemAddedEventArgs : IItemEvent, IPickupEvent
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ItemRemovedEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ItemRemovedEventArgs.cs
index ef0dc9a53..f14eb31d2 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ItemRemovedEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ItemRemovedEventArgs.cs
@@ -17,7 +17,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information after removing an item from a player's inventory.
///
- public class ItemRemovedEventArgs : IPlayerEvent, IItemEvent, IPickupEvent
+ public class ItemRemovedEventArgs : IItemEvent, IPickupEvent
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs
index 736a52e6c..036b2aa4c 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/KickingEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Player
{
- using System;
- using System.Linq;
using System.Reflection;
using API.Features;
@@ -76,14 +74,9 @@ public Player Target
public string Reason { get; set; }
///
- /// Gets or sets the full kick message.
+ /// Gets the full kick message.
///
- public string FullMessage
- {
- get => startkickmessage + Reason;
- [Obsolete("this will be remove use Reason instead of FullMessage")]
- set => Reason = value.StartsWith(startkickmessage) ? value.Remove(0, startkickmessage.Count()) : value;
- }
+ public string FullMessage => startkickmessage + Reason;
///
/// Gets or sets a value indicating whether action is taken against the target.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/KillingPlayerEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/KillingPlayerEventArgs.cs
deleted file mode 100644
index d575cb310..000000000
--- a/EXILED/Exiled.Events/EventArgs/Player/KillingPlayerEventArgs.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright (c) ExMod Team. All rights reserved.
-// Licensed under the CC BY-SA 3.0 license.
-//
-// -----------------------------------------------------------------------
-
-namespace Exiled.Events.EventArgs.Player
-{
- using System;
-
- using Interfaces;
- using PlayerStatsSystem;
-
- ///
- /// Contains all information before player data to kill player is sent.
- ///
- [Obsolete]
- public class KillingPlayerEventArgs : IPlayerEvent
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// Current player.
- /// DamageHandler instance.
- public KillingPlayerEventArgs(API.Features.Player player, ref DamageHandlerBase handler)
- {
- Player = player;
- Handler = handler;
- }
-
- ///
- /// Gets or sets current player.
- ///
- public API.Features.Player Player { get; set; }
-
- ///
- /// Gets or sets current Damage Handler.
- ///
- public DamageHandlerBase Handler { get; set; }
- }
-}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/RotatingRevolverEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/RotatingRevolverEventArgs.cs
new file mode 100644
index 000000000..515d8c7b0
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Player/RotatingRevolverEventArgs.cs
@@ -0,0 +1,64 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Player
+{
+ using API.Features;
+ using API.Features.Items;
+
+ using Exiled.API.Features.Items.FirearmModules.Primary;
+
+ using Interfaces;
+
+ using InventorySystem.Items.Firearms.Modules;
+
+ using FirearmBase = InventorySystem.Items.Firearms.Firearm;
+
+ ///
+ /// Contains all information when a player rotates revolver.
+ ///
+ public class RotatingRevolverEventArgs : IPlayerEvent, IFirearmEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public RotatingRevolverEventArgs(FirearmBase firearm, int rotations)
+ {
+ Firearm = Item.Get(firearm);
+ Player = Firearm.Owner;
+ Rotations = rotations;
+ }
+
+ ///
+ /// Gets or sets a rotations count(per chamber).
+ ///
+ public int Rotations { get; set; }
+
+ ///
+ /// Gets a value indicating whether the rotation will have an effect.
+ ///
+ ///
+ /// checks rotations and chambers counts equality by mod of chambers counts. Rotations % Chambers.Length == 0
+ ///
+ public bool HasEffect => Firearm.PrimaryMagazine.MaxAmmo % Rotations == 0;
+
+ ///
+ public Firearm Firearm { get; }
+
+ ///
+ public Item Item => Firearm;
+
+ ///
+ public Player Player { get; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ShootingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ShootingEventArgs.cs
index 177b3c5a6..3c2f9d12b 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ShootingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ShootingEventArgs.cs
@@ -8,106 +8,72 @@
namespace Exiled.Events.EventArgs.Player
{
using API.Features;
-
using Exiled.API.Features.Items;
-
using Interfaces;
-
- using InventorySystem.Items.Firearms.BasicMessages;
-
- using RelativePositioning;
-
+ using InventorySystem.Items.Firearms.Modules.Misc;
using UnityEngine;
using BaseFirearm = InventorySystem.Items.Firearms.Firearm;
///
/// Contains all information before a player fires a weapon.
+ /// ClaimedTarget and Player transform values are modified by according to sent by the Player and do not match the actual values.
///
public class ShootingEventArgs : IPlayerEvent, IDeniableEvent, IFirearmEvent
{
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
///
- ///
+ /// The that is being fired.
///
- ///
- ///
+ ///
+ /// sent by the client.
///
- public ShootingEventArgs(Player shooter, BaseFirearm firearm, ShotMessage msg)
+ public ShootingEventArgs(BaseFirearm firearm, ref ShotBacktrackData shotBacktrackData)
{
- Player = shooter;
- Firearm = Item.Get(firearm).As();
- ShotMessage = msg;
+ Firearm = (Firearm)Item.Get(firearm);
+ Player = Firearm.Owner;
+ ShotBacktrackData = shotBacktrackData;
}
///
- /// Gets the player who's shooting.
+ /// Gets the player who is shooting.
///
public Player Player { get; }
///
- /// Gets the target .
+ /// Gets the target that client claims it hit.
///
- public Firearm Firearm { get; }
-
- ///
- public Item Item => Firearm;
+ /// This value is controlled by the shooting player and should not be trusted. Can be null.
+ public Player ClaimedTarget => ShotBacktrackData.HasPrimaryTarget ? Player.Get(ShotBacktrackData.PrimaryTargetHub) : null;
///
- /// Gets or sets the for the event.
+ /// Gets the . This object contains the data sent by the client to the server.
///
- public ShotMessage ShotMessage { get; set; }
+ /// Values are controlled by the shooting player and should not be trusted.
+ public ShotBacktrackData ShotBacktrackData { get; }
///
- /// Gets or sets the position of the shot.
+ /// Gets or sets the exact direction of the shot before the bullet spread is applied.
///
- public Vector3 ShotPosition
+ public Vector3 Direction
{
- get => ShotMessage.TargetPosition.Position;
- set
- {
- ShotMessage msg = ShotMessage;
- ShotMessage = new ShotMessage
- {
- ShooterPosition = msg.ShooterPosition,
- ShooterCameraRotation = msg.ShooterCameraRotation,
- ShooterWeaponSerial = msg.ShooterWeaponSerial,
- TargetPosition = new RelativePosition(value),
- TargetRotation = msg.TargetRotation,
- TargetNetId = msg.TargetNetId,
- };
- }
+ get => Player.CameraTransform.forward;
+ set => Player.CameraTransform.forward = value; // It is going to be reset by FpcBacktracker the same frame, so why we can set it freely.
}
///
- /// Gets or sets the netId of the target of the shot.
+ /// Gets the firearm that is being fired.
///
- public uint TargetNetId
- {
- get => ShotMessage.TargetNetId;
- set
- {
- ShotMessage msg = ShotMessage;
- ShotMessage = new ShotMessage
- {
- ShooterPosition = msg.ShooterPosition,
- ShooterCameraRotation = msg.ShooterCameraRotation,
- ShooterWeaponSerial = msg.ShooterWeaponSerial,
- TargetPosition = msg.TargetPosition,
- TargetRotation = msg.TargetRotation,
- TargetNetId = value,
- };
- }
- }
+ public Firearm Firearm { get; }
+
+ ///
+ public Item Item => Firearm;
///
/// Gets or sets a value indicating whether the shot can be fired.
///
public bool IsAllowed { get; set; } = true;
}
-}
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ShotEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ShotEventArgs.cs
index 18ff833b4..0eb6a5c69 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ShotEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ShotEventArgs.cs
@@ -10,7 +10,7 @@ namespace Exiled.Events.EventArgs.Player
using API.Features;
using Exiled.API.Features.Items;
using Interfaces;
-
+ using InventorySystem.Items.Firearms.Modules;
using UnityEngine;
///
@@ -19,44 +19,36 @@ namespace Exiled.Events.EventArgs.Player
public class ShotEventArgs : IPlayerEvent, IFirearmEvent
{
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
- ///
- ///
- ///
- ///
- ///
- ///
- /// The hit.
- ///
- ///
- ///
- ///
- ///
- ///
- public ShotEventArgs(Player shooter, Firearm firearm, RaycastHit hit, IDestructible destructible, float damage)
+ /// Hitreg module that calculated the shot.
+ /// Raycast hit info.
+ /// The firearm used.
+ /// The IDestructible that was hit. Can be null.
+ public ShotEventArgs(HitscanHitregModuleBase hitregModule, RaycastHit hitInfo, InventorySystem.Items.Firearms.Firearm firearm, IDestructible destructible)
{
- Player = shooter;
- Firearm = firearm;
- Damage = damage;
- Distance = hit.distance;
- Position = hit.point;
- RaycastHit = hit;
-
- if (destructible is HitboxIdentity identity)
+ HitregModule = hitregModule;
+ RaycastHit = hitInfo;
+ Destructible = destructible;
+ Firearm = Item.Get(firearm);
+
+ Player = Firearm.Owner;
+ Damage = Destructible is not null ? HitregModule.DamageAtDistance(hitInfo.distance) : 0f;
+
+ if (Destructible is HitboxIdentity hitboxIdentity)
{
- Hitbox = identity;
+ Hitbox = hitboxIdentity;
Target = Player.Get(Hitbox.TargetHub);
}
}
///
- /// Gets the player who shot.
+ /// Gets the player who fired the shot.
///
public Player Player { get; }
///
- /// Gets the firearm used to shoot.
+ /// Gets the firearm used to fire the shot.
///
public Firearm Firearm { get; }
@@ -64,38 +56,53 @@ public ShotEventArgs(Player shooter, Firearm firearm, RaycastHit hit, IDestructi
public Item Item => Firearm;
///
- /// Gets the hitbox type of the shot. Can be !.
+ /// Gets the firearm hitreg module responsible for the shot.
///
- public HitboxIdentity Hitbox { get; }
+ public HitscanHitregModuleBase HitregModule { get; }
///
- /// Gets or sets the inflicted damage.
+ /// Gets the raycast info.
///
- public float Damage { get; set; }
+ public RaycastHit RaycastHit { get; }
///
- /// Gets the shot distance.
+ /// Gets the bullet travel distance.
///
- public float Distance { get; }
+ public float Distance => RaycastHit.distance;
///
- /// Gets the shot position.
+ /// Gets the position of the hit.
///
- public Vector3 Position { get; }
+ public Vector3 Position => RaycastHit.point;
///
- /// Gets the raycast result.
+ /// Gets the firearm base damage at the hit distance. Actual inflicted damage may vary.
///
- public RaycastHit RaycastHit { get; }
+ public float Damage { get; }
///
- /// Gets the target of the shot. Can be !.
+ /// Gets the target player. Can be null.
///
public Player Target { get; }
///
- /// Gets or sets a value indicating whether the shot can hurt the target.
+ /// Gets the component of the target player that was hit. Can be null.
+ ///
+ public HitboxIdentity Hitbox { get; }
+
+ ///
+ /// Gets the component of the hit collider. Can be null.
+ ///
+ public IDestructible Destructible { get; }
+
+ ///
+ /// Gets or sets a value indicating whether the shot can deal damage.
///
public bool CanHurt { get; set; } = true;
+
+ ///
+ /// Gets or sets a value indicating whether the shot can produce impact effects (e.g. bullet holes).
+ ///
+ public bool CanSpawnImpactEffects { get; set; } = true;
}
}
diff --git a/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs
index 1e4c28346..785ff5a3c 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/SpawningEventArgs.cs
@@ -7,11 +7,12 @@
namespace Exiled.Events.EventArgs.Player
{
+ using System;
+
using Exiled.API.Features;
using Exiled.API.Features.Roles;
using Exiled.Events.EventArgs.Interfaces;
using PlayerRoles;
-
using UnityEngine;
///
@@ -31,15 +32,15 @@ public class SpawningEventArgs : IPlayerEvent
///
///
///
- ///
- /// the spawned player's old role.
+ ///
+ /// the spawned player's new role.
///
- public SpawningEventArgs(Player player, Vector3 position, float rotation, PlayerRoleBase oldRole)
+ public SpawningEventArgs(Player player, Vector3 position, float rotation, PlayerRoleBase newRole)
{
Player = player;
Position = position;
HorizontalRotation = rotation;
- OldRole = Role.Create(oldRole);
+ NewRole = Role.Create(newRole);
}
///
@@ -66,6 +67,12 @@ public SpawningEventArgs(Player player, Vector3 position, float rotation, Player
///
/// Gets the player's old role.
///
- public Role OldRole { get; }
+ [Obsolete("Removed because the method is no longer provide OldRole since version 14.0. Use Player.Role instead")]
+ public Role OldRole => Player.Role;
+
+ ///
+ /// Gets the player's new role.
+ ///
+ public Role NewRole { get; }
}
-}
\ No newline at end of file
+}
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ThrowingRequestEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ThrowingRequestEventArgs.cs
index 586cc15f5..ee1b36558 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ThrowingRequestEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ThrowingRequestEventArgs.cs
@@ -17,7 +17,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information before receving a throwing request.
///
- public class ThrowingRequestEventArgs : IPlayerEvent, IItemEvent
+ public class ThrowingRequestEventArgs : IItemEvent
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/ThrownProjectileEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/ThrownProjectileEventArgs.cs
index 7da1528af..14ab42de1 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/ThrownProjectileEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/ThrownProjectileEventArgs.cs
@@ -18,7 +18,7 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information after a player throws a grenade.
///
- public class ThrownProjectileEventArgs : IPlayerEvent, IItemEvent, IPickupEvent
+ public class ThrownProjectileEventArgs : IItemEvent, IPickupEvent
{
///
/// Initializes a new instance of the class.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/TogglingWeaponFlashlightEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/TogglingWeaponFlashlightEventArgs.cs
index ccc8a6fd3..3c6f2f788 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/TogglingWeaponFlashlightEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/TogglingWeaponFlashlightEventArgs.cs
@@ -12,6 +12,8 @@ namespace Exiled.Events.EventArgs.Player
using Interfaces;
+ using BaseFirearm = InventorySystem.Items.Firearms.Firearm;
+
///
/// Contains all information before a player toggles the weapon's flashlight.
///
@@ -20,24 +22,17 @@ public class TogglingWeaponFlashlightEventArgs : IPlayerEvent, IFirearmEvent, ID
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
///
///
///
- ///
+ ///
///
///
- ///
- ///
- ///
- public TogglingWeaponFlashlightEventArgs(Player player, Firearm firearm, bool newState, bool isAllowed = true)
+ public TogglingWeaponFlashlightEventArgs(BaseFirearm firearm, bool oldState)
{
- Firearm = firearm;
- Player = player;
- NewState = newState;
- IsAllowed = isAllowed;
+ Firearm = Item.Get(firearm);
+ Player = Firearm.Owner;
+ NewState = !oldState;
}
///
@@ -48,7 +43,7 @@ public TogglingWeaponFlashlightEventArgs(Player player, Firearm firearm, bool ne
///
/// Gets or sets a value indicating whether the weapon's flashlight can be toggled.
///
- public bool IsAllowed { get; set; }
+ public bool IsAllowed { get; set; } = true;
///
/// Gets the being held.
diff --git a/EXILED/Exiled.Events/EventArgs/Player/TransmittingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/TransmittingEventArgs.cs
index f8e4419d0..96e1ffde4 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/TransmittingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/TransmittingEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Player
{
- using System;
-
using Exiled.API.Features;
using Exiled.Events.EventArgs.Interfaces;
@@ -48,12 +46,6 @@ public TransmittingEventArgs(Player player, VoiceModuleBase voiceModule, bool is
///
public VoiceModuleBase VoiceModule { get; }
- ///
- /// Gets a value indicating whether the player is transmitting.
- ///
- [Obsolete("IsTransmitting is always true.")]
- public bool IsTransmitting => true;
-
///
/// Gets or sets a value indicating whether the player can transmit.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Player/UsingMicroHIDEnergyEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Player/UsingMicroHIDEnergyEventArgs.cs
index d4203283f..cbf292d86 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/UsingMicroHIDEnergyEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Player/UsingMicroHIDEnergyEventArgs.cs
@@ -17,32 +17,24 @@ namespace Exiled.Events.EventArgs.Player
///
/// Contains all information before MicroHID energy is changed.
///
- public class UsingMicroHIDEnergyEventArgs : IPlayerEvent, IDeniableEvent, IItemEvent
+ public class UsingMicroHIDEnergyEventArgs : IDeniableEvent, IItemEvent
{
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
///
///
///
- ///
- ///
- ///
- ///
+ ///
///
///
///
///
///
- public UsingMicroHIDEnergyEventArgs(Player player, MicroHIDItem microHIDitem, HidState currentState, float drain, bool isAllowed = true)
+ public UsingMicroHIDEnergyEventArgs(MicroHIDItem microHIDitem, float newEnergy, bool isAllowed = true)
{
- Player = player;
MicroHID = Item.Get(microHIDitem);
- CurrentState = currentState;
- Drain = drain;
+ Drain = MicroHID.Energy - newEnergy;
IsAllowed = isAllowed;
}
@@ -54,11 +46,6 @@ public UsingMicroHIDEnergyEventArgs(Player player, MicroHIDItem microHIDitem, Hi
///
public Item Item => MicroHID;
- ///
- /// Gets the current state of the MicroHID.
- ///
- public HidState CurrentState { get; }
-
///
/// Gets or sets the MicroHID energy drain.
///
@@ -69,9 +56,7 @@ public UsingMicroHIDEnergyEventArgs(Player player, MicroHIDItem microHIDitem, Hi
///
public bool IsAllowed { get; set; }
- ///
- /// Gets the player who's using the MicroHID.
- ///
- public Player Player { get; }
+ ///
+ public Player Player => MicroHID.Owner;
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Scp049/ActivatingSenseEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp049/ActivatingSenseEventArgs.cs
index e350a746d..c8ae4fdae 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp049/ActivatingSenseEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp049/ActivatingSenseEventArgs.cs
@@ -7,10 +7,7 @@
namespace Exiled.Events.EventArgs.Scp049
{
- using System;
-
using API.Features;
- using Exiled.API.Features.Roles;
using Exiled.Events.EventArgs.Interfaces;
using Scp049Role = API.Features.Roles.Scp049Role;
@@ -54,12 +51,6 @@ public ActivatingSenseEventArgs(Player player, Player target, bool isAllowed = t
///
public float FailedCooldown { get; set; }
- ///
- /// Gets or sets the cooldown of the ability.
- ///
- [Obsolete("Use FailedCooldown instead of this")]
- public float Cooldown { get => FailedCooldown; set => FailedCooldown = value; }
-
///
/// Gets or sets the duration of the Effect.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Scp0492/ConsumedCorpseEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp0492/ConsumedCorpseEventArgs.cs
index e27675ed3..56aff95ac 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp0492/ConsumedCorpseEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp0492/ConsumedCorpseEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Scp0492
{
- using System;
-
using API.Features;
using Exiled.API.Features.Roles;
using Interfaces;
diff --git a/EXILED/Exiled.Events/EventArgs/Scp079/ElevatorTeleportingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp079/ElevatorTeleportingEventArgs.cs
index da8aae174..85907c0db 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp079/ElevatorTeleportingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp079/ElevatorTeleportingEventArgs.cs
@@ -29,18 +29,18 @@ public class ElevatorTeleportingEventArgs : IScp079Event, IRoomEvent, IDeniableE
///
///
///
- ///
+ ///
///
///
///
///
///
- public ElevatorTeleportingEventArgs(Player player, RoomIdentifier room, ElevatorDoor elevatorDoor, float auxiliaryPowerCost)
+ public ElevatorTeleportingEventArgs(Player player, RoomIdentifier room, ElevatorChamber elevatorChamber, float auxiliaryPowerCost)
{
Player = player;
Scp079 = player.Role.As();
Room = Room.Get(room);
- Lift = Lift.Get(elevatorDoor.TargetPanel.AssignedChamber);
+ Lift = Lift.Get(elevatorChamber);
AuxiliaryPowerCost = auxiliaryPowerCost;
IsAllowed = auxiliaryPowerCost <= Scp079.Energy;
}
diff --git a/EXILED/Exiled.Events/EventArgs/Scp106/ExitStalkingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp106/ExitStalkingEventArgs.cs
index 0f86698bf..b501c112c 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp106/ExitStalkingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp106/ExitStalkingEventArgs.cs
@@ -7,11 +7,8 @@
namespace Exiled.Events.EventArgs.Scp106
{
- using System;
-
using API.Features;
using Interfaces;
- using PlayerRoles.PlayableScps.Scp106;
using Scp106Role = API.Features.Roles.Scp106Role;
diff --git a/EXILED/Exiled.Events/EventArgs/Scp106/StalkingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp106/StalkingEventArgs.cs
index 1ed03bc42..b94a3db6f 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp106/StalkingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp106/StalkingEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Scp106
{
- using System;
-
using API.Features;
using Interfaces;
using PlayerRoles.PlayableScps.Scp106;
@@ -24,32 +22,14 @@ public class StalkingEventArgs : IScp106Event, IDeniableEvent
/// Initializes a new instance of the class.
///
///
- ///
- public StalkingEventArgs(Player player, bool isAllowed = true)
+ public StalkingEventArgs(Player player)
{
Player = player;
Scp106 = player.Role.As();
- IsAllowed = isAllowed;
+ IsAllowed = true;
MinimumVigor = Scp106StalkAbility.MinVigorToSubmerge;
}
- ///
- /// Gets the .
- ///
- [Obsolete("Use Scp106.StalkAbility instead of this")]
- public Scp106StalkAbility Scp106StalkAbility => Scp106.StalkAbility;
-
- ///
- /// Gets or sets the current vigor when SCP-106 starts to stalk.
- ///
- public float Vigor
- {
- [Obsolete("Use Scp106.Vigor instead of this")]
- get => Scp106.Vigor;
- [Obsolete("Use Scp106.Vigor instead of this")]
- set => Scp106.Vigor = value;
- }
-
///
/// Gets or sets the required minimum vigor to stalk.
///
@@ -66,6 +46,7 @@ public float Vigor
///
/// Gets or sets a value indicating whether SCP-106 can stalk.
///
+ /// IsAllowed doesn't indicate whether vigor is sufficient for Stalking. needs to be changed to override the base game check.
public bool IsAllowed { get; set; }
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs
new file mode 100644
index 000000000..11afddf79
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangedStatusEventArgs.cs
@@ -0,0 +1,55 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Scp1344
+{
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+ using InventorySystem.Items.Usables.Scp1344;
+
+ ///
+ /// Contains all information after SCP-1344 status changing.
+ ///
+ public class ChangedStatusEventArgs : IScp1344Event, IPlayerEvent, IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public ChangedStatusEventArgs(Item item, Scp1344Status scp1344Status)
+ {
+ Item = item;
+ Scp1344 = item as Scp1344;
+ Player = item.Owner;
+ Scp1344Status = scp1344Status;
+ }
+
+ ///
+ /// Gets the new state.
+ ///
+ public Scp1344Status Scp1344Status { get; }
+
+ ///
+ /// Gets the item.
+ ///
+ public Item Item { get; }
+
+ ///
+ /// Gets the player in owner of the item.
+ ///
+ public Exiled.API.Features.Player Player { get; }
+
+ ///
+ /// Gets Scp1344 item.
+ ///
+ public Scp1344 Scp1344 { get; }
+
+ ///
+ public bool IsAllowed { get; set; }
+ }
+}
diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/ChangingStatusEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangingStatusEventArgs.cs
new file mode 100644
index 000000000..89329e073
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Scp1344/ChangingStatusEventArgs.cs
@@ -0,0 +1,64 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Scp1344
+{
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+ using InventorySystem.Items.Usables.Scp1344;
+
+ ///
+ /// Contains all information before SCP-1344 status changing.
+ ///
+ public class ChangingStatusEventArgs : IPlayerEvent, IScp1344Event, IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ChangingStatusEventArgs(Item item, Scp1344Status scp1344StatusNew, Scp1344Status scp1344StatusOld, bool isAllowed = true)
+ {
+ Item = item;
+ Scp1344 = item as Scp1344;
+ Player = item.Owner;
+ Scp1344StatusNew = scp1344StatusNew;
+ Scp1344StatusOld = scp1344StatusOld;
+ IsAllowed = isAllowed;
+ }
+
+ ///
+ /// Gets the current status.
+ ///
+ public Scp1344Status Scp1344StatusOld { get; }
+
+ ///
+ /// Gets or sets the new state.
+ ///
+ public Scp1344Status Scp1344StatusNew { get; set; }
+
+ ///
+ /// Gets the item.
+ ///
+ public Item Item { get; }
+
+ ///
+ /// Gets the player in owner of the item.
+ ///
+ public Exiled.API.Features.Player Player { get; }
+
+ ///
+ /// Gets Scp1344 item.
+ ///
+ public Scp1344 Scp1344 { get; }
+
+ ///
+ public bool IsAllowed { get; set; }
+ }
+}
diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatedEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatedEventArgs.cs
new file mode 100644
index 000000000..79ec6925e
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatedEventArgs.cs
@@ -0,0 +1,44 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Scp1344
+{
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+
+ ///
+ /// Contains all information after deactivating.
+ ///
+ public class DeactivatedEventArgs : IPlayerEvent, IScp1344Event
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ public DeactivatedEventArgs(Item item)
+ {
+ Item = item;
+ Scp1344 = item as Scp1344;
+ Player = item.Owner;
+ }
+
+ ///
+ /// Gets the item.
+ ///
+ public Item Item { get; }
+
+ ///
+ /// Gets the player in owner of the item.
+ ///
+ public Exiled.API.Features.Player Player { get; }
+
+ ///
+ /// Gets Scp1344 item.
+ ///
+ public Scp1344 Scp1344 { get; }
+ }
+}
diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs
new file mode 100644
index 000000000..96bcbc211
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Scp1344/DeactivatingEventArgs.cs
@@ -0,0 +1,49 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Scp1344
+{
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+
+ ///
+ /// Contains all information before deactivating.
+ ///
+ public class DeactivatingEventArgs : IPlayerEvent, IScp1344Event, IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public DeactivatingEventArgs(Item item, bool isAllowed = true)
+ {
+ Item = item;
+ Scp1344 = item as Scp1344;
+ Player = item.Owner;
+ IsAllowed = isAllowed;
+ }
+
+ ///
+ /// Gets the item.
+ ///
+ public Item Item { get; }
+
+ ///
+ /// Gets the player in owner of the item.
+ ///
+ public Exiled.API.Features.Player Player { get; }
+
+ ///
+ /// Gets Scp1344 item.
+ ///
+ public Scp1344 Scp1344 { get; }
+
+ ///
+ public bool IsAllowed { get; set; }
+ }
+}
diff --git a/EXILED/Exiled.Events/EventArgs/Scp1344/TryingDeactivatingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp1344/TryingDeactivatingEventArgs.cs
new file mode 100644
index 000000000..f236851f1
--- /dev/null
+++ b/EXILED/Exiled.Events/EventArgs/Scp1344/TryingDeactivatingEventArgs.cs
@@ -0,0 +1,49 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.EventArgs.Scp1344
+{
+ using Exiled.API.Features.Items;
+ using Exiled.Events.EventArgs.Interfaces;
+
+ ///
+ /// Contains all information before trying deactivating.
+ ///
+ public class TryingDeactivatingEventArgs : IPlayerEvent, IScp1344Event, IDeniableEvent
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ ///
+ ///
+ public TryingDeactivatingEventArgs(Item item, bool isAllowed = true)
+ {
+ Item = item;
+ Scp1344 = item as Scp1344;
+ Player = item.Owner;
+ IsAllowed = isAllowed;
+ }
+
+ ///
+ /// Gets the item.
+ ///
+ public Item Item { get; }
+
+ ///
+ /// Gets the player in owner of the item.
+ ///
+ public Exiled.API.Features.Player Player { get; }
+
+ ///
+ /// Gets Scp1344 item.
+ ///
+ public Scp1344 Scp1344 { get; }
+
+ ///
+ public bool IsAllowed { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Scp173/BlinkingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp173/BlinkingEventArgs.cs
index ef697602d..95f3e2a08 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp173/BlinkingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp173/BlinkingEventArgs.cs
@@ -58,8 +58,7 @@ public BlinkingEventArgs(Player player, List targets, Vector3 blinkPos)
///
/// Gets a of players who have triggered SCP-173.
///
- // TODO: convert to ReadOnlyCollection
- public List Targets { get; }
+ public IReadOnlyCollection Targets { get; }
///
/// Gets or sets a value indicating whether the player is allowed to blink.
diff --git a/EXILED/Exiled.Events/EventArgs/Scp330/DroppingScp330EventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp330/DroppingScp330EventArgs.cs
index 1542d6aa0..0ead45776 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp330/DroppingScp330EventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp330/DroppingScp330EventArgs.cs
@@ -39,9 +39,9 @@ public DroppingScp330EventArgs(Player player, Scp330Bag scp330, CandyKindID cand
}
///
- /// Gets or sets a value representing the being picked up.
+ /// Gets a value representing the being picked up.
///
- public Scp330 Scp330 { get; set; } // Todo Remove set
+ public Scp330 Scp330 { get; }
///
public Item Item => Scp330;
diff --git a/EXILED/Exiled.Events/EventArgs/Scp330/InteractingScp330EventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp330/InteractingScp330EventArgs.cs
index 526042dd9..dc39d420c 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp330/InteractingScp330EventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp330/InteractingScp330EventArgs.cs
@@ -12,7 +12,6 @@ namespace Exiled.Events.EventArgs.Scp330
using Interfaces;
using InventorySystem.Items.Usables.Scp330;
- using YamlDotNet.Core.Tokens;
///
/// Contains all information before a player interacts with SCP-330.
@@ -35,6 +34,7 @@ public InteractingScp330EventArgs(Player player, int usage)
ShouldSever = usage >= 2;
ShouldPlaySound = true;
IsAllowed = Player.IsHuman;
+ Candy = Scp330Candies.GetRandom();
if (Scp330Bag.TryGetBag(player.ReferenceHub, out Scp330Bag scp330Bag))
{
@@ -46,8 +46,6 @@ public InteractingScp330EventArgs(Player player, int usage)
Scp330.RemoveAllCandy();
player.AddItem(Scp330);
}
-
- Scp330.CandyToAdd = Scp330Candies.GetRandom();
}
///
@@ -55,15 +53,6 @@ public InteractingScp330EventArgs(Player player, int usage)
///
public int UsageCount { get; }
- ///
- /// Gets or sets a value indicating the type of candy that will be received from this interaction.
- ///
- public CandyKindID Candy
- {
- get => Scp330.CandyToAdd;
- set => Scp330.CandyToAdd = value;
- }
-
///
/// Gets or sets a value indicating whether the player's hands should get severed.
///
@@ -75,6 +64,11 @@ public CandyKindID Candy
/// It won't work if = .
public bool ShouldPlaySound { get; set; }
+ ///
+ /// Gets or sets a value indicating the type of candy that will be received from this interaction.
+ ///
+ public CandyKindID Candy { get; set; }
+
///
/// Gets or sets a value indicating whether the player is allowed to interact with SCP-330.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingInventoryItemEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingInventoryItemEventArgs.cs
index 18247e605..667320e57 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingInventoryItemEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingInventoryItemEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Scp914
{
- using System;
-
using API.Features;
using API.Features.Items;
using global::Scp914;
@@ -18,7 +16,7 @@ namespace Exiled.Events.EventArgs.Scp914
///
/// Contains all information before SCP-914 upgrades an item.
///
- public class UpgradingInventoryItemEventArgs : IPlayerEvent, IItemEvent, IDeniableEvent
+ public class UpgradingInventoryItemEventArgs : IItemEvent, IDeniableEvent
{
///
/// Initializes a new instance of the class.
@@ -43,12 +41,6 @@ public UpgradingInventoryItemEventArgs(Player player, ItemBase item, Scp914KnobS
IsAllowed = isAllowed;
}
- ///
- /// Gets the instance.
- ///
- [Obsolete("Use Scp914::Scp914Controller instead.")]
- public Scp914Controller Scp914 => API.Features.Scp914.Scp914Controller;
-
///
/// Gets or sets SCP-914 working knob setting.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPickupEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPickupEventArgs.cs
index cf374690a..691db20a1 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPickupEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPickupEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Scp914
{
- using System;
-
using Exiled.API.Features.Pickups;
using Exiled.Events.EventArgs.Interfaces;
using global::Scp914;
@@ -44,12 +42,6 @@ public UpgradingPickupEventArgs(ItemPickupBase item, Vector3 newPos, Scp914KnobS
///
public Pickup Pickup { get; }
- ///
- /// Gets the instance.
- ///
- [Obsolete("Use Scp914::Scp914Controller instead.")]
- public Scp914Controller Scp914 => API.Features.Scp914.Scp914Controller;
-
///
/// Gets or sets the position the item will be output to.
///
diff --git a/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPlayerEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPlayerEventArgs.cs
index 9dedafb5a..cf4487ecc 100644
--- a/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPlayerEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Scp914/UpgradingPlayerEventArgs.cs
@@ -31,16 +31,16 @@ public class UpgradingPlayerEventArgs : IPlayerEvent, IDeniableEvent
///
///
///
- ///
- ///
+ ///
+ ///
///
- public UpgradingPlayerEventArgs(Player player, bool upgradeItems, bool heldOnly, Scp914KnobSetting setting, Vector3 moveVector)
+ public UpgradingPlayerEventArgs(Player player, bool upgradeItems, bool heldOnly, Scp914KnobSetting setting, Vector3 outputPos)
{
Player = player;
UpgradeItems = upgradeItems;
HeldOnly = heldOnly;
KnobSetting = setting;
- OutputPosition = player.Position + moveVector;
+ OutputPosition = outputPos;
}
///
diff --git a/EXILED/Exiled.Events/EventArgs/Server/EndingRoundEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/EndingRoundEventArgs.cs
index 5c72d299b..216676772 100644
--- a/EXILED/Exiled.Events/EventArgs/Server/EndingRoundEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Server/EndingRoundEventArgs.cs
@@ -7,8 +7,6 @@
namespace Exiled.Events.EventArgs.Server
{
- using System;
-
using API.Enums;
using Interfaces;
@@ -20,24 +18,24 @@ public class EndingRoundEventArgs : IDeniableEvent
///
/// Initializes a new instance of the class.
///
- ///
- ///
- ///
///
///
///
- ///
- ///
+ ///
+ ///
///
///
///
///
- public EndingRoundEventArgs(RoundSummary.LeadingTeam leadingTeam, RoundSummary.SumInfo_ClassList classList, bool isAllowed, bool isForceEnded)
+ ///
+ ///
+ ///
+ public EndingRoundEventArgs(LeadingTeam leadingTeam, RoundSummary.SumInfo_ClassList classList, bool isForceEnded, bool isAllowed)
{
+ LeadingTeam = leadingTeam;
ClassList = classList;
- LeadingTeam = (LeadingTeam)leadingTeam;
- IsRoundEnded = isAllowed;
IsForceEnded = isForceEnded;
+ IsAllowed = isAllowed;
}
///
@@ -51,22 +49,13 @@ public EndingRoundEventArgs(RoundSummary.LeadingTeam leadingTeam, RoundSummary.S
public LeadingTeam LeadingTeam { get; set; }
///
- /// Gets or sets a value indicating whether the round is going to finish.
- ///
- public bool IsRoundEnded { get; set; } // TODO: Obsolete this in Exiled 10
-
- ///
- /// Gets or Sets a value indicating whether the round is ended by API call.
+ /// Gets or sets a value indicating whether the round is ended by API call.
///
public bool IsForceEnded { get; set; }
///
- /// Gets or sets a value indicating whether the event can be executed.
+ /// Gets or sets a value indicating whether the round is going to finish or not.
///
- public bool IsAllowed
- {
- get => IsRoundEnded;
- set => IsRoundEnded = value;
- }
-}
+ public bool IsAllowed { get; set; }
+ }
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/EventArgs/Player/LocalReportingEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/LocalReportingEventArgs.cs
similarity index 95%
rename from EXILED/Exiled.Events/EventArgs/Player/LocalReportingEventArgs.cs
rename to EXILED/Exiled.Events/EventArgs/Server/LocalReportingEventArgs.cs
index d937a5fef..02d1d6b98 100644
--- a/EXILED/Exiled.Events/EventArgs/Player/LocalReportingEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Server/LocalReportingEventArgs.cs
@@ -5,7 +5,7 @@
//
// -----------------------------------------------------------------------
-namespace Exiled.Events.EventArgs.Player // TODO: Wrong namespace should be Server
+namespace Exiled.Events.EventArgs.Server
{
using API.Features;
diff --git a/EXILED/Exiled.Events/EventArgs/Server/RespawnedTeamEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/RespawnedTeamEventArgs.cs
index cbc6886cf..d3d62667a 100644
--- a/EXILED/Exiled.Events/EventArgs/Server/RespawnedTeamEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Server/RespawnedTeamEventArgs.cs
@@ -13,6 +13,7 @@ namespace Exiled.Events.EventArgs.Server
using Exiled.API.Features;
using Exiled.Events.EventArgs.Interfaces;
using Respawning;
+ using Respawning.Waves;
///
/// Contains all information after team spawns.
@@ -23,11 +24,11 @@ public class RespawnedTeamEventArgs : IExiledEvent
/// Initializes a new instance of the class.
///
///
- ///
- public RespawnedTeamEventArgs(SpawnableTeamType team, IEnumerable hubs)
+ ///
+ public RespawnedTeamEventArgs(SpawnableWaveBase wave, IEnumerable hubs)
{
Players = hubs.Select(Player.Get);
- Team = team;
+ Wave = wave;
}
///
@@ -38,6 +39,6 @@ public RespawnedTeamEventArgs(SpawnableTeamType team, IEnumerable
///
/// Gets the spawned team.
///
- public SpawnableTeamType Team { get; }
+ public SpawnableWaveBase Wave { get; }
}
}
diff --git a/EXILED/Exiled.Events/EventArgs/Server/RespawningTeamEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/RespawningTeamEventArgs.cs
index ab0234c2a..e65bdbf03 100644
--- a/EXILED/Exiled.Events/EventArgs/Server/RespawningTeamEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Server/RespawningTeamEventArgs.cs
@@ -10,19 +10,17 @@ namespace Exiled.Events.EventArgs.Server
using System.Collections.Generic;
using Exiled.API.Features;
+ using Exiled.API.Features.Waves;
using Exiled.Events.EventArgs.Interfaces;
-
using PlayerRoles;
-
using Respawning;
+ using Respawning.Waves;
///
- /// Contains all information before spawning a wave of or
- /// .
+ /// Contains all information before spawning a wave.
///
public class RespawningTeamEventArgs : IDeniableEvent
{
- private SpawnableTeamType nextKnownTeam;
private int maximumRespawnAmount;
///
@@ -34,21 +32,16 @@ public class RespawningTeamEventArgs : IDeniableEvent
///
///
///
- ///
+ ///
///
///
- ///
- ///
- ///
- public RespawningTeamEventArgs(List players, int maxRespawn, SpawnableTeamType nextKnownTeam, bool isAllowed = true)
+ public RespawningTeamEventArgs(List players, int maxRespawn, SpawnableWaveBase wave)
{
Players = players;
MaximumRespawnAmount = maxRespawn;
-
- this.nextKnownTeam = nextKnownTeam;
- SpawnQueue = new();
- SpawnableTeam.GenerateQueue(SpawnQueue, players.Count);
- IsAllowed = isAllowed;
+ SpawnQueue = WaveSpawner.SpawnQueue;
+ Wave = new TimedWave((TimeBasedWave)wave);
+ IsAllowed = true;
}
///
@@ -75,32 +68,14 @@ public int MaximumRespawnAmount
}
///
- /// Gets or sets a value indicating what the next respawnable team is.
+ /// Gets or sets a value indicating what the next wave is.
///
- public SpawnableTeamType NextKnownTeam
- {
- get => nextKnownTeam;
- set
- {
- nextKnownTeam = value;
-
- if (!RespawnManager.SpawnableTeams.TryGetValue(value, out SpawnableTeamHandlerBase spawnableTeam))
- {
- MaximumRespawnAmount = 0;
- return;
- }
-
- MaximumRespawnAmount = spawnableTeam.MaxWaveSize;
- if (RespawnManager.SpawnableTeams.TryGetValue(nextKnownTeam, out SpawnableTeamHandlerBase @base))
- @base.GenerateQueue(SpawnQueue, Players.Count);
- }
- }
+ public TimedWave Wave { get; set; }
///
- /// Gets the current spawnable team.
+ /// Gets a value indicating what the next respawnable team is.
///
- public SpawnableTeamHandlerBase SpawnableTeam
- => RespawnManager.SpawnableTeams.TryGetValue(NextKnownTeam, out SpawnableTeamHandlerBase @base) ? @base : null;
+ public Faction NextKnownTeam => Wave.Faction;
///
/// Gets or sets a value indicating whether the spawn can occur.
diff --git a/EXILED/Exiled.Events/EventArgs/Server/SelectingRespawnTeamEventArgs.cs b/EXILED/Exiled.Events/EventArgs/Server/SelectingRespawnTeamEventArgs.cs
index 63f27d345..dd6294777 100644
--- a/EXILED/Exiled.Events/EventArgs/Server/SelectingRespawnTeamEventArgs.cs
+++ b/EXILED/Exiled.Events/EventArgs/Server/SelectingRespawnTeamEventArgs.cs
@@ -7,29 +7,36 @@
namespace Exiled.Events.EventArgs.Server
{
- using System;
-
- using Exiled.API.Features;
+ using Exiled.API.Enums;
+ using Exiled.API.Features.Waves;
using Exiled.Events.EventArgs.Interfaces;
- using Respawning;
+ using Respawning.Waves;
///
/// Contains all information before selecting the team to respawn next.
///
- public class SelectingRespawnTeamEventArgs : IExiledEvent
+ public class SelectingRespawnTeamEventArgs : IDeniableEvent
{
///
/// Initializes a new instance of the class.
///
- /// The used as the starting value for this event.
- public SelectingRespawnTeamEventArgs(SpawnableTeamType type)
+ /// .
+ public SelectingRespawnTeamEventArgs(SpawnableWaveBase wave)
{
- Team = type;
+ Wave = new TimedWave((TimeBasedWave)wave);
}
///
- /// Gets or sets that represents the team chosen to spawn.
+ /// Gets that represents the team chosen to spawn.
///
- public SpawnableTeamType Team { get; set; }
+ public SpawnableFaction Team => Wave.SpawnableFaction;
+
+ ///
+ /// Gets or sets that is selected.
+ ///
+ public TimedWave Wave { get; set; }
+
+ ///
+ public bool IsAllowed { get; set; } = true;
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Events.cs b/EXILED/Exiled.Events/Events.cs
index f11eab2e1..ac37f5528 100644
--- a/EXILED/Exiled.Events/Events.cs
+++ b/EXILED/Exiled.Events/Events.cs
@@ -13,16 +13,17 @@ namespace Exiled.Events
using API.Enums;
using API.Features;
using CentralAuth;
+ using Exiled.API.Features.Core.UserSettings;
using Exiled.Events.Features;
using HarmonyLib;
using InventorySystem.Items.Pickups;
using InventorySystem.Items.Usables;
-
using PlayerRoles.Ragdolls;
using PlayerRoles.RoleAssign;
using PluginAPI.Events;
using Respawning;
using UnityEngine.SceneManagement;
+ using UserSettings.ServerSpecific;
///
/// Patch and unpatch events into the game.
@@ -59,8 +60,9 @@ public override void OnEnabled()
Log.Info($"{(Config.UseDynamicPatching ? "Non-event" : "All")} patches completed in {watch.Elapsed}");
PlayerAuthenticationManager.OnInstanceModeChanged -= RoleAssigner.CheckLateJoin;
+ CustomNetworkManager.OnClientStarted += Handlers.Internal.ClientStarted.OnClientStarted;
SceneManager.sceneUnloaded += Handlers.Internal.SceneUnloaded.OnSceneUnloaded;
- MapGeneration.SeedSynchronizer.OnMapGenerated += Handlers.Internal.MapGenerated.OnMapGenerated;
+ MapGeneration.SeedSynchronizer.OnGenerationFinished += Handlers.Internal.MapGenerated.OnMapGenerated;
UsableItemsController.ServerOnUsingCompleted += Handlers.Internal.Round.OnServerOnUsingCompleted;
Handlers.Server.WaitingForPlayers += Handlers.Internal.Round.OnWaitingForPlayers;
Handlers.Server.RestartingRound += Handlers.Internal.Round.OnRestartingRound;
@@ -71,7 +73,7 @@ public override void OnEnabled()
Handlers.Map.ChangedIntoGrenade += Handlers.Internal.ExplodingGrenade.OnChangedIntoGrenade;
CharacterClassManager.OnRoundStarted += Handlers.Server.OnRoundStarted;
- RespawnManager.ServerOnRespawned += Handlers.Server.OnRespawnedTeam;
+ WaveManager.OnWaveSpawned += Handlers.Server.OnRespawnedTeam;
InventorySystem.InventoryExtensions.OnItemAdded += Handlers.Player.OnItemAdded;
InventorySystem.InventoryExtensions.OnItemRemoved += Handlers.Player.OnItemRemoved;
@@ -81,6 +83,8 @@ public override void OnEnabled()
ItemPickupBase.OnPickupDestroyed += Handlers.Internal.PickupEvent.OnRemovedPickup;
ServerConsole.ReloadServerName();
+ ServerSpecificSettingsSync.ServerOnSettingValueReceived += SettingBase.OnSettingUpdated;
+
EventManager.RegisterEvents(this);
}
@@ -91,8 +95,9 @@ public override void OnDisabled()
Unpatch();
+ CustomNetworkManager.OnClientStarted -= Handlers.Internal.ClientStarted.OnClientStarted;
SceneManager.sceneUnloaded -= Handlers.Internal.SceneUnloaded.OnSceneUnloaded;
- MapGeneration.SeedSynchronizer.OnMapGenerated -= Handlers.Internal.MapGenerated.OnMapGenerated;
+ MapGeneration.SeedSynchronizer.OnGenerationFinished -= Handlers.Internal.MapGenerated.OnMapGenerated;
UsableItemsController.ServerOnUsingCompleted -= Handlers.Internal.Round.OnServerOnUsingCompleted;
Handlers.Server.WaitingForPlayers -= Handlers.Internal.Round.OnWaitingForPlayers;
Handlers.Server.RestartingRound -= Handlers.Internal.Round.OnRestartingRound;
@@ -106,12 +111,14 @@ public override void OnDisabled()
InventorySystem.InventoryExtensions.OnItemAdded -= Handlers.Player.OnItemAdded;
InventorySystem.InventoryExtensions.OnItemRemoved -= Handlers.Player.OnItemRemoved;
- RespawnManager.ServerOnRespawned -= Handlers.Server.OnRespawnedTeam;
+ WaveManager.OnWaveSpawned -= Handlers.Server.OnRespawnedTeam;
RagdollManager.OnRagdollSpawned -= Handlers.Internal.RagdollList.OnSpawnedRagdoll;
RagdollManager.OnRagdollRemoved -= Handlers.Internal.RagdollList.OnRemovedRagdoll;
ItemPickupBase.OnPickupAdded -= Handlers.Internal.PickupEvent.OnSpawnedPickup;
ItemPickupBase.OnPickupDestroyed -= Handlers.Internal.PickupEvent.OnRemovedPickup;
+ ServerSpecificSettingsSync.ServerOnSettingValueReceived -= SettingBase.OnSettingUpdated;
+
EventManager.UnregisterEvents(this);
}
diff --git a/EXILED/Exiled.Events/Handlers/Internal/ClientStarted.cs b/EXILED/Exiled.Events/Handlers/Internal/ClientStarted.cs
new file mode 100644
index 000000000..a260cf495
--- /dev/null
+++ b/EXILED/Exiled.Events/Handlers/Internal/ClientStarted.cs
@@ -0,0 +1,53 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Handlers.Internal
+{
+ using System.Collections.Generic;
+ using System.Linq;
+
+ using Exiled.API.Enums;
+ using Exiled.API.Features;
+ using Exiled.API.Features.Attributes;
+ using Mirror;
+ using PlayerRoles.Ragdolls;
+ using UnityEngine;
+
+ ///
+ /// Handles on client started event.
+ ///
+ internal static class ClientStarted
+ {
+ ///
+ /// Called once when the client is started.
+ ///
+ public static void OnClientStarted()
+ {
+ PrefabHelper.Prefabs.Clear();
+
+ Dictionary prefabs = new();
+
+ foreach (KeyValuePair prefab in NetworkClient.prefabs)
+ {
+ if(!prefabs.ContainsKey(prefab.Key))
+ prefabs.Add(prefab.Key, prefab.Value);
+ }
+
+ foreach (NetworkIdentity ragdollPrefab in RagdollManager.AllRagdollPrefabs)
+ {
+ if(!prefabs.ContainsKey(ragdollPrefab.assetId))
+ prefabs.Add(ragdollPrefab.assetId, ragdollPrefab.gameObject);
+ }
+
+ foreach (PrefabType prefabType in EnumUtils.Values)
+ {
+ PrefabAttribute attribute = prefabType.GetPrefabAttribute();
+ PrefabHelper.Prefabs.Add(prefabType, prefabs.FirstOrDefault(prefab => prefab.Key == attribute.AssetId || prefab.Value.name.Contains(attribute.Name)).Value);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs b/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs
index 68c47a99d..1320ad76a 100644
--- a/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs
+++ b/EXILED/Exiled.Events/Handlers/Internal/MapGenerated.cs
@@ -7,25 +7,14 @@
namespace Exiled.Events.Handlers.Internal
{
- using System;
using System.Collections.Generic;
using System.Linq;
using API.Features;
- using API.Features.Items;
- using API.Features.Pools;
- using API.Structs;
-
- using Exiled.API.Enums;
- using Exiled.API.Extensions;
using Exiled.API.Features.Lockers;
- using InventorySystem.Items.Firearms.Attachments;
- using InventorySystem.Items.Firearms.Attachments.Components;
using MEC;
- using Utils.NonAllocLINQ;
-
///
/// Handles event.
///
@@ -46,7 +35,6 @@ internal static class MapGenerated
public static void OnMapGenerated()
{
Map.ClearCache();
- PrefabHelper.LoadPrefabs();
Locker.ClearCache();
// TODO: Fix For (https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/377)
@@ -54,54 +42,7 @@ public static void OnMapGenerated()
PlayerRoles.RoleAssign.HumanSpawner.Handlers[PlayerRoles.Team.OtherAlive] = new PlayerRoles.RoleAssign.OneRoleHumanSpawner(PlayerRoles.RoleTypeId.Tutorial);
PlayerRoles.RoleAssign.HumanSpawner.Handlers[PlayerRoles.Team.Dead] = new PlayerRoles.RoleAssign.OneRoleHumanSpawner(PlayerRoles.RoleTypeId.Spectator);
- GenerateAttachments();
- Timing.CallDelayed(1, GenerateCache);
- }
-
- private static void GenerateCache()
- {
- Handlers.Map.OnGenerated();
-
- Timing.CallDelayed(0.1f, Handlers.Server.OnWaitingForPlayers);
- }
-
- private static void GenerateAttachments()
- {
- foreach (FirearmType firearmType in EnumUtils.Values)
- {
- if (firearmType == FirearmType.None)
- continue;
-
- if (Item.Create(firearmType.GetItemType()) is not Firearm firearm)
- continue;
-
- Firearm.ItemTypeToFirearmInstance.Add(firearmType, firearm);
-
- List attachmentIdentifiers = ListPool.Pool.Get();
- HashSet attachmentsSlots = HashSetPool.Pool.Get();
-
- uint code = 1;
-
- foreach (Attachment attachment in firearm.Attachments)
- {
- attachmentsSlots.Add(attachment.Slot);
- attachmentIdentifiers.Add(new(code, attachment.Name, attachment.Slot));
- code *= 2U;
- }
-
- uint baseCode = 0;
-
- attachmentsSlots
- .ForEach(slot => baseCode += attachmentIdentifiers
- .Where(attachment => attachment.Slot == slot)
- .Min(slot => slot.Code));
-
- Firearm.BaseCodesValue.Add(firearmType, baseCode);
- Firearm.AvailableAttachmentsValue.Add(firearmType, attachmentIdentifiers.ToArray());
-
- ListPool.Pool.Return(attachmentIdentifiers);
- HashSetPool.Pool.Return(attachmentsSlots);
- }
+ Timing.CallDelayed(1, Handlers.Map.OnGenerated);
}
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Handlers/Internal/Round.cs b/EXILED/Exiled.Events/Handlers/Internal/Round.cs
index 5c9ff4c5f..9d04e5c4c 100644
--- a/EXILED/Exiled.Events/Handlers/Internal/Round.cs
+++ b/EXILED/Exiled.Events/Handlers/Internal/Round.cs
@@ -7,20 +7,29 @@
namespace Exiled.Events.Handlers.Internal
{
+ using System.Collections.Generic;
using System.Linq;
using CentralAuth;
+ using Exiled.API.Enums;
using Exiled.API.Extensions;
using Exiled.API.Features;
+ using Exiled.API.Features.Core.UserSettings;
+ using Exiled.API.Features.Items;
+ using Exiled.API.Features.Pools;
using Exiled.API.Features.Roles;
+ using Exiled.API.Structs;
using Exiled.Events.EventArgs.Player;
using Exiled.Events.EventArgs.Scp049;
using Exiled.Loader;
using Exiled.Loader.Features;
using InventorySystem;
+ using InventorySystem.Items.Firearms.Attachments;
+ using InventorySystem.Items.Firearms.Attachments.Components;
using InventorySystem.Items.Usables;
using PlayerRoles;
using PlayerRoles.RoleAssign;
+ using Utils.NonAllocLINQ;
///
/// Handles some round clean-up events and some others related to players.
@@ -33,6 +42,7 @@ internal static class Round
///
public static void OnWaitingForPlayers()
{
+ GenerateAttachments();
MultiAdminFeatures.CallEvent(MultiAdminFeatures.EventType.WAITING_FOR_PLAYERS);
if (Events.Instance.Config.ShouldReloadConfigsAtRoundRestart)
@@ -86,6 +96,9 @@ public static void OnVerified(VerifiedEventArgs ev)
{
RoleAssigner.CheckLateJoin(ev.Player.ReferenceHub, ClientInstanceMode.ReadyClient);
+ if (SettingBase.SyncOnJoin != null && SettingBase.SyncOnJoin(ev.Player))
+ SettingBase.SendToPlayer(ev.Player);
+
// TODO: Remove if this has been fixed for https://git.scpslgame.com/northwood-qa/scpsl-bug-reporting/-/issues/52
foreach (Room room in Room.List.Where(current => current.AreLightsOff))
{
@@ -93,5 +106,42 @@ public static void OnVerified(VerifiedEventArgs ev)
ev.Player.SendFakeSyncVar(room.RoomLightControllerNetIdentity, typeof(RoomLightController), nameof(RoomLightController.NetworkLightsEnabled), false);
}
}
+
+ private static void GenerateAttachments()
+ {
+ foreach (FirearmType firearmType in EnumUtils.Values)
+ {
+ if (firearmType == FirearmType.None)
+ continue;
+
+ if (Item.Create(firearmType.GetItemType()) is not Firearm firearm)
+ continue;
+
+ Firearm.ItemTypeToFirearmInstance.Add(firearmType, firearm);
+
+ List attachmentIdentifiers = ListPool.Pool.Get();
+ HashSet attachmentsSlots = HashSetPool.Pool.Get();
+
+ uint code = 1;
+
+ foreach (Attachment attachment in firearm.Attachments)
+ {
+ attachmentsSlots.Add(attachment.Slot);
+ attachmentIdentifiers.Add(new(code, attachment.Name, attachment.Slot));
+ code *= 2U;
+ }
+
+ uint baseCode = 0;
+ attachmentsSlots.ForEach(slot => baseCode += attachmentIdentifiers
+ .Where(attachment => attachment.Slot == slot)
+ .Min(slot => slot.Code));
+
+ Firearm.BaseCodesValue.Add(firearmType, baseCode);
+ Firearm.AvailableAttachmentsValue.Add(firearmType, attachmentIdentifiers.ToArray());
+
+ ListPool.Pool.Return(attachmentIdentifiers);
+ HashSetPool.Pool.Return(attachmentsSlots);
+ }
+ }
}
}
diff --git a/EXILED/Exiled.Events/Handlers/Map.cs b/EXILED/Exiled.Events/Handlers/Map.cs
index eaaf3703e..3036d4ede 100644
--- a/EXILED/Exiled.Events/Handlers/Map.cs
+++ b/EXILED/Exiled.Events/Handlers/Map.cs
@@ -25,11 +25,6 @@ public static class Map
///
public static Event PlacingBulletHole { get; set; } = new();
- ///
- /// Invoked before placing blood.
- ///
- public static Event PlacingBlood { get; set; } = new();
-
///
/// Invoked before announcing the light containment zone decontamination.
///
@@ -45,6 +40,11 @@ public static class Map
///
public static Event AnnouncingNtfEntrance { get; set; } = new();
+ ///
+ /// Invoked before announcing the Chaos entrance.
+ ///
+ public static Event AnnouncingChaosEntrance { get; set; } = new();
+
///
/// Invoked before a has been activated.
///
@@ -121,12 +121,6 @@ public static class Map
/// The instance.
public static void OnPlacingBulletHole(PlacingBulletHoleEventArgs ev) => PlacingBulletHole.InvokeSafely(ev);
- ///
- /// Called before placing bloods.
- ///
- /// The instance.
- public static void OnPlacingBlood(PlacingBloodEventArgs ev) => PlacingBlood.InvokeSafely(ev);
-
///
/// Called before announcing the light containment zone decontamination.
///
@@ -145,6 +139,12 @@ public static class Map
/// The instance.
public static void OnAnnouncingNtfEntrance(AnnouncingNtfEntranceEventArgs ev) => AnnouncingNtfEntrance.InvokeSafely(ev);
+ ///
+ /// Called before announcing the Chaos entrance.
+ ///
+ /// The instance.
+ public static void OnAnnouncingChaosEntrance(AnnouncingChaosEntranceEventArgs ev) => AnnouncingChaosEntrance.InvokeSafely(ev);
+
///
/// Called before a has been activated.
///
diff --git a/EXILED/Exiled.Events/Handlers/Player.cs b/EXILED/Exiled.Events/Handlers/Player.cs
index 2d277ce6a..4efe258a3 100644
--- a/EXILED/Exiled.Events/Handlers/Player.cs
+++ b/EXILED/Exiled.Events/Handlers/Player.cs
@@ -70,12 +70,16 @@ public class Player
public static Event EarningAchievement { get; set; } = new();
///
- /// Invoked before using an .
+ /// Invoked before the player starts to use an . In other words, it is invoked just before the animation starts.
///
+ ///
+ /// Will be invoked even if the is on cooldown.
+ /// Candies are the only that do not invoke this event.
+ ///
public static Event UsingItem { get; set; } = new();
///
- /// Invoked after a uses an .
+ /// Invoked before a finishes using a . In other words, it is invoked after the animation finishes but before the is actually used.
///
public static Event UsingItemCompleted { get; set; } = new ();
@@ -501,8 +505,8 @@ public class Player
///
/// Invoked before a damage a Window.
- /// // TODO: DamagingWindow instead of PlayerDamageWindow
- public static Event PlayerDamageWindow { get; set; } = new();
+ ///
+ public static Event DamagingWindow { get; set; } = new();
///
/// Invoked before a damage a Door.
@@ -519,12 +523,6 @@ public class Player
///
public static Event ItemRemoved { get; set; } = new();
- ///
- /// Invoked before KillPlayer is called.
- ///
- [Obsolete("Use DyingEventArgs")]
- public static Event KillingPlayer { get; set; } = new();
-
///
/// Invoked before a enters in an environmental hazard.
///
@@ -545,6 +543,38 @@ public class Player
///
public static Event ChangingNickname { get; set; } = new();
+ ///
+ /// Invoked before a player's emotion changed.
+ ///
+ public static Event ChangingEmotion { get; set; } = new();
+
+ ///
+ /// Invoked after a player's emotion changed.
+ ///
+ public static Event ChangedEmotion { get; set; } = new();
+
+ ///
+ /// Invoked before a 's rotates the revolver.
+ ///
+ public static Event RotatingRevolver { get; set; } = new();
+
+ ///
+ /// Invoked before disruptor's mode is changed.
+ ///
+ public static Event ChangingDisruptorMode { get; set; } = new();
+
+ ///
+ /// Called before a player's emotion changed.
+ ///
+ /// The instance.
+ public static void OnChangingEmotion(ChangingEmotionEventArgs ev) => ChangingEmotion.InvokeSafely(ev);
+
+ ///
+ /// Called after a player's emotion changed.
+ ///
+ /// The instance.
+ public static void OnChangedEmotion(ChangedEmotionEventArgs ev) => ChangedEmotion.InvokeSafely(ev);
+
///
/// Called before reserved slot is resolved for a .
///
@@ -676,8 +706,7 @@ public class Player
/// Called before throwing a grenade.
///
/// The instance.
- // TODO: rename that to OnThrownProjectile
- public static void OnThrowingProjectile(ThrownProjectileEventArgs ev) => ThrownProjectile.InvokeSafely(ev);
+ public static void OnThrownProjectile(ThrownProjectileEventArgs ev) => ThrownProjectile.InvokeSafely(ev);
///
/// Called before receving a throwing request.
@@ -985,13 +1014,6 @@ public class Player
/// The instance.
public static void OnSendingAdminChatMessage(SendingAdminChatMessageEventsArgs ev) => SendingAdminChatMessage.InvokeSafely(ev);
- ///
- /// Called before KillPlayer is called.
- ///
- /// The event handler.
- [Obsolete("Use DyingEventArgs")]
- public static void OnKillPlayer(KillingPlayerEventArgs ev) => KillingPlayer.InvokeSafely(ev);
-
///
/// Called after a has an item added to their inventory.
///
@@ -1018,11 +1040,12 @@ public static void OnItemAdded(ReferenceHub referenceHub, InventorySystem.Items.
public static void OnItemRemoved(ReferenceHub referenceHub, InventorySystem.Items.ItemBase itemBase, InventorySystem.Items.Pickups.ItemPickupBase pickupBase)
{
ItemRemovedEventArgs ev = new(referenceHub, itemBase, pickupBase);
- ItemRemoved.InvokeSafely(ev);
ev.Player.ItemsValue.Remove(ev.Item);
API.Features.Items.Item.BaseToItem.Remove(itemBase);
+
+ ItemRemoved.InvokeSafely(ev);
}
///
@@ -1047,7 +1070,7 @@ public static void OnItemRemoved(ReferenceHub referenceHub, InventorySystem.Item
/// Called before a damage a window.
///
/// The instance.
- public static void OnPlayerDamageWindow(DamagingWindowEventArgs ev) => PlayerDamageWindow.InvokeSafely(ev);
+ public static void OnDamagingWindow(DamagingWindowEventArgs ev) => DamagingWindow.InvokeSafely(ev);
///
/// Called before a damage a window.
@@ -1175,6 +1198,18 @@ public static void OnItemRemoved(ReferenceHub referenceHub, InventorySystem.Item
/// The instance.
public static void OnChangingNickname(ChangingNicknameEventArgs ev) => ChangingNickname.InvokeSafely(ev);
+ ///
+ /// Called before a 's rotates the revolver.
+ ///
+ /// The instance.
+ public static void OnRotatingRevolver(RotatingRevolverEventArgs ev) => RotatingRevolver.InvokeSafely(ev);
+
+ ///
+ /// Called before disruptor's mode is changed.
+ ///
+ /// The instance.
+ public static void OnChangingDisruptorMode(ChangingDisruptorModeEventArgs ev) => ChangingDisruptorMode.InvokeSafely(ev);
+
///
/// Called before pre-authenticating a .
///
diff --git a/EXILED/Exiled.Events/Handlers/Scp1344.cs b/EXILED/Exiled.Events/Handlers/Scp1344.cs
new file mode 100644
index 000000000..e3cd688c7
--- /dev/null
+++ b/EXILED/Exiled.Events/Handlers/Scp1344.cs
@@ -0,0 +1,75 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Handlers
+{
+#pragma warning disable SA1623 // Property summary documentation should match accessors
+
+ using Exiled.Events.EventArgs.Scp1344;
+ using Exiled.Events.Features;
+
+ ///
+ /// SCP-1344 related events.
+ ///
+ public static class Scp1344
+ {
+ ///
+ /// Invoked before SCP-1344 status changing.
+ ///
+ public static Event ChangingStatus { get; set; } = new();
+
+ ///
+ /// Invoked after SCP-1344 status changing.
+ ///
+ public static Event ChangedStatus { get; set; } = new();
+
+ ///
+ /// Invoked after trying deactivating SCP-1344.
+ ///
+ public static Event TryingDeactivating { get; set; } = new();
+
+ ///
+ /// Invoked before deactivating SCP-1344.
+ ///
+ public static Event Deactivating { get; set; } = new();
+
+ ///
+ /// Invoked after deactivating SCP-1344.
+ ///
+ public static Event Deactivated { get; set; } = new();
+
+ ///
+ /// Called after deactivating SCP-1344.
+ ///
+ /// The instance.
+ public static void OnDeactivated(DeactivatedEventArgs ev) => Deactivated.InvokeSafely(ev);
+
+ ///
+ /// Called before deactivating SCP-1344.
+ ///
+ /// The instance.
+ public static void OnDeactivating(DeactivatingEventArgs ev) => Deactivating.InvokeSafely(ev);
+
+ ///
+ /// Called after trying deactivating SCP-1344.
+ ///
+ /// The instance.
+ public static void OnTryingDeactivating(TryingDeactivatingEventArgs ev) => TryingDeactivating.InvokeSafely(ev);
+
+ ///
+ /// Called before SCP-1344 status changing.
+ ///
+ /// The instance.
+ public static void OnChangingStatus(ChangingStatusEventArgs ev) => ChangingStatus.InvokeSafely(ev);
+
+ ///
+ /// Called after SCP-1344 status changing.
+ ///
+ /// The instance.
+ public static void OnChangedStatus(ChangedStatusEventArgs ev) => ChangedStatus.InvokeSafely(ev);
+ }
+}
diff --git a/EXILED/Exiled.Events/Handlers/Server.cs b/EXILED/Exiled.Events/Handlers/Server.cs
index f7032f6ed..c86a8adee 100644
--- a/EXILED/Exiled.Events/Handlers/Server.cs
+++ b/EXILED/Exiled.Events/Handlers/Server.cs
@@ -10,9 +10,10 @@ namespace Exiled.Events.Handlers
using System.Collections.Generic;
using Respawning;
+ using Respawning.Waves;
+
#pragma warning disable SA1623 // Property summary documentation should match accessors
- using Exiled.Events.EventArgs.Player;
using Exiled.Events.EventArgs.Server;
using Exiled.Events.Features;
@@ -163,9 +164,9 @@ public static class Server
///
/// Called after team spawns.
///
- ///
+ ///
///
- public static void OnRespawnedTeam(SpawnableTeamType teamType, List hubs) => RespawnedTeam.InvokeSafely(new RespawnedTeamEventArgs(teamType, hubs));
+ public static void OnRespawnedTeam(SpawnableWaveBase teamType, List hubs) => RespawnedTeam.InvokeSafely(new RespawnedTeamEventArgs(teamType, hubs));
///
/// Called before adding an unit name.
diff --git a/EXILED/Exiled.Events/Patches/Events/Item/ChangingAmmo.cs b/EXILED/Exiled.Events/Patches/Events/Item/ChangingAmmo.cs
index 2d020b250..7ef8824da 100644
--- a/EXILED/Exiled.Events/Patches/Events/Item/ChangingAmmo.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Item/ChangingAmmo.cs
@@ -23,13 +23,15 @@ namespace Exiled.Events.Patches.Events.Item
using static HarmonyLib.AccessTools;
///
- /// Patches .
+ /// Patches .
/// Adds the event.
///
[EventPatch(typeof(Item), nameof(Item.ChangingAmmo))]
- [HarmonyPatch(typeof(Firearm), nameof(Firearm.Status), MethodType.Setter)]
+
+ // [HarmonyPatch(typeof(Firearm), nameof(Firearm.Status), MethodType.Setter)]
internal static class ChangingAmmo
{
+ /*
private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
{
List newInstructions = ListPool.Pool.Get(instructions);
@@ -137,5 +139,6 @@ private static IEnumerable Transpiler(IEnumerable.Pool.Return(newInstructions);
}
+ */
}
}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Item/ReceivingPreference.cs b/EXILED/Exiled.Events/Patches/Events/Item/ReceivingPreference.cs
index 1558c49fe..96b9907b3 100644
--- a/EXILED/Exiled.Events/Patches/Events/Item/ReceivingPreference.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Item/ReceivingPreference.cs
@@ -39,7 +39,8 @@ private static IEnumerable Transpiler(IEnumerable newInstructions = ListPool.Pool.Get(instructions);
- int index = newInstructions.FindLastIndex(instruction => instruction.opcode == OpCodes.Ldloc_1);
+ int offset = 1;
+ int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Ret) + offset;
LocalBuilder ev = generator.DeclareLocal(typeof(ReceivingPreferenceEventArgs));
LocalBuilder curCode = generator.DeclareLocal(typeof(uint));
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/AnnouncingChaosEntrance.cs b/EXILED/Exiled.Events/Patches/Events/Map/AnnouncingChaosEntrance.cs
new file mode 100644
index 000000000..1bf2c9c02
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Map/AnnouncingChaosEntrance.cs
@@ -0,0 +1,84 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Map
+{
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Text;
+
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Map;
+ using HarmonyLib;
+ using Respawning.Announcements;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches and
+ /// to add event.
+ ///
+ [EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.AnnouncingChaosEntrance))]
+ [HarmonyPatch]
+ internal static class AnnouncingChaosEntrance
+ {
+ private static IEnumerable TargetMethods()
+ {
+ yield return Method(typeof(ChaosWaveAnnouncement), nameof(ChaosWaveAnnouncement.CreateAnnouncementString));
+ yield return Method(typeof(ChaosMiniwaveAnnouncement), nameof(ChaosMiniwaveAnnouncement.CreateAnnouncementString));
+ }
+
+ private static IEnumerable Transpiler(IEnumerable instruction, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instruction);
+
+ Label continueLabel = generator.DefineLabel();
+
+ LocalBuilder ev = generator.DeclareLocal(typeof(AnnouncingChaosEntranceEventArgs));
+
+ int index = newInstructions.FindIndex(i => i.opcode == OpCodes.Ldloca_S);
+
+ newInstructions.InsertRange(index, new[]
+ {
+ // WaveAnnouncementBase
+ new(OpCodes.Ldarg_0),
+
+ // builder
+ new(OpCodes.Ldarg_1),
+
+ // new AnnouncingChaosEntranceEventArgs(WaveAnnouncementBase, StringBuilder)
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(AnnouncingChaosEntranceEventArgs))[0]),
+ new(OpCodes.Dup),
+ new(OpCodes.Dup),
+ new(OpCodes.Stloc_S, ev.LocalIndex),
+
+ // Map.OnAnnouncingChaosEntrance(ev)
+ new(OpCodes.Call, Method(typeof(Handlers.Map), nameof(Handlers.Map.OnAnnouncingChaosEntrance))),
+
+ // if (!ev.IsAllowed)
+ // builder.Clear();
+ // return;
+ new(OpCodes.Callvirt, PropertyGetter(typeof(AnnouncingChaosEntranceEventArgs), nameof(AnnouncingChaosEntranceEventArgs.IsAllowed))),
+ new(OpCodes.Brtrue_S, continueLabel),
+
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Callvirt, Method(typeof(StringBuilder), nameof(StringBuilder.Clear))),
+ new(OpCodes.Pop),
+ new(OpCodes.Ret),
+
+ new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel),
+ });
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/AnnouncingNtfEntrance.cs b/EXILED/Exiled.Events/Patches/Events/Map/AnnouncingNtfEntrance.cs
index 558362a9b..f9663ecc7 100644
--- a/EXILED/Exiled.Events/Patches/Events/Map/AnnouncingNtfEntrance.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Map/AnnouncingNtfEntrance.cs
@@ -8,29 +8,34 @@
namespace Exiled.Events.Patches.Events.Map
{
using System.Collections.Generic;
+ using System.Reflection;
using System.Reflection.Emit;
using System.Text.RegularExpressions;
using API.Features.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Map;
-
using Handlers;
-
using HarmonyLib;
-
+ using Respawning.Announcements;
using Respawning.NamingRules;
using static HarmonyLib.AccessTools;
///
- /// Patch the .
+ /// Patch the and .
/// Adds the event.
///
[EventPatch(typeof(Map), nameof(Map.AnnouncingNtfEntrance))]
- [HarmonyPatch(typeof(NineTailedFoxNamingRule), nameof(NineTailedFoxNamingRule.PlayEntranceAnnouncement))]
+ [HarmonyPatch]
internal static class AnnouncingNtfEntrance
{
+ private static IEnumerable TargetMethods()
+ {
+ yield return Method(typeof(NtfWaveAnnouncement), nameof(NtfWaveAnnouncement.CreateAnnouncementString));
+ yield return Method(typeof(NtfMiniwaveAnnouncement), nameof(NtfMiniwaveAnnouncement.CreateAnnouncementString));
+ }
+
private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
{
List newInstructions = ListPool.Pool.Get(instructions);
@@ -40,31 +45,21 @@ private static IEnumerable Transpiler(IEnumerable instruction.opcode == OpCodes.Stloc_1) + offset;
-
- // int scpsLeft = ReferenceHub.GetAllHubs().Values.Count(x => x.characterClassManager.CurRole.team == Team.SCP && x.characterClassManager.CurClass != RoleTypeId.Scp0492);
- // string unitNameClear = Regex.Replace(unitName, "<[^>]*?>", string.Empty);
- // string[] unitInformation = unitNameClear.Split('-');
- //
- // AnnouncingNtfEntranceEventArgs ev = new(scpsLeft, unitInformation[0], int.Parse(unitInformation[1]));
- // Map.OnAnnouncingNtfEntrance(ev);
- //
- // if (!ev.IsAllowed)
- // return;
- //
- // unitName = $"{ev.UnitName}-{ev.UnitNumber};
- // cassieUnitName = this.GetCassieUnitName(unitName);
- // scpsLeft = ev.ScpsLeft;
+ int offset = 1;
+ int index = newInstructions.FindIndex(instruction => instruction.opcode == OpCodes.Stloc_3) + offset;
+
newInstructions.InsertRange(
index,
- new[]
+ new CodeInstruction[]
{
+ // WaveAnnouncementBase
+ new(OpCodes.Ldarg_0),
+
// int scpsLeft = ReferenceHub.GetAllHubs().Values.Count(x => x.characterClassManager.CurRole.team == Team.SCP && x.characterClassManager.CurClass != RoleTypeId.Scp0492);
- new CodeInstruction(OpCodes.Ldloc_1),
+ new(OpCodes.Ldloc_3),
// string[] unitInformation = unitNameClear.Split('-');
- new(OpCodes.Ldarg_1),
+ new(OpCodes.Ldloc_1),
new(OpCodes.Ldstr, "<[^>]*?>"),
new(OpCodes.Ldsfld, Field(typeof(string), nameof(string.Empty))),
new(OpCodes.Call, Method(typeof(Regex), nameof(Regex.Replace), new System.Type[] { typeof(string), typeof(string), typeof(string) })),
@@ -87,7 +82,6 @@ private static IEnumerable Transpiler(IEnumerable Transpiler(IEnumerable Transpiler(IEnumerable
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Map
+{
+ using System.Collections.Generic;
+ using System.Reflection;
+ using System.Reflection.Emit;
+ using System.Text;
+
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Map;
+ using HarmonyLib;
+ using Respawning.Announcements;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches to prevent cassie from playing empty string.
+ ///
+ [EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.AnnouncingNtfEntrance))]
+ [EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.AnnouncingChaosEntrance))]
+ [HarmonyPatch(typeof(WaveAnnouncementBase), nameof(WaveAnnouncementBase.PlayAnnouncement))]
+ internal static class AnnouncingTeamEntrance
+ {
+ private static IEnumerable Transpiler(IEnumerable instruction, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instruction);
+
+ Label returnLabel = generator.DefineLabel();
+
+ int index = newInstructions.FindLastIndex(i => i.opcode == OpCodes.Ldsfld);
+
+ newInstructions.InsertRange(index, new CodeInstruction[]
+ {
+ // if (stringReturn == "")
+ // return;
+ new(OpCodes.Ldloc_S, 4),
+ new(OpCodes.Ldstr, string.Empty),
+ new(OpCodes.Ceq),
+ new(OpCodes.Brtrue_S, returnLabel),
+ });
+
+ newInstructions[newInstructions.Count - 1].labels.Add(returnLabel);
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/BreakingScp2176.cs b/EXILED/Exiled.Events/Patches/Events/Map/BreakingScp2176.cs
index 6707f5b82..8236e2c48 100644
--- a/EXILED/Exiled.Events/Patches/Events/Map/BreakingScp2176.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Map/BreakingScp2176.cs
@@ -56,8 +56,8 @@ private static IEnumerable Transpiler(IEnumerable, bool)
- new(OpCodes.Newobj, DeclaredConstructor(typeof(ExplodingGrenadeEventArgs), new[] { typeof(Player), typeof(EffectGrenade), typeof(List), typeof(bool) })),
+ // new ExplodingGrenadeEventArgs(Player, EffectGrenade, HashSet, bool)
+ new(OpCodes.Newobj, DeclaredConstructor(typeof(ExplodingGrenadeEventArgs), new[] { typeof(Player), typeof(EffectGrenade), typeof(HashSet), typeof(bool) })),
new(OpCodes.Dup),
// Handlers.Map.OnExplodingGrenade(ev);
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs
index 3237e5603..4413d1829 100644
--- a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFlashGrenade.cs
@@ -12,8 +12,10 @@ namespace Exiled.Events.Patches.Events.Map
using API.Features;
using API.Features.Pools;
+ using Exiled.API.Extensions;
using Exiled.Events.EventArgs.Map;
using Exiled.Events.Patches.Generic;
+ using Footprinting;
using HarmonyLib;
using InventorySystem.Items.ThrowableProjectiles;
using UnityEngine;
@@ -61,15 +63,14 @@ private static IEnumerable Transpiler(IEnumerable targetToAffect = ListPool.Pool.Get();
- foreach (ReferenceHub referenceHub in ReferenceHub.AllHubs)
+ HashSet targetToAffect = HashSetPool.Pool.Get();
+ foreach (Player player in Player.List)
{
- Player player = Player.Get(referenceHub);
- if ((instance.transform.position - referenceHub.transform.position).sqrMagnitude >= distance)
+ if ((instance.transform.position - player.Position).sqrMagnitude >= distance)
continue;
- if (!ExiledEvents.Instance.Config.CanFlashbangsAffectThrower && instance.PreviousOwner.SameLife(new(referenceHub)))
+ if (!ExiledEvents.Instance.Config.CanFlashbangsAffectThrower && instance.PreviousOwner.CompareLife(player.ReferenceHub))
continue;
- if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub) && !instance.PreviousOwner.SameLife(new(referenceHub)))
+ if (!IndividualFriendlyFire.CheckFriendlyFirePlayer(instance.PreviousOwner, player.ReferenceHub) && !instance.PreviousOwner.CompareLife(player.ReferenceHub))
continue;
if (Physics.Linecast(instance.transform.position, player.CameraTransform.position, instance._blindingMask))
continue;
@@ -79,7 +80,7 @@ private static void ProcessEvent(FlashbangGrenade instance, float distance)
ExplodingGrenadeEventArgs explodingGrenadeEvent = new(Player.Get(instance.PreviousOwner.Hub), instance, targetToAffect);
- ListPool.Pool.Return(targetToAffect);
+ HashSetPool.Pool.Return(targetToAffect);
Handlers.Map.OnExplodingGrenade(explodingGrenadeEvent);
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFragGrenade.cs b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFragGrenade.cs
index 60faf8a97..37a8bef64 100644
--- a/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFragGrenade.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Map/ExplodingFragGrenade.cs
@@ -26,7 +26,7 @@ namespace Exiled.Events.Patches.Events.Map
using static HarmonyLib.AccessTools;
///
- /// Patches .
+ /// Patches .
/// Adds the event.
///
[EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.ExplodingGrenade))]
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/FillingLocker.cs b/EXILED/Exiled.Events/Patches/Events/Map/FillingLocker.cs
index 2ec49178a..0816e0934 100644
--- a/EXILED/Exiled.Events/Patches/Events/Map/FillingLocker.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Map/FillingLocker.cs
@@ -37,14 +37,14 @@ private static IEnumerable Transpiler(IEnumerable instruction.Calls(Method(typeof(HashSet), nameof(HashSet.Add), new[] { typeof(ItemPickupBase) }))) + offset;
+ int index = newInstructions.FindIndex(instruction => instruction.Calls(Method(typeof(List), nameof(List.Add), new[] { typeof(ItemPickupBase) }))) + offset;
newInstructions.InsertRange(
index,
new[]
{
// FillingLockerEventArgs ev = new(ItemPickupBase, loockerChamber)
- new(OpCodes.Ldloc_S, 4),
+ new(OpCodes.Ldloc_S, 5),
new(OpCodes.Ldarg_0),
new CodeInstruction(OpCodes.Newobj, GetDeclaredConstructors(typeof(FillingLockerEventArgs))[0]),
new(OpCodes.Dup),
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/PlacingBlood.cs b/EXILED/Exiled.Events/Patches/Events/Map/PlacingBlood.cs
deleted file mode 100644
index f8703fe0b..000000000
--- a/EXILED/Exiled.Events/Patches/Events/Map/PlacingBlood.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-// -----------------------------------------------------------------------
-//
-// Copyright (c) ExMod Team. All rights reserved.
-// Licensed under the CC BY-SA 3.0 license.
-//
-// -----------------------------------------------------------------------
-
-namespace Exiled.Events.Patches.Events.Map
-{
- using System.Collections.Generic;
- using System.Reflection.Emit;
-
- using API.Features.Pools;
- using Exiled.Events.Attributes;
- using Exiled.Events.EventArgs.Map;
-
- using HarmonyLib;
-
- using InventorySystem.Items.Firearms.Modules;
-
- using UnityEngine;
-
- using static HarmonyLib.AccessTools;
-
- using ExiledEvents = Exiled.Events.Events;
-
- ///
- /// Patches .
- /// Adds the event.
- ///
- [EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.PlacingBlood))]
- [HarmonyPatch(typeof(StandardHitregBase), nameof(StandardHitregBase.PlaceBloodDecal))]
- internal static class PlacingBlood
- {
- private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
- {
- List newInstructions = ListPool.Pool.Get(instructions);
-
- Label returnLabel = generator.DefineLabel();
-
- LocalBuilder ev = generator.DeclareLocal(typeof(PlacingBloodEventArgs));
-
- // if (!ExiledEvents.Instance.Config.CanSpawnBlood)
- // return;
- //
- // PlacingBloodEventArgs ev = new(Player.Get(this.Hub), Player.Get(target.NetworkId), hit, true);
- //
- // Handlers.Map.OnPlacingBlood(ev);
- //
- // if (!ev.IsAllowed)
- // return;
- //
- // hit.point = ev.Position;
- newInstructions.InsertRange(
- 0,
- new[]
- {
- // if (!ExiledEvents.Instance.Config.CanSpawnBlood)
- // return;
- new CodeInstruction(OpCodes.Call, PropertyGetter(typeof(ExiledEvents), nameof(ExiledEvents.Instance))),
- new(OpCodes.Callvirt, PropertyGetter(typeof(ExiledEvents), nameof(ExiledEvents.Config))),
- new(OpCodes.Callvirt, PropertyGetter(typeof(Config), nameof(Config.CanSpawnBlood))),
- new(OpCodes.Brfalse_S, returnLabel),
-
- // Player.Get(this.Hub)
- new(OpCodes.Ldarg_0),
- new(OpCodes.Callvirt, PropertyGetter(typeof(StandardHitregBase), nameof(StandardHitregBase.Hub))),
- new(OpCodes.Call, Method(typeof(API.Features.Player), nameof(API.Features.Player.Get), new[] { typeof(ReferenceHub) })),
-
- // Player.Get(target.NetworkId)
- new(OpCodes.Ldarg_3),
- new(OpCodes.Callvirt, PropertyGetter(typeof(IDestructible), nameof(IDestructible.NetworkId))),
- new(OpCodes.Call, Method(typeof(API.Features.Player), nameof(API.Features.Player.Get), new[] { typeof(uint) })),
-
- // hit
- new(OpCodes.Ldarg_2),
-
- // true
- new(OpCodes.Ldc_I4_1),
-
- // PlacingBloodEventArgs ev = new(Player, Player, RaycastHit, bool)
- new(OpCodes.Newobj, GetDeclaredConstructors(typeof(PlacingBloodEventArgs))[0]),
- new(OpCodes.Dup),
- new(OpCodes.Dup),
- new(OpCodes.Stloc_S, ev.LocalIndex),
-
- // Handlers.Map.OnPlacingBlood(ev)
- new(OpCodes.Call, Method(typeof(Handlers.Map), nameof(Handlers.Map.OnPlacingBlood))),
-
- // if (!ev.isAllowed)
- // return;
- new(OpCodes.Callvirt, PropertyGetter(typeof(PlacingBloodEventArgs), nameof(PlacingBloodEventArgs.IsAllowed))),
- new(OpCodes.Brfalse_S, returnLabel),
-
- // hit.info = ev.Position
- new(OpCodes.Ldarga_S, 2),
- new(OpCodes.Ldloc_S, ev.LocalIndex),
- new(OpCodes.Callvirt, PropertyGetter(typeof(PlacingBloodEventArgs), nameof(PlacingBloodEventArgs.Position))),
- new(OpCodes.Callvirt, PropertySetter(typeof(RaycastHit), nameof(RaycastHit.point))),
- });
-
- newInstructions[newInstructions.Count - 1].labels.Add(returnLabel);
-
- for (int z = 0; z < newInstructions.Count; z++)
- yield return newInstructions[z];
-
- ListPool.Pool.Return(newInstructions);
- }
- }
-}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/PlacingBulletHole.cs b/EXILED/Exiled.Events/Patches/Events/Map/PlacingBulletHole.cs
index fd20be131..16a1b96e8 100644
--- a/EXILED/Exiled.Events/Patches/Events/Map/PlacingBulletHole.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Map/PlacingBulletHole.cs
@@ -8,19 +8,18 @@
namespace Exiled.Events.Patches.Events.Map
{
using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
using System.Reflection.Emit;
using API.Features.Pools;
-
+ using Decals;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Map;
-
using Handlers;
-
using HarmonyLib;
-
+ using InventorySystem.Items;
using InventorySystem.Items.Firearms.Modules;
-
using UnityEngine;
using static HarmonyLib.AccessTools;
@@ -28,11 +27,11 @@ namespace Exiled.Events.Patches.Events.Map
using Player = API.Features.Player;
///
- /// Patches .
+ /// Patches .
/// Adds the event.
///
[EventPatch(typeof(Map), nameof(Map.PlacingBulletHole))]
- [HarmonyPatch(typeof(StandardHitregBase), nameof(StandardHitregBase.PlaceBulletholeDecal))]
+ [HarmonyPatch(typeof(ImpactEffectsModule), nameof(ImpactEffectsModule.ServerSendImpactDecal))]
internal static class PlacingBulletHole
{
private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
@@ -48,15 +47,15 @@ private static IEnumerable Transpiler(IEnumerable x.Name == "Get").First()),
// hit
new(OpCodes.Ldarg_2),
- // PlacingBulletHole ev = new(Player, RaycastHit)
+ // PlacingBulletHole ev = new(Item, RaycastHit)
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(PlacingBulletHoleEventArgs))[0]),
new(OpCodes.Dup),
new(OpCodes.Dup),
diff --git a/EXILED/Exiled.Events/Patches/Events/Map/SpawningTeamVehicle.cs b/EXILED/Exiled.Events/Patches/Events/Map/SpawningTeamVehicle.cs
index 7edd27513..08926e5be 100644
--- a/EXILED/Exiled.Events/Patches/Events/Map/SpawningTeamVehicle.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Map/SpawningTeamVehicle.cs
@@ -21,11 +21,11 @@ namespace Exiled.Events.Patches.Events.Map
using static HarmonyLib.AccessTools;
///
- /// Patches .
+ /// Patches .
/// Adds the event.
///
[EventPatch(typeof(Handlers.Map), nameof(Handlers.Map.SpawningTeamVehicle))]
- [HarmonyPatch(typeof(RespawnEffectsController), nameof(RespawnEffectsController.ExecuteAllEffects))]
+ [HarmonyPatch(typeof(WaveUpdateMessage), nameof(WaveUpdateMessage.ServerSendUpdate))]
internal static class SpawningTeamVehicle
{
private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
@@ -35,28 +35,30 @@ private static IEnumerable Transpiler(IEnumerable x.opcode == OpCodes.Newobj) + offset;
+
+ newInstructions.InsertRange(index, new[]
{
+ new(OpCodes.Stloc_S, msg.LocalIndex),
+
// if (type != RespawnEffectsController.EffectType.Selection)
// goto continueLabel;
- new(OpCodes.Ldarg_0),
- new(OpCodes.Ldc_I4_0),
- new(OpCodes.Ceq),
+ new(OpCodes.Ldloca_S, msg.LocalIndex),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(WaveUpdateMessage), nameof(WaveUpdateMessage.IsTrigger))),
new(OpCodes.Brfalse_S, continueLabel),
- // team
- new(OpCodes.Ldarg_1),
+ // wave
+ new(OpCodes.Ldarg_0),
// true
new(OpCodes.Ldc_I4_1),
- // SpawningTeamVehicleEventArgs ev = new(SpawnableTeamType, bool);
+ // SpawningTeamVehicleEventArgs ev = new(SpawnableWaveBase, bool);
new(OpCodes.Newobj, GetDeclaredConstructors(typeof(SpawningTeamVehicleEventArgs))[0]),
new(OpCodes.Dup),
- new(OpCodes.Dup),
- new(OpCodes.Stloc_S, ev.LocalIndex),
// Handlers.Map.OnSpawningTeamVehicle(ev);
new(OpCodes.Call, Method(typeof(Handlers.Map), nameof(Handlers.Map.OnSpawningTeamVehicle))),
@@ -66,12 +68,7 @@ private static IEnumerable Transpiler(IEnumerable
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Player
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Extensions;
+ using Exiled.API.Features.Pools;
+
+ using Exiled.Events.Attributes;
+
+ using Exiled.Events.EventArgs.Player;
+
+ using Exiled.Events.Handlers;
+
+ using HarmonyLib;
+ using InventorySystem.Items.Firearms.Modules;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches
+ /// to add event.
+ ///
+ [EventPatch(typeof(Player), nameof(Player.AimingDownSight))]
+ [HarmonyPatch(typeof(LinearAdsModule), nameof(LinearAdsModule.ServerProcessCmd))]
+ internal class Aiming
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ LocalBuilder ads = generator.DeclareLocal(typeof(bool));
+
+ int offset = 0;
+ int index = newInstructions.FindIndex(x => x.StoresField(Field(typeof(LinearAdsModule), nameof(LinearAdsModule._userInput)))) + offset;
+
+ newInstructions.InsertRange(
+ index,
+ new[]
+ {
+ // read bool value
+ new CodeInstruction(OpCodes.Stloc_S, ads.LocalIndex),
+
+ // this.Firearm;
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(LinearAdsModule), nameof(LinearAdsModule.Firearm))),
+
+ // userInput
+ new(OpCodes.Ldloc_S, ads.LocalIndex),
+
+ // AimingDownSightEventArgs ev = new(firearm, userInput);
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(AimingDownSightEventArgs))[0]),
+ new(OpCodes.Dup),
+
+ // Handlers.Player.OnAimingDownSight(ev);
+ new(OpCodes.Call, Method(typeof(Player), nameof(Player.OnAimingDownSight))),
+
+ // loads AdsIn
+ new(OpCodes.Callvirt, PropertyGetter(typeof(AimingDownSightEventArgs), nameof(AimingDownSightEventArgs.AdsIn))),
+ });
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/ChangingDisruptorMode.cs b/EXILED/Exiled.Events/Patches/Events/Player/ChangingDisruptorMode.cs
new file mode 100644
index 000000000..37aa6376b
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Player/ChangingDisruptorMode.cs
@@ -0,0 +1,71 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Player
+{
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Items;
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Player;
+ using HarmonyLib;
+ using InventorySystem.Items;
+ using InventorySystem.Items.Firearms.Modules;
+ using Mirror;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches
+ /// to add event.
+ ///
+ [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ChangingDisruptorMode))]
+ [HarmonyPatch(typeof(DisruptorModeSelector), nameof(DisruptorModeSelector.ServerProcessCmd))]
+ internal static class ChangingDisruptorMode
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ int index = newInstructions.FindLastIndex(x => x.opcode == OpCodes.Ldarg_0);
+
+ newInstructions.InsertRange(index, new CodeInstruction[]
+ {
+ // Item.Get(this.Firearm);
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(DisruptorModeSelector), nameof(DisruptorModeSelector.Firearm))),
+ new(OpCodes.Call, GetDeclaredMethods(typeof(Item)).Find(x => !x.IsGenericMethod && x.GetParameters().FirstOrDefault()?.ParameterType == typeof(ItemBase))),
+
+ // reader.ReadBool();
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Call, Method(typeof(NetworkReaderExtensions), nameof(NetworkReaderExtensions.ReadBool))),
+
+ // ChangerDisruptorModeEventArgs ev = new(Item.Get(this.Firearm), reader.ReadBool(), true);
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangingDisruptorModeEventArgs))[0]),
+
+ // Handlers.Player.OnChangingDisruptorMode(ev);
+ new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnChangingDisruptorMode))),
+
+ // reader.Position--;
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Ldfld, Field(typeof(NetworkReader), nameof(NetworkReader.Position))),
+ new(OpCodes.Ldc_I4_M1),
+ new(OpCodes.Add),
+ new(OpCodes.Stfld, Field(typeof(NetworkReader), nameof(NetworkReader.Position))),
+ });
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/ChangingItem.cs b/EXILED/Exiled.Events/Patches/Events/Player/ChangingItem.cs
index 9fa2a4f1b..fa964cad8 100644
--- a/EXILED/Exiled.Events/Patches/Events/Player/ChangingItem.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Player/ChangingItem.cs
@@ -42,8 +42,8 @@ private static IEnumerable Transpiler(IEnumerable instruction.Calls(Method(typeof(EquipDequipModifierExtensions), nameof(EquipDequipModifierExtensions.CanEquip)))) + offset;
+ int index = newInstructions.FindIndex(
+ instruction => instruction.Calls(PropertyGetter(typeof(ItemBase), nameof(ItemBase.AllowEquip)))) + offset;
newInstructions.InsertRange(
index,
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/ChangingMicroHIDState.cs b/EXILED/Exiled.Events/Patches/Events/Player/ChangingMicroHIDState.cs
index f203bf349..c45000b67 100644
--- a/EXILED/Exiled.Events/Patches/Events/Player/ChangingMicroHIDState.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Player/ChangingMicroHIDState.cs
@@ -8,89 +8,72 @@
namespace Exiled.Events.Patches.Events.Player
{
using System.Collections.Generic;
+ using System.Linq;
using System.Reflection.Emit;
- using API.Features;
+ using API.Features.Items;
using API.Features.Pools;
using Exiled.Events.Attributes;
using Exiled.Events.EventArgs.Player;
-
using HarmonyLib;
-
using InventorySystem.Items.MicroHID;
+ using InventorySystem.Items.MicroHID.Modules;
using static HarmonyLib.AccessTools;
///
- /// Patches .
+ /// Patches .
/// Adds the event.
///
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ChangingMicroHIDState))]
- [HarmonyPatch(typeof(MicroHIDItem), nameof(MicroHIDItem.ExecuteServerside))]
+ [HarmonyPatch(typeof(CycleController), nameof(CycleController.Phase), MethodType.Setter)]
internal static class ChangingMicroHIDState
{
private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
{
List newInstructions = ListPool.Pool.Get(instructions);
- Label skipLabel = generator.DefineLabel();
- Label continueLabel = generator.DefineLabel();
+ Label returnLabel = generator.DefineLabel();
LocalBuilder ev = generator.DeclareLocal(typeof(ChangingMicroHIDStateEventArgs));
- List instructionsToAdd = new()
- {
- // Player.Get(this.Owner);
- new CodeInstruction(OpCodes.Ldarg_0),
- new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(MicroHIDItem), nameof(MicroHIDItem.Owner))),
- new CodeInstruction(OpCodes.Call, Method(typeof(Player), nameof(Player.Get), new[] { typeof(ReferenceHub) })),
-
- // this
- new CodeInstruction(OpCodes.Ldarg_0),
+ int offset = 1;
+ int index = newInstructions.FindIndex(x => x.opcode == OpCodes.Ret) + offset;
- // state
- new CodeInstruction(OpCodes.Ldloc_0),
+ newInstructions.InsertRange(index, new[]
+ {
+ // Item.Get(this.Serial);
+ new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(newInstructions[index]),
+ new(OpCodes.Ldfld, Field(typeof(CycleController), nameof(CycleController.Serial))),
+ new(OpCodes.Call, GetDeclaredMethods(typeof(Item)).Find(x => !x.IsGenericMethod && x.IsStatic && x.GetParameters().FirstOrDefault()?.ParameterType == typeof(ushort))),
- // this.State
- new CodeInstruction(OpCodes.Ldarg_0),
- new CodeInstruction(OpCodes.Ldfld, Field(typeof(MicroHIDItem), nameof(MicroHIDItem.State))),
+ // value
+ new(OpCodes.Ldarg_1),
// true
- new CodeInstruction(OpCodes.Ldc_I4_1),
+ new(OpCodes.Ldc_I4_1),
- // ChangingMicroHIDStateEventArgs ev = new(Player, MicroHIDItem, HidState, HidState, bool)
- new CodeInstruction(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangingMicroHIDStateEventArgs))[0]),
- new CodeInstruction(OpCodes.Dup),
- new CodeInstruction(OpCodes.Dup),
- new CodeInstruction(OpCodes.Stloc_S, ev.LocalIndex),
+ // ChangerMicroHIDStateEventArgs ev = new(Item.Get(this.Serial), value, true);
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangingMicroHIDStateEventArgs))[0]),
+ new(OpCodes.Dup),
+ new(OpCodes.Dup),
+ new(OpCodes.Stloc_S, ev.LocalIndex),
// Handlers.Player.OnChangingMicroHIDState(ev);
- new CodeInstruction(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnChangingMicroHIDState))),
+ new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnChangingMicroHIDState))),
// if (!ev.IsAllowed)
- // goto skipLabel;
- new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(ChangingMicroHIDStateEventArgs), nameof(ChangingMicroHIDStateEventArgs.IsAllowed))),
- new CodeInstruction(OpCodes.Brfalse_S, skipLabel),
-
- // this.State = ev.NewState
- new CodeInstruction(OpCodes.Ldarg_0),
- new CodeInstruction(OpCodes.Ldloc_S, ev.LocalIndex),
- new CodeInstruction(OpCodes.Callvirt, PropertyGetter(typeof(ChangingMicroHIDStateEventArgs), nameof(ChangingMicroHIDStateEventArgs.NewState))),
- new CodeInstruction(OpCodes.Stfld, Field(typeof(MicroHIDItem), nameof(MicroHIDItem.State))),
- new CodeInstruction(OpCodes.Br, continueLabel),
-
- // this.State = state;
- new CodeInstruction(OpCodes.Ldarg_0).WithLabels(skipLabel),
- new CodeInstruction(OpCodes.Ldloc_0),
- new CodeInstruction(OpCodes.Stfld, Field(typeof(MicroHIDItem), nameof(MicroHIDItem.State))),
+ // return;
+ new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingMicroHIDStateEventArgs), nameof(ChangingMicroHIDStateEventArgs.IsAllowed))),
+ new(OpCodes.Brfalse_S, returnLabel),
- new CodeInstruction(OpCodes.Nop).WithLabels(continueLabel),
- };
-
- int offset = 1;
+ // value = ev.NewPhase;
+ new(OpCodes.Ldloc_S, ev.LocalIndex),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingMicroHIDStateEventArgs), nameof(ChangingMicroHIDStateEventArgs.NewPhase))),
+ new(OpCodes.Starg_S, 1),
+ });
- foreach (CodeInstruction instruction in newInstructions.FindAll(i => i.StoresField(Field(typeof(MicroHIDItem), nameof(MicroHIDItem.State)))))
- newInstructions.InsertRange(newInstructions.IndexOf(instruction) + offset, instructionsToAdd);
+ newInstructions[newInstructions.Count - 1].labels.Add(returnLabel);
for (int z = 0; z < newInstructions.Count; z++)
yield return newInstructions[z];
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/ChangingMoveState.cs b/EXILED/Exiled.Events/Patches/Events/Player/ChangingMoveState.cs
index b65d6e5c9..5c9879f7c 100644
--- a/EXILED/Exiled.Events/Patches/Events/Player/ChangingMoveState.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Player/ChangingMoveState.cs
@@ -58,10 +58,7 @@ private static IEnumerable Transpiler(IEnumerable Transpiler(IEnumerable list = new();
+ List list = new List();
if (inventory.TryGetBodyArmor(out BodyArmor bodyArmor))
bodyArmor.DontRemoveExcessOnDrop = true;
- while (inventory.UserInventory.Items.Count > 0)
+ HashSet hashSet = HashSetPool.Pool.Get();
+ foreach (KeyValuePair item2 in inventory.UserInventory.Items)
{
- int startCount = inventory.UserInventory.Items.Count;
- ushort key = inventory.UserInventory.Items.ElementAt(0).Key;
- ItemPickupBase item = inventory.ServerDropItem(key);
-
- // If the list wasn't changed, we need to manually remove the item to avoid a softlock.
- if (startCount == inventory.UserInventory.Items.Count)
- inventory.UserInventory.Items.Remove(key);
+ if (item2.Value is Scp1344Item scp1344Item)
+ scp1344Item.Status = Scp1344Status.Idle;
else
- list.Add(item);
+ hashSet.Add(item2.Key);
}
+ foreach (ushort item in hashSet)
+ list.Add(inventory.ServerDropItem(item));
+
+ HashSetPool.Pool.Return(hashSet);
InventoryItemProvider.PreviousInventoryPickups[ev.Player.ReferenceHub] = list;
}
else
{
while (inventory.UserInventory.Items.Count > 0)
- {
- int startCount = inventory.UserInventory.Items.Count;
- ushort key = inventory.UserInventory.Items.ElementAt(0).Key;
- inventory.ServerRemoveItem(key, null);
-
- // If the list wasn't changed, we need to manually remove the item to avoid a softlock.
- if (startCount == inventory.UserInventory.Items.Count)
- inventory.UserInventory.Items.Remove(key);
- }
+ inventory.ServerRemoveItem(inventory.UserInventory.Items.ElementAt(0).Key, null);
inventory.UserInventory.ReserveAmmo.Clear();
inventory.SendAmmoNextFrame = true;
}
- foreach (ItemType item in ev.Items)
- inventory.ServerAddItem(item);
+ if (!StartingInventories.DefinedInventories.TryGetValue(ev.NewRole, out InventoryRoleInfo value))
+ return;
- foreach (KeyValuePair keyValuePair in ev.Ammo)
- inventory.ServerAddAmmo(keyValuePair.Key, keyValuePair.Value);
+ foreach (KeyValuePair item in value.Ammo)
+ inventory.ServerAddAmmo(item.Key, item.Value);
- foreach (KeyValuePair item in inventory.UserInventory.Items)
- InventoryItemProvider.OnItemProvided?.Invoke(ev.Player.ReferenceHub, item.Value);
+ for (int i = 0; i < value.Items.Length; i++)
+ {
+ ItemBase arg = inventory.ServerAddItem(value.Items[i], ItemAddReason.StartingItem, 0);
+ InventoryItemProvider.OnItemProvided?.Invoke(ev.Player.ReferenceHub, arg);
+ }
- InventoryItemProvider.SpawnPreviousInventoryPickups(ev.Player.ReferenceHub);
+ InventoryItemProvider.InventoriesToReplenish.Enqueue(ev.Player.ReferenceHub);
}
catch (Exception exception)
{
@@ -254,4 +240,4 @@ private static void ChangeInventory(ChangingRoleEventArgs ev)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/DamagingDoor.cs b/EXILED/Exiled.Events/Patches/Events/Player/DamagingDoor.cs
index 2d8d52176..2f5135a56 100644
--- a/EXILED/Exiled.Events/Patches/Events/Player/DamagingDoor.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Player/DamagingDoor.cs
@@ -24,7 +24,7 @@ namespace Exiled.Events.Patches.Events.Player
using static HarmonyLib.AccessTools;
///
- /// Patch the .
+ /// Patch the .
/// Adds the event.
///
[EventPatch(typeof(Player), nameof(Player.DamagingDoor))]
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/DamagingWindow.cs b/EXILED/Exiled.Events/Patches/Events/Player/DamagingWindow.cs
index df26d055b..097127383 100644
--- a/EXILED/Exiled.Events/Patches/Events/Player/DamagingWindow.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Player/DamagingWindow.cs
@@ -25,9 +25,9 @@ namespace Exiled.Events.Patches.Events.Player
///
/// Patch the .
- /// Adds the event.
+ /// Adds the event.
///
- [EventPatch(typeof(Player), nameof(Player.PlayerDamageWindow))]
+ [EventPatch(typeof(Player), nameof(Player.DamagingWindow))]
[HarmonyPatch(typeof(BreakableWindow), nameof(BreakableWindow.Damage))]
internal static class DamagingWindow
{
@@ -62,7 +62,7 @@ private static IEnumerable Transpiler(IEnumerable
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Player
+{
+#pragma warning disable SA1402
+#pragma warning disable SA1600
+#pragma warning disable SA1649
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Reflection;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Extensions;
+ using Exiled.API.Features.Pools;
+
+ using Exiled.Events.Attributes;
+
+ using Exiled.Events.EventArgs.Player;
+
+ using Exiled.Events.Handlers;
+
+ using HarmonyLib;
+
+ using InventorySystem.Items.Firearms;
+ using InventorySystem.Items.Firearms.Modules;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches
+ /// to add event for automatic firearms.
+ ///
+ [EventPatch(typeof(Player), nameof(Player.DryfiringWeapon))]
+ [HarmonyPatch(typeof(AutomaticActionModule), nameof(AutomaticActionModule.UpdateServer))]
+ internal class DryFireAutomatic
+ {
+ internal static IEnumerable GetInstructions(CodeInstruction start, Label ret)
+ {
+ // this.Firearm
+ yield return new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(start);
+ yield return new(OpCodes.Callvirt, PropertyGetter(typeof(FirearmSubcomponentBase), nameof(FirearmSubcomponentBase.Firearm)));
+
+ // DryfiringWeaponEventArgs ev = new(firearm);
+ yield return new(OpCodes.Newobj, GetDeclaredConstructors(typeof(DryfiringWeaponEventArgs))[0]);
+ yield return new(OpCodes.Dup);
+
+ // Handlers.Player.OnDryfiringWeapon(ev);
+ yield return new(OpCodes.Call, Method(typeof(Player), nameof(Player.OnDryfiringWeapon)));
+
+ // if (!ev.IsAllowed)
+ // return;
+ yield return new(OpCodes.Callvirt, PropertyGetter(typeof(DryfiringWeaponEventArgs), nameof(DryfiringWeaponEventArgs.IsAllowed)));
+ yield return new(OpCodes.Brfalse_S, ret);
+ }
+
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ // for returning we will goto ServerSendResponse method, it is necessarily
+ int offset = -3;
+ Label ret = newInstructions[newInstructions.Count - 1 + offset].labels[0];
+
+ offset = -2;
+ int index = newInstructions.FindIndex(x => x.Calls(PropertyGetter(typeof(AutomaticActionModule), nameof(AutomaticActionModule.Cocked)))) + offset;
+
+ newInstructions.InsertRange(index, GetInstructions(newInstructions[index], ret));
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+
+ ///
+ /// Patches
+ /// to add event for double shots.
+ ///
+ [EventPatch(typeof(Player), nameof(Player.DryfiringWeapon))]
+ [HarmonyPatch(typeof(DoubleActionModule), nameof(DoubleActionModule.FireDry))]
+ internal class DryFireDouble
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label ret = generator.DefineLabel();
+
+ newInstructions.InsertRange(0, DryFireAutomatic.GetInstructions(newInstructions[0], ret));
+
+ newInstructions[newInstructions.Count - 1].labels.Add(ret);
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+
+ ///
+ /// Patches
+ /// to add event for double shots.
+ ///
+ [EventPatch(typeof(Player), nameof(Player.DryfiringWeapon))]
+ [HarmonyPatch(typeof(PumpActionModule), nameof(PumpActionModule.ShootOneBarrel))]
+ internal class DryFirePump
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label ret = generator.DefineLabel();
+
+ int offset = -7;
+ int index = newInstructions.FindIndex(i => i.opcode == OpCodes.Stloc_1) + offset;
+
+ // firstly, set `flag` to a false, and then if `IsAllowed == false` we could return without problems
+ newInstructions.InsertRange(index, new CodeInstruction[]
+ {
+ new CodeInstruction(OpCodes.Ldc_I4_0),
+ new(OpCodes.Stloc_1),
+ }.Concat(DryFireAutomatic.GetInstructions(newInstructions[0], ret)));
+
+ // place return label to a ldloc instruction, to return `flag` variables
+ newInstructions[newInstructions.Count - 2].labels.Add(ret);
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
\ No newline at end of file
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/Emotion.cs b/EXILED/Exiled.Events/Patches/Events/Player/Emotion.cs
new file mode 100644
index 000000000..a7d447569
--- /dev/null
+++ b/EXILED/Exiled.Events/Patches/Events/Player/Emotion.cs
@@ -0,0 +1,87 @@
+// -----------------------------------------------------------------------
+//
+// Copyright (c) ExMod Team. All rights reserved.
+// Licensed under the CC BY-SA 3.0 license.
+//
+// -----------------------------------------------------------------------
+
+namespace Exiled.Events.Patches.Events.Player
+{
+ using System.Collections.Generic;
+ using System.Reflection.Emit;
+
+ using Exiled.API.Features.Pools;
+ using Exiled.Events.Attributes;
+ using Exiled.Events.EventArgs.Player;
+ using HarmonyLib;
+ using PlayerRoles.FirstPersonControl.Thirdperson.Subcontrollers;
+
+ using static HarmonyLib.AccessTools;
+
+ ///
+ /// Patches .
+ /// Adds the event and
+ /// event.
+ ///
+ [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ChangingEmotion))]
+ [EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.ChangedEmotion))]
+ [HarmonyPatch(typeof(EmotionSync), nameof(EmotionSync.ServerSetEmotionPreset))]
+ internal static class Emotion
+ {
+ private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
+ {
+ List newInstructions = ListPool.Pool.Get(instructions);
+
+ Label ret = generator.DefineLabel();
+ LocalBuilder ev = generator.DeclareLocal(typeof(ChangingEmotionEventArgs));
+
+ int index = newInstructions.FindIndex(x => x.opcode == OpCodes.Ldsfld);
+
+ newInstructions.InsertRange(index, new CodeInstruction[]
+ {
+ // ChangingEmotionEventArgs ev = new(hub, preset, EmotionSync.GetEmotionPreset(hub), true);
+ new CodeInstruction(OpCodes.Ldarg_0).MoveLabelsFrom(newInstructions[index]),
+ new(OpCodes.Ldarg_1),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Call, Method(typeof(EmotionSync), nameof(EmotionSync.GetEmotionPreset))),
+ new(OpCodes.Ldc_I4_1),
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangingEmotionEventArgs))[0]),
+ new(OpCodes.Dup),
+ new(OpCodes.Dup),
+ new(OpCodes.Stloc_S, ev),
+
+ // Handlers.Player.OnChangingEmotion(ev);
+ new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnChangingEmotion))),
+
+ // if (!ev.IsAllowed)
+ // return;
+ new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingEmotionEventArgs), nameof(ChangingEmotionEventArgs.IsAllowed))),
+ new(OpCodes.Brfalse, ret),
+
+ // preset = ev.EmotionPresetTypeNew
+ new(OpCodes.Ldloc_S, ev),
+ new(OpCodes.Callvirt, PropertyGetter(typeof(ChangingEmotionEventArgs), nameof(ChangingEmotionEventArgs.NewEmotionPresetType))),
+ new(OpCodes.Starg_S, 1),
+ });
+
+ newInstructions.InsertRange(newInstructions.Count - 1, new CodeInstruction[]
+ {
+ // ChangedEmotionEventArgs ev = new(hub, EmotionSync.GetEmotionPreset(hub));
+ new CodeInstruction(OpCodes.Ldarg_0),
+ new(OpCodes.Ldarg_0),
+ new(OpCodes.Call, Method(typeof(EmotionSync), nameof(EmotionSync.GetEmotionPreset))),
+ new(OpCodes.Newobj, GetDeclaredConstructors(typeof(ChangedEmotionEventArgs))[0]),
+
+ // Handlers.Player.OnChangedEmotion(ev);
+ new(OpCodes.Call, Method(typeof(Handlers.Player), nameof(Handlers.Player.OnChangedEmotion))),
+ });
+
+ newInstructions[newInstructions.Count - 1].labels.Add(ret);
+
+ for (int z = 0; z < newInstructions.Count; z++)
+ yield return newInstructions[z];
+
+ ListPool.Pool.Return(newInstructions);
+ }
+ }
+}
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/EnteringKillerCollision.cs b/EXILED/Exiled.Events/Patches/Events/Player/EnteringKillerCollision.cs
index 9ecb86df8..59259d210 100644
--- a/EXILED/Exiled.Events/Patches/Events/Player/EnteringKillerCollision.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Player/EnteringKillerCollision.cs
@@ -19,11 +19,11 @@ namespace Exiled.Events.Patches.Events.Player
using static HarmonyLib.AccessTools;
///
- /// Patches .
+ /// Patches .
/// Adds the event.
///
[EventPatch(typeof(Handlers.Player), nameof(Handlers.Player.EnteringKillerCollision))]
- [HarmonyPatch(typeof(CheckpointKiller), nameof(CheckpointKiller.OnTriggerEnter))]
+ [HarmonyPatch(typeof(PitKiller), nameof(PitKiller.OnTriggerEnter))]
internal static class EnteringKillerCollision
{
private static IEnumerable Transpiler(IEnumerable instructions, ILGenerator generator)
@@ -32,8 +32,7 @@ private static IEnumerable Transpiler(IEnumerable instruction.opcode == OpCodes.Newobj) + offset;
+ int index = newInstructions.FindLastIndex(instruction => instruction.opcode == OpCodes.Ldarg_0);
newInstructions.InsertRange(
index,
diff --git a/EXILED/Exiled.Events/Patches/Events/Player/EscapingAndEscaped.cs b/EXILED/Exiled.Events/Patches/Events/Player/EscapingAndEscaped.cs
index 9bf3bb35f..c078ac2dc 100644
--- a/EXILED/Exiled.Events/Patches/Events/Player/EscapingAndEscaped.cs
+++ b/EXILED/Exiled.Events/Patches/Events/Player/EscapingAndEscaped.cs
@@ -10,10 +10,7 @@ namespace Exiled.Events.Patches.Events.Player
#pragma warning disable SA1402 // File may only contain a single type
#pragma warning disable IDE0060
- using System;
using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
using System.Reflection.Emit;
using API.Enums;
@@ -24,7 +21,6 @@ namespace Exiled.Events.Patches.Events.Player
using Exiled.Events.Attributes;
using HarmonyLib;
using PlayerRoles.FirstPersonControl;
- using Respawning;
using static HarmonyLib.AccessTools;
@@ -40,7 +36,6 @@ private static IEnumerable Transpiler(IEnumerable newInstructions = ListPool.Pool.Get(instructions);
- List