This commit is contained in:
Oscar 2025-06-28 18:13:47 +03:00
parent 875d594038
commit 23a35fe3cd
23 changed files with 2579 additions and 607 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

24
Assets/Items/rifle.ammo Normal file
View File

@ -0,0 +1,24 @@
{
"AmmoType": "Rifle",
"Damage": 20,
"Penetration": 0,
"IsExplosive": false,
"ExplosionRadius": 0,
"CompatibleWeapons": "",
"Category": "Ammo",
"Name": "Rifle Ammo",
"Description": "",
"Prefab": {
"_type": "gameobject",
"prefab": "prefabs/weapon/rifle_ammo.prefab"
},
"ImageTexture": null,
"ImageUrl": null,
"MaxCount": 256,
"Rarity": "Common",
"Weight": 1,
"IsStackable": true,
"IsEquipable": false,
"__references": [],
"__version": 0
}

33
Assets/Items/rifle.weapon Normal file
View File

@ -0,0 +1,33 @@
{
"Slot": "RightHand",
"HoldType": "Rifle",
"WeaponDefinition": {
"Position": "0,0,0",
"Rotation": "0,0,0,0",
"Scale": "0,0,0"
},
"Damage": 20,
"FireRate": 14,
"Range": 1000,
"MagazineSize": 40,
"AmmoType": "Rifle",
"ReloadTime": 2,
"Spread": 0.02,
"IsAutomatic": true,
"Category": "Weapon",
"Name": "Rifle",
"Description": "Rifle test",
"Prefab": {
"_type": "gameobject",
"prefab": "prefabs/weapon/rifle.prefab"
},
"ImageTexture": null,
"ImageUrl": null,
"MaxCount": 1,
"Rarity": "Common",
"Weight": 1,
"IsStackable": false,
"IsEquipable": true,
"__references": [],
"__version": 0
}

View File

@ -118,10 +118,7 @@
},
"DuckSpeed": 100,
"InteractDistance": 350,
"Inventory": {
"Items": [],
"EquippedItems": {}
},
"Inventory": null,
"InventoryUI": {
"_type": "gameobject",
"go": "f421a41f-0db1-40fe-8694-8fc5109ed8ed"
@ -2053,8 +2050,8 @@
"__version": 1,
"Flags": 8,
"Name": "ankle_R",
"Position": "0.4100258,-4.377087,3.80752",
"Rotation": "0.672856,0.2185197,-0.3316687,0.6241072",
"Position": "0.4100087,-4.377703,3.807678",
"Rotation": "0.6728455,0.2185408,-0.3316475,0.6241224",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
@ -2070,9 +2067,9 @@
"__version": 1,
"Flags": 8,
"Name": "ankle_L",
"Position": "0.4083739,4.427568,3.805843",
"Rotation": "0.624587,0.3321075,-0.2183182,0.6722596",
"Scale": "1.000001,1.000001,1.000001",
"Position": "0.4083801,4.427946,3.805992",
"Rotation": "0.6245957,0.3320946,-0.2183304,0.6722538",
"Scale": "1,1,1",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2087,9 +2084,9 @@
"__version": 1,
"Flags": 8,
"Name": "arm_lower_R",
"Position": "-2.248101,-8.62746,41.00563",
"Rotation": "0.5017254,0.3809418,-0.5422131,0.5560213",
"Scale": "1.000003,1.000003,1.000003",
"Position": "-1.944306,-9.198144,41.10852",
"Rotation": "0.4837707,0.4009385,-0.5580629,0.542015",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2104,8 +2101,8 @@
"__version": 1,
"Flags": 8,
"Name": "arm_lower_L",
"Position": "-1.88412,9.84506,41.47677",
"Rotation": "0.5825445,0.5398754,-0.372816,0.4797757",
"Position": "-1.786701,8.974261,41.26266",
"Rotation": "0.5538174,0.5558982,-0.3962672,0.4766927",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
"Enabled": true,
@ -2121,9 +2118,9 @@
"__version": 1,
"Flags": 8,
"Name": "hand_R",
"Position": "-1.309633,-10.32845,33.54772",
"Rotation": "0.4728318,0.3592023,-0.5989242,0.5373023",
"Scale": "1.000004,1.000004,1.000004",
"Position": "-1.515604,-10.87078,33.59772",
"Rotation": "0.4529333,0.3786638,-0.6138031,0.5241288",
"Scale": "1.000005,1.000005,1.000005",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2138,8 +2135,8 @@
"__version": 1,
"Flags": 8,
"Name": "hand_L",
"Position": "-0.8122468,11.93556,34.13684",
"Rotation": "0.564046,0.596406,-0.3489397,0.4520986",
"Position": "-1.263442,10.80791,33.7956",
"Rotation": "0.5359527,0.6116646,-0.3731866,0.4464895",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
"Enabled": true,
@ -2155,9 +2152,9 @@
"__version": 1,
"Flags": 8,
"Name": "hold_R",
"Position": "0.04548915,-8.87489,27.48961",
"Rotation": "0.3158478,0.7257434,0.06756637,0.6074303",
"Scale": "1.000005,1.000005,1.000005",
"Position": "-0.5782236,-9.393594,27.46674",
"Rotation": "0.3187549,0.7460795,0.05836753,0.581682",
"Scale": "1.000006,1.000006,1.000006",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2172,8 +2169,8 @@
"__version": 1,
"Flags": 8,
"Name": "hold_L",
"Position": "0.5382646,10.78157,28.01336",
"Rotation": "-0.2832639,0.7311895,-0.05981389,0.6176938",
"Position": "-0.2961033,9.453352,27.64081",
"Rotation": "-0.305681,0.7467785,-0.05618108,0.5879837",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
"Enabled": true,
@ -2207,7 +2204,7 @@
"Flags": 8,
"Name": "IK_left_hand",
"Position": "-1.501041,11.36666,33.23686",
"Rotation": "0.5482481,0.6048241,-0.3533374,0.4569075",
"Rotation": "0.5482481,0.6048241,-0.3533375,0.4569075",
"Scale": "1,1,1",
"Tags": "",
"Enabled": true,
@ -2223,9 +2220,9 @@
"__version": 1,
"Flags": 8,
"Name": "leg_lower_R",
"Position": "2.155842,-4.43963,16.20059",
"Rotation": "0.491346,0.5029026,-0.5628809,0.4345495",
"Scale": "1,1,1",
"Position": "3.235427,-4.608579,15.99795",
"Rotation": "0.4655335,0.530396,-0.5758093,0.4127981",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2240,9 +2237,9 @@
"__version": 1,
"Flags": 8,
"Name": "leg_lower_L",
"Position": "3.027968,4.837151,16.03734",
"Rotation": "0.4127347,0.5692022,-0.5297762,0.4743376",
"Scale": "1,1,1",
"Position": "2.338159,4.713587,16.16856",
"Rotation": "0.4252933,0.5630658,-0.5099532,0.4919657",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2257,8 +2254,8 @@
"__version": 1,
"Flags": 8,
"Name": "middle_of_both_hands",
"Position": "-0.8828036,0.9401312,29.01773",
"Rotation": "0.01912965,0.7545437,0.003921955,0.6559592",
"Position": "-1.561194,0.02484846,28.83653",
"Rotation": "0.007330432,0.7686383,0.001971816,0.6396385",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
"Enabled": true,
@ -2274,9 +2271,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_arm_upper_R_twist1",
"Position": "-1.32694,-7.710932,45.85728",
"Position": "-0.9131499,-8.264956,45.93478",
"Rotation": "0,0,0,1",
"Scale": "1.000003,1.000003,1.000003",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2291,9 +2288,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_arm_lower_R_twist1",
"Position": "-1.778867,-9.477953,37.27668",
"Position": "-1.729955,-10.03446,37.35312",
"Rotation": "0,0,0,1",
"Scale": "1.000003,1.000003,1.000003",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2308,9 +2305,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_elbow_R_position",
"Position": "-2.251795,-8.630569,41.00162",
"Rotation": "-0.02769216,-0.6303626,0.7755523,0.01986925",
"Scale": "1.000003,1.000003,1.000003",
"Position": "-1.904696,-9.206528,41.10199",
"Rotation": "-0.007202899,-0.6295701,0.7761958,0.03331204",
"Scale": "1.000005,1.000005,1.000005",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2325,9 +2322,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_elbow_L_position",
"Position": "-1.887652,9.848536,41.47289",
"Rotation": "-0.04448023,0.791288,-0.6053749,0.07352691",
"Scale": "1.000003,1.000003,1.000003",
"Position": "-1.746899,8.982116,41.25662",
"Rotation": "-0.06745388,0.780771,-0.6183518,0.05905678",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2342,7 +2339,7 @@
"__version": 1,
"Flags": 8,
"Name": "driver_arm_upper_L_twist1",
"Position": "-1.043476,8.613153,46.27288",
"Position": "-0.8141831,7.915582,46.07516",
"Rotation": "0,0,0,1",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
@ -2359,7 +2356,7 @@
"__version": 1,
"Flags": 8,
"Name": "driver_arm_lower_L_twist1",
"Position": "-1.348183,10.89031,37.80681",
"Position": "-1.525071,9.891087,37.52913",
"Rotation": "0,0,0,1",
"Scale": "1.000004,1.000004,1.000004",
"Tags": "",
@ -2376,9 +2373,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_leg_upper_R_twist1",
"Position": "1.394789,-4.274455,23.39375",
"Position": "1.935349,-4.430572,23.11317",
"Rotation": "0,0,0,1",
"Scale": "1,1,1",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2393,9 +2390,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_leg_upper_L_twist1",
"Position": "1.860858,4.789178,23.17761",
"Position": "1.490429,4.655171,23.35368",
"Rotation": "0,0,0,1",
"Scale": "1,1,1",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2410,9 +2407,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_kneecap_R_position",
"Position": "2.51964,-4.481263,16.17043",
"Rotation": "0.5185956,0.4738925,-0.533102,0.4714729",
"Scale": "1,1,1",
"Position": "3.838389,-4.672735,15.96004",
"Rotation": "0.5150546,0.4793396,-0.5310991,0.4721081",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2427,9 +2424,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_kneecap_L_position",
"Position": "3.579065,4.895428,15.99909",
"Rotation": "0.7002168,0.0440556,0.02651213,0.7120762",
"Scale": "1,1,1",
"Position": "2.741635,4.759412,16.13647",
"Rotation": "0.7031127,0.0449258,0.03150867,0.7089581",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2444,9 +2441,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_leg_lower_R_twist1",
"Position": "1.282935,-4.408351,10.00407",
"Position": "1.822711,-4.493139,9.902801",
"Rotation": "0,0,0,1",
"Scale": "1.000001,1.000001,1.000001",
"Scale": "1.000002,1.000002,1.000002",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2461,9 +2458,9 @@
"__version": 1,
"Flags": 8,
"Name": "driver_leg_lower_L_twist1",
"Position": "1.718169,4.632352,9.9216",
"Position": "1.373267,4.570763,9.987267",
"Rotation": "0,0,0,1",
"Scale": "1,1,1",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2478,7 +2475,7 @@
"__version": 1,
"Flags": 8,
"Name": "forward_reference_modelspace",
"Position": "-0.2026396,0.2526463,43.41861",
"Position": "0.07471489,-0.05039266,43.35883",
"Rotation": "0,0,0,1",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
@ -2495,8 +2492,8 @@
"__version": 1,
"Flags": 8,
"Name": "eyes",
"Position": "6.016993,-0.1828848,63.23574",
"Rotation": "0.01225863,-0.01333019,-0.01481459,0.9997262",
"Position": "6.744137,-0.4365017,63.04519",
"Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
"Enabled": true,
@ -2512,8 +2509,8 @@
"__version": 1,
"Flags": 8,
"Name": "eye_R_forward",
"Position": "5.91896,-3.526865,63.1524",
"Rotation": "0.01225863,-0.01333019,-0.01481459,0.9997262",
"Position": "6.684545,-3.782319,63.01836",
"Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
"Enabled": true,
@ -2529,8 +2526,8 @@
"__version": 1,
"Flags": 8,
"Name": "eye_L_forward",
"Position": "6.115024,3.161095,63.3191",
"Rotation": "0.01225863,-0.01333019,-0.01481459,0.9997262",
"Position": "6.803728,2.909316,63.07203",
"Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
"Enabled": true,
@ -2546,8 +2543,8 @@
"__version": 1,
"Flags": 8,
"Name": "forward_reference",
"Position": "0.8923788,0.1424403,56.21077",
"Rotation": "0.01225863,-0.01333019,-0.01481459,0.9997262",
"Position": "1.469969,-0.2870641,56.12576",
"Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
"Enabled": true,
@ -2563,9 +2560,9 @@
"__version": 1,
"Flags": 8,
"Name": "foot_R",
"Position": "1.982161,-4.910443,0.1893465",
"Rotation": "0.0004871786,-0.00001364574,-0.0871154,0.9961981",
"Scale": "1,1,1",
"Position": "1.98215,-4.910992,0.1894621",
"Rotation": "0.0004820525,-0.00001450255,-0.08708134,0.9962011",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
@ -2580,8 +2577,8 @@
"__version": 1,
"Flags": 8,
"Name": "foot_L",
"Position": "1.978681,4.966858,1.053351",
"Rotation": "-0.08723652,0.9961876,0.0004068614,0.00001396679",
"Position": "1.978714,4.967169,1.053503",
"Rotation": "-0.08721654,0.9961893,0.0004095733,0.00001492791",
"Scale": "1.000001,1.000001,1.000001",
"Tags": "",
"Enabled": true,
@ -2597,8 +2594,8 @@
"__version": 1,
"Flags": 8,
"Name": "hat",
"Position": "0.7779539,-0.2314876,71.36609",
"Rotation": "0.01225863,-0.01333019,-0.01481459,0.9997262",
"Position": "1.677502,-0.4118944,71.28418",
"Rotation": "0.003984303,-0.002858207,-0.008915529,0.9999482",
"Scale": "1.000003,1.000003,1.000003",
"Tags": "",
"Enabled": true,

View File

@ -107,38 +107,6 @@
},
"Volume": 1
},
{
"__type": "Sandbox.Weapons.Weapon",
"__guid": "fc38d078-995b-443a-b409-e877618fcf09",
"__enabled": true,
"bloodParticle": {
"_type": "gameobject",
"prefab": "prefabs/impacts/impact.flesh.mist.prefab"
},
"Cooldown": 0.5,
"Equipped": false,
"GunRenderer": {
"_type": "component",
"component_id": "6017d24d-39d0-4acf-bf9f-010c345fd13d",
"go": "dec3b7f3-79ae-4bb4-b868-8de9d0306ebb",
"component_type": "SkinnedModelRenderer"
},
"MuzzleLight": {
"_type": "gameobject",
"go": "eda01dbe-7e56-4e66-af99-673e197e7dc0"
},
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"particlePrefab": {
"_type": "gameobject",
"prefab": "prefabs/impacts/impact.metal.prefab"
},
"WeaponDefinition": "items/pistol_test.weapon"
},
{
"__type": "Sasalka.PickupItem",
"__guid": "7350112e-dea3-4c22-b9fc-76eaed3d2e57",
@ -152,19 +120,6 @@
"OnComponentUpdate": null,
"RequiresHold": false
},
{
"__type": "Sasalka.InventoryItem",
"__guid": "ce60c131-01f0-4aa3-a84c-c93eac1d1c2d",
"__enabled": true,
"Count": 1,
"Definition": "items/pistol_test.weapon",
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null
},
{
"__type": "Sandbox.BoxCollider",
"__guid": "8a705640-2966-489e-a41a-2bf6f2cc62f0",
@ -214,6 +169,41 @@
"OverrideMassCenter": false,
"RigidbodyFlags": 0,
"StartAsleep": false
},
{
"__type": "Sandbox.Weapons.BaseWeapon",
"__guid": "b5ffb918-23a1-419f-a24f-fc29537de2fc",
"__enabled": true,
"BloodParticle": {
"_type": "gameobject",
"prefab": "prefabs/impacts/impact.flesh.mist.prefab"
},
"Count": 1,
"Definition": "items/pistol_test.weapon",
"EjectShellPrefab": null,
"EjectTransform": null,
"GunRenderer": {
"_type": "component",
"component_id": "6017d24d-39d0-4acf-bf9f-010c345fd13d",
"go": "dec3b7f3-79ae-4bb4-b868-8de9d0306ebb",
"component_type": "SkinnedModelRenderer"
},
"MuzzleFlashPrefab": null,
"MuzzleLight": {
"_type": "gameobject",
"go": "eda01dbe-7e56-4e66-af99-673e197e7dc0"
},
"MuzzleTransform": null,
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"ParticlePrefab": {
"_type": "gameobject",
"prefab": "prefabs/impacts/impact.metal.prefab"
}
}
],
"Children": [
@ -269,126 +259,6 @@
"Components": [],
"Children": []
},
{
"__guid": "47bb3ba1-b0de-4af4-b639-235a5ad2c312",
"__version": 1,
"Flags": 0,
"Name": "Laser2",
"Position": "11.14736,-0.2659489,3.71905",
"Rotation": "0,0,0,1",
"Scale": "1,0.1,0.1",
"Tags": "",
"Enabled": false,
"NetworkMode": 2,
"NetworkInterpolation": true,
"NetworkOrphaned": 0,
"OwnerTransfer": 1,
"Components": [
{
"__type": "Sandbox.SkinnedModelRenderer",
"__guid": "862e0738-e57f-456a-b0c8-ff03a165faf9",
"__enabled": true,
"AnimationGraph": null,
"BodyGroups": 18446744073709551615,
"BoneMergeTarget": null,
"CreateAttachments": false,
"CreateBoneObjects": false,
"MaterialGroup": null,
"MaterialOverride": "materials/pistol/glow_2.vmat",
"Model": "lasermesh.vmdl",
"Morphs": {},
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"Parameters": {
"bools": {},
"ints": {},
"floats": {},
"vectors": {},
"rotations": {}
},
"PlaybackRate": 1,
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Sequence": {
"Name": null,
"Looping": true,
"Blending": false
},
"Tint": "1,1,1,1",
"UseAnimGraph": true
}
],
"Children": []
},
{
"__guid": "a9d8c3d0-cbcb-4ebe-994c-5f4c36f08996",
"__version": 1,
"Flags": 0,
"Name": "Laser",
"Position": "11.14736,-0.2659489,5.71905",
"Rotation": "0,0,0,1",
"Scale": "1,0.1,0.1",
"Tags": "",
"Enabled": false,
"NetworkMode": 2,
"NetworkInterpolation": true,
"NetworkOrphaned": 0,
"OwnerTransfer": 1,
"Components": [
{
"__type": "Sandbox.SkinnedModelRenderer",
"__guid": "e1b93001-f96d-474d-bd6f-aaa2acb0d33e",
"__enabled": true,
"AnimationGraph": null,
"BodyGroups": 18446744073709551615,
"BoneMergeTarget": null,
"CreateAttachments": false,
"CreateBoneObjects": false,
"MaterialGroup": null,
"MaterialOverride": "materials/pistol/glow_2.vmat",
"Model": "lasermesh.vmdl",
"Morphs": {},
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"Parameters": {
"bools": {},
"ints": {},
"floats": {},
"vectors": {},
"rotations": {}
},
"PlaybackRate": 1,
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Sequence": {
"Name": null,
"Looping": true,
"Blending": false
},
"Tint": "1,1,1,1",
"UseAnimGraph": true
}
],
"Children": []
},
{
"__guid": "0e9f41d3-8000-4c3c-9cdd-076056da9d0a",
"__version": 1,

View File

@ -0,0 +1,270 @@
{
"RootObject": {
"__guid": "ce810e36-c1c4-4ea3-be56-46c1d13e5273",
"__version": 1,
"Flags": 0,
"Name": "rifle",
"Position": "0,0,0",
"Rotation": "0,0,0,1",
"Scale": "1,1,1",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
"NetworkInterpolation": true,
"NetworkOrphaned": 0,
"OwnerTransfer": 1,
"Components": [
{
"__type": "Sandbox.SkinnedModelRenderer",
"__guid": "b925eab6-e868-4a8b-98d2-253a888c8b61",
"__enabled": true,
"AnimationGraph": null,
"BodyGroups": 3,
"BoneMergeTarget": null,
"CreateAttachments": false,
"CreateBoneObjects": false,
"MaterialGroup": null,
"MaterialOverride": null,
"Model": "models/weapons/sbox_smg_mp5/w_mp5.vmdl",
"Morphs": {},
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"Parameters": {
"bools": {},
"ints": {},
"floats": {},
"vectors": {},
"rotations": {}
},
"PlaybackRate": 1,
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Sequence": {
"Name": null,
"Looping": true,
"Blending": false
},
"Tint": "1,1,1,1",
"UseAnimGraph": true
},
{
"__type": "Sandbox.SoundPointComponent",
"__guid": "7107268f-7ddf-4ecd-95c7-476f0245e407",
"__enabled": true,
"Distance": 2219,
"DistanceAttenuation": true,
"DistanceAttenuationOverride": true,
"Falloff": [
{
"x": 0,
"y": 1,
"in": 3.1415927,
"out": -3.1415927,
"mode": "Mirrored"
},
{
"x": 1,
"y": 0,
"in": 0,
"out": 0,
"mode": "Mirrored"
}
],
"Force2d": false,
"MaxRepeatTime": 1,
"MinRepeatTime": 1,
"Occlusion": false,
"OcclusionOverride": false,
"OcclusionRadius": 32,
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"Pitch": 1,
"PlayOnStart": false,
"ReflectionOverride": false,
"Reflections": false,
"Repeat": false,
"SoundEvent": "sounds/shoot_sound_1.sound",
"SoundOverride": false,
"StopOnNew": true,
"TargetMixer": {
"Name": "game",
"Id": "fa65adf3-a336-4d2b-9e2f-37f15349175a"
},
"Volume": 1
},
{
"__type": "Sasalka.PickupItem",
"__guid": "bd83be18-ee6a-4de8-b3eb-5faee04b353c",
"__enabled": true,
"Label": "E",
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"RequiresHold": false
},
{
"__type": "Sandbox.BoxCollider",
"__guid": "d9bc44c9-fb0c-423f-abe7-313a9004f75f",
"__enabled": true,
"Center": "1.620956,-0.09806705,5.646916",
"Friction": null,
"IsTrigger": false,
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"OnObjectTriggerEnter": null,
"OnObjectTriggerExit": null,
"OnTriggerEnter": null,
"OnTriggerExit": null,
"Scale": "22.61082,2.802388,10.66742",
"Static": false,
"Surface": null,
"SurfaceVelocity": "0,0,0"
},
{
"__type": "Sandbox.Rigidbody",
"__guid": "22b20b29-fe55-4216-b753-3e0133f7fdeb",
"__enabled": true,
"AngularDamping": 0,
"Gravity": true,
"LinearDamping": 0,
"Locking": {
"X": false,
"Y": false,
"Z": false,
"Pitch": false,
"Yaw": false,
"Roll": false
},
"MassCenterOverride": "0,0,0",
"MassOverride": 35,
"MotionEnabled": true,
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"OverrideMassCenter": false,
"RigidbodyFlags": 0,
"StartAsleep": false
},
{
"__type": "Sandbox.Weapons.BaseWeapon",
"__guid": "d0fd09c4-795e-48f1-a8e0-d842e34a08b4",
"__enabled": true,
"BloodParticle": {
"_type": "gameobject",
"prefab": "prefabs/impacts/impact.flesh.mist.prefab"
},
"Count": 1,
"Definition": "items/rifle.weapon",
"EjectShellPrefab": null,
"EjectTransform": null,
"GunRenderer": {
"_type": "component",
"component_id": "b925eab6-e868-4a8b-98d2-253a888c8b61",
"go": "ce810e36-c1c4-4ea3-be56-46c1d13e5273",
"component_type": "SkinnedModelRenderer"
},
"MuzzleFlashPrefab": null,
"MuzzleLight": null,
"MuzzleTransform": null,
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"ParticlePrefab": {
"_type": "gameobject",
"prefab": "prefabs/impacts/impact.metal.prefab"
}
}
],
"Children": [
{
"__guid": "7fb74dde-10e5-42fe-a8ee-204e88d9191b",
"__version": 1,
"Flags": 0,
"Name": "Point Light",
"Position": "15.51598,0.00004095561,8.259875",
"Rotation": "0,0,0,1",
"Scale": "1,1,1",
"Tags": "light_point,light",
"Enabled": false,
"NetworkMode": 2,
"NetworkInterpolation": true,
"NetworkOrphaned": 0,
"OwnerTransfer": 1,
"Components": [
{
"__type": "Sandbox.PointLight",
"__guid": "cff6f843-9ace-46d0-b3bf-cf882762b913",
"__enabled": true,
"Attenuation": 1,
"FogMode": "Enabled",
"FogStrength": 1,
"LightColor": "0.45,1,0,1",
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"Radius": 400,
"Shadows": true
}
],
"Children": []
}
],
"__properties": {
"NetworkInterpolation": true,
"TimeScale": 1,
"WantsSystemScene": true,
"Metadata": {},
"NavMesh": {
"Enabled": false,
"IncludeStaticBodies": true,
"IncludeKeyframedBodies": true,
"EditorAutoUpdate": true,
"AgentHeight": 64,
"AgentRadius": 16,
"AgentStepSize": 18,
"AgentMaxSlope": 40,
"ExcludedBodies": "",
"IncludedBodies": ""
}
},
"__variables": []
},
"ResourceVersion": 2,
"ShowInMenu": false,
"MenuPath": null,
"MenuIcon": null,
"DontBreakAsTemplate": false,
"__references": [
"facepunch.w_mp5#33703"
],
"__version": 2
}

View File

@ -0,0 +1,166 @@
{
"RootObject": {
"__guid": "4ff6f615-319d-4ec0-a44e-b41f043aba92",
"__version": 1,
"Flags": 0,
"Name": "rifle_ammo",
"Position": "0,0,0",
"Rotation": "0,0,0,1",
"Scale": "0.7,0.7,0.7",
"Tags": "",
"Enabled": true,
"NetworkMode": 2,
"NetworkInterpolation": true,
"NetworkOrphaned": 0,
"OwnerTransfer": 1,
"Components": [
{
"__type": "Sandbox.SkinnedModelRenderer",
"__guid": "9ef3a8e5-9305-4390-91ba-9c58981bb8ec",
"__enabled": true,
"AnimationGraph": null,
"BodyGroups": 18446744073709551615,
"BoneMergeTarget": null,
"CreateAttachments": false,
"CreateBoneObjects": false,
"MaterialGroup": null,
"MaterialOverride": null,
"Model": "pr/gta5_ammo_1.vmdl",
"Morphs": {},
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"Parameters": {
"bools": {},
"ints": {},
"floats": {},
"vectors": {},
"rotations": {}
},
"PlaybackRate": 1,
"RenderOptions": {
"GameLayer": true,
"OverlayLayer": false,
"BloomLayer": false,
"AfterUILayer": false
},
"RenderType": "On",
"Sequence": {
"Name": null,
"Looping": true,
"Blending": false
},
"Tint": "1,1,1,1",
"UseAnimGraph": true
},
{
"__type": "Sandbox.BoxCollider",
"__guid": "e8bf0351-5b2f-46be-aba4-6fe5862578e7",
"__enabled": true,
"Center": "0.02521539,-0.003817081,3.401833",
"Friction": null,
"IsTrigger": false,
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"OnObjectTriggerEnter": null,
"OnObjectTriggerExit": null,
"OnTriggerEnter": null,
"OnTriggerExit": null,
"Scale": "4.454757,15.74074,6.848438",
"Static": false,
"Surface": null,
"SurfaceVelocity": "0,0,0"
},
{
"__type": "Sasalka.PickupItem",
"__guid": "c22be7d5-6e97-46f1-b4d4-ceadfd9c0c45",
"__enabled": true,
"Label": "E",
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"RequiresHold": false
},
{
"__type": "Sandbox.Rigidbody",
"__guid": "d6491a9e-6cdd-4c0f-8153-97b7a4b4a83d",
"__enabled": true,
"AngularDamping": 0,
"Gravity": true,
"LinearDamping": 0,
"Locking": {
"X": false,
"Y": false,
"Z": false,
"Pitch": false,
"Yaw": false,
"Roll": false
},
"MassCenterOverride": "0,0,0",
"MassOverride": 0,
"MotionEnabled": true,
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null,
"OverrideMassCenter": false,
"RigidbodyFlags": 0,
"StartAsleep": false
},
{
"__type": "Sasalka.InventoryItem",
"__guid": "07adf41b-f453-45e5-9235-7f372563b8f7",
"__enabled": true,
"Count": 256,
"Definition": "items/rifle.ammo",
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null
}
],
"Children": [],
"__properties": {
"NetworkInterpolation": true,
"TimeScale": 1,
"WantsSystemScene": true,
"Metadata": {},
"NavMesh": {
"Enabled": false,
"IncludeStaticBodies": true,
"IncludeKeyframedBodies": true,
"EditorAutoUpdate": true,
"AgentHeight": 64,
"AgentRadius": 16,
"AgentStepSize": 18,
"AgentMaxSlope": 40,
"ExcludedBodies": "",
"IncludedBodies": ""
}
},
"__variables": []
},
"ResourceVersion": 2,
"ShowInMenu": false,
"MenuPath": null,
"MenuIcon": null,
"DontBreakAsTemplate": false,
"__references": [
"gtavteam.gta5ammo1#103232"
],
"__version": 2
}

View File

@ -483,18 +483,18 @@
"e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec": "7cdbb78c-19c3-4f0a-9662-91609da57955",
"ee9d15a8-ffe9-43f1-b6b4-2f04ce55c908": "5fbe67ec-6b54-4560-87ef-8515fce7d33d",
"5830c995-d747-4c8c-abd7-b0366fa2a2aa": "81bd6292-744c-4e33-8c6a-3904a13ee646",
"eeca4029-990c-43e6-aa16-1df8fc69fa1c": "cd79147f-c09a-4b76-94a0-b46b730a9ff1",
"a8bc6a6d-dc7b-441a-8191-79e83a998981": "2bbccf7e-a902-430e-9436-a01d86a0fe5b",
"4d97a077-f187-44f4-967b-d346530c38d9": "7fb3b2db-8dd8-4611-b79b-18529c4a2081",
"beaec0c2-ccc3-48b0-8459-5a3f3fe679f1": "823f8251-0a51-4513-9995-178c44e63469",
"e428ecbc-40fd-4ec5-b1af-373bce265f3e": "766cbde5-8f5c-4660-8608-100ffefbfa29",
"ce6aaed8-3ae5-41a4-a21c-1386b86a158a": "a8918404-1c91-48c8-ba49-f878516a2565",
"1ef0f21d-1147-4a46-97e8-97c587a99040": "6151c1b8-ff4e-4cc8-99dd-1eff15bb641d",
"038bd275-df09-422f-9f02-8448b02706f8": "bc2008a9-f206-4008-89d1-beee5d1051bd",
"edaf7116-38ed-4e2f-91d6-b20aa9a1a009": "8d625f14-d541-41ad-9c41-11561fb1a931",
"1bb4075f-849c-4761-93bc-38f31cd11650": "811e4d93-ba7e-4edd-9ac4-ccb89bc87fb3",
"0b67d1c5-594a-49fa-8c23-e7a3ed9edb2c": "90d493ea-1b5c-4a93-ba8b-a8b538fb4ade",
"3cd5251b-38a8-4f0e-8b33-4b2e5f7041ab": "2ccacb25-f30f-42ea-982d-bc521e4aefac",
"8b94182b-9ac1-4646-8f8c-d3188a804946": "15f06e09-733f-4885-9a95-f7dd23d93657",
"c4a3df64-7ff1-483a-9f9e-e181152d7645": "f5ed5bad-5418-4b0d-a6f6-3c0cdfbcef5f",
"8546ae27-6c60-4e32-b613-760bc20bd651": "82b483e1-7ceb-4ab0-865c-97891016f1a1",
"064ba569-c0b4-48ac-8ab4-a5c4d63b1a30": "73756613-cabc-413b-8fec-024b6e6c0246",
"50b368f3-d27b-4408-a66b-a9d852e6fbae": "dd02755a-000b-440f-9e55-7b4b0b7bac75"
}
@ -530,22 +530,163 @@
"e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec": "2fe45086-5076-4fdc-a2c7-29ec92c23810",
"ee9d15a8-ffe9-43f1-b6b4-2f04ce55c908": "c7e24a6f-de41-4d1e-be96-0348b347119b",
"5830c995-d747-4c8c-abd7-b0366fa2a2aa": "d7c8e6d4-4f33-4929-9600-91bab058201d",
"eeca4029-990c-43e6-aa16-1df8fc69fa1c": "30727755-3261-4208-b2cd-604ea5f3110e",
"a8bc6a6d-dc7b-441a-8191-79e83a998981": "1a3087d3-c5ef-4770-8473-11ecb7e429b0",
"4d97a077-f187-44f4-967b-d346530c38d9": "6d89a94c-3924-4534-822a-8199fcc273c6",
"beaec0c2-ccc3-48b0-8459-5a3f3fe679f1": "7f1321e3-4e18-431a-ac36-4c006ff42ca2",
"e428ecbc-40fd-4ec5-b1af-373bce265f3e": "dd9de019-e850-4b70-9f23-9c7606b71258",
"ce6aaed8-3ae5-41a4-a21c-1386b86a158a": "6835aaa4-31e7-44d3-bcf7-21435bfc30a8",
"1ef0f21d-1147-4a46-97e8-97c587a99040": "24907222-1cef-4d26-aae2-55cde0ce8506",
"038bd275-df09-422f-9f02-8448b02706f8": "f23c909a-e080-418f-8bf4-4812459b17b4",
"edaf7116-38ed-4e2f-91d6-b20aa9a1a009": "4e5c0f1e-d31e-40ad-ade5-594b2de38e2d",
"1bb4075f-849c-4761-93bc-38f31cd11650": "60d7794d-069e-4533-a002-5a0596f4a52d",
"0b67d1c5-594a-49fa-8c23-e7a3ed9edb2c": "f87dd0c6-58c1-4d94-9799-7ad2e8a247f8",
"3cd5251b-38a8-4f0e-8b33-4b2e5f7041ab": "abb38bd9-332e-45fc-8929-165de4a4cbde",
"8b94182b-9ac1-4646-8f8c-d3188a804946": "2f496a29-ba4e-4878-abdb-85a9b2af2748",
"c4a3df64-7ff1-483a-9f9e-e181152d7645": "89cb0618-4fb3-4ccf-b9d3-63abe5bd67ed",
"8546ae27-6c60-4e32-b613-760bc20bd651": "83bff6d3-cf32-4171-b61f-7f65107412f7",
"064ba569-c0b4-48ac-8ab4-a5c4d63b1a30": "f291bdc2-16d4-496b-9cfc-2c1900649bf0",
"50b368f3-d27b-4408-a66b-a9d852e6fbae": "a2165c8e-f32c-4bba-a482-c0a1c52bfe1f"
}
},
{
"__guid": "4ed6abca-da6a-40a4-a85d-e3eb3ab9c9fe",
"__version": 1,
"__Prefab": "prefabs/weapon/ammobox.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec"
},
"Property": "Name",
"Value": "ammobox (3)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec"
},
"Property": "Position",
"Value": "-208,0,25.9415"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec": "4ed6abca-da6a-40a4-a85d-e3eb3ab9c9fe",
"ee9d15a8-ffe9-43f1-b6b4-2f04ce55c908": "07934156-cd77-4ab8-8a7e-d18824fa97a2",
"5830c995-d747-4c8c-abd7-b0366fa2a2aa": "1a4c01ee-6b56-4ece-9f44-067a75c6ed49",
"a8bc6a6d-dc7b-441a-8191-79e83a998981": "42f257d3-c347-4e42-98c3-50b3ef90b616",
"4d97a077-f187-44f4-967b-d346530c38d9": "c81e4f94-ee68-411e-8fc9-620bb554713a",
"beaec0c2-ccc3-48b0-8459-5a3f3fe679f1": "79bafc64-2b92-459d-9b0d-cfbdbe7a9d3d",
"e428ecbc-40fd-4ec5-b1af-373bce265f3e": "c6a1c625-0f1d-4e2d-a827-ff1900a1b78a",
"ce6aaed8-3ae5-41a4-a21c-1386b86a158a": "0813eb9d-0650-4535-b508-8ee8492de37f",
"1ef0f21d-1147-4a46-97e8-97c587a99040": "98137f85-135f-421a-aeb4-f19da15fdcb9",
"edaf7116-38ed-4e2f-91d6-b20aa9a1a009": "e81c11b9-e5ba-4706-973e-ba524f950f53",
"1bb4075f-849c-4761-93bc-38f31cd11650": "3d5b8eea-68c8-437c-8e94-4a65547d4ca5",
"0b67d1c5-594a-49fa-8c23-e7a3ed9edb2c": "d8952b1b-43da-41f3-8b2d-e78535dc259f",
"3cd5251b-38a8-4f0e-8b33-4b2e5f7041ab": "d2bb83c5-4890-4778-ac8b-d28521fdbabe",
"8b94182b-9ac1-4646-8f8c-d3188a804946": "8c0262f4-3716-4002-950e-ac4275727078",
"8546ae27-6c60-4e32-b613-760bc20bd651": "aeff76fb-997e-4c18-b5ae-5cd7c5519c51",
"064ba569-c0b4-48ac-8ab4-a5c4d63b1a30": "b93d37a8-08d7-483b-ac33-7ba4ff3578e0",
"50b368f3-d27b-4408-a66b-a9d852e6fbae": "3c748d15-e279-491e-8818-14b16c13f449"
}
},
{
"__guid": "f85bc434-abd2-4df8-afe2-6938d81882e7",
"__version": 1,
"__Prefab": "prefabs/weapon/ammobox.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec"
},
"Property": "Name",
"Value": "ammobox (4)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec"
},
"Property": "Position",
"Value": "-208,-73.59452,25.9415"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec": "f85bc434-abd2-4df8-afe2-6938d81882e7",
"ee9d15a8-ffe9-43f1-b6b4-2f04ce55c908": "53144f80-1ae6-4e38-afd8-de5b940c9914",
"5830c995-d747-4c8c-abd7-b0366fa2a2aa": "a8f7cbe5-1a72-4f23-be58-54f94834a856",
"a8bc6a6d-dc7b-441a-8191-79e83a998981": "3f843b6a-4ff0-4e98-a8b3-712de388be30",
"4d97a077-f187-44f4-967b-d346530c38d9": "2dbbb9a0-8442-4d3f-b029-3baa42cb8160",
"beaec0c2-ccc3-48b0-8459-5a3f3fe679f1": "ff359104-6fac-4007-bd4a-e36c4bfaa8f6",
"e428ecbc-40fd-4ec5-b1af-373bce265f3e": "bdfae16e-cb5e-484b-a6fd-77253077120c",
"ce6aaed8-3ae5-41a4-a21c-1386b86a158a": "935de003-427d-4cd6-8afd-1d2e576aebbc",
"1ef0f21d-1147-4a46-97e8-97c587a99040": "2a6379aa-065d-4115-9e64-42105c075829",
"edaf7116-38ed-4e2f-91d6-b20aa9a1a009": "667ca01c-b3f1-4ce3-acae-b1621106c75e",
"1bb4075f-849c-4761-93bc-38f31cd11650": "30a1989e-1697-4122-b2fc-2a8c995f44fa",
"0b67d1c5-594a-49fa-8c23-e7a3ed9edb2c": "d2298566-d2fb-4166-9edf-2362a0b8704b",
"3cd5251b-38a8-4f0e-8b33-4b2e5f7041ab": "4cf14ee4-793d-45ee-8683-a4accb99bcab",
"8b94182b-9ac1-4646-8f8c-d3188a804946": "9bbd7a6a-e21e-4f33-9547-d1e15b599950",
"8546ae27-6c60-4e32-b613-760bc20bd651": "78315867-fa2d-43be-9502-bdc5e1226c22",
"064ba569-c0b4-48ac-8ab4-a5c4d63b1a30": "f5b20e36-4239-4214-b807-aa3d3882ab8c",
"50b368f3-d27b-4408-a66b-a9d852e6fbae": "18acb634-ca98-42c0-9a0c-df5df0fc774f"
}
},
{
"__guid": "2b30f1ea-0750-4356-8c74-f1df112f0eca",
"__version": 1,
"__Prefab": "prefabs/weapon/ammobox.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec"
},
"Property": "Name",
"Value": "ammobox (5)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec"
},
"Property": "Position",
"Value": "-208,63.99999,25.9415"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec": "2b30f1ea-0750-4356-8c74-f1df112f0eca",
"ee9d15a8-ffe9-43f1-b6b4-2f04ce55c908": "ecbe40cb-4a40-4ba8-a11b-4f8a3c4bafdf",
"5830c995-d747-4c8c-abd7-b0366fa2a2aa": "8ed3d160-7285-4c45-bded-f04d9065358a",
"a8bc6a6d-dc7b-441a-8191-79e83a998981": "597ad90e-a16b-46b2-8d57-29365272387b",
"4d97a077-f187-44f4-967b-d346530c38d9": "43d19e9d-c180-4015-9e40-c960f9a5eb9b",
"beaec0c2-ccc3-48b0-8459-5a3f3fe679f1": "d47aa8c4-ab1e-4c6a-b9f1-e75a51b49b87",
"e428ecbc-40fd-4ec5-b1af-373bce265f3e": "cf7c358d-803c-438e-bb77-37808b53db0e",
"ce6aaed8-3ae5-41a4-a21c-1386b86a158a": "ac5687fd-4ca1-4249-bae6-e5585c89587a",
"1ef0f21d-1147-4a46-97e8-97c587a99040": "3b61ed68-653c-481d-9f1f-d3e32de495f7",
"edaf7116-38ed-4e2f-91d6-b20aa9a1a009": "99960b6a-3144-4c60-9f04-81a181889fd7",
"1bb4075f-849c-4761-93bc-38f31cd11650": "9b438347-d95f-451b-a7b8-6d3f35d77d5b",
"0b67d1c5-594a-49fa-8c23-e7a3ed9edb2c": "5e7ae2a9-b609-405a-a334-14bc66464ab7",
"3cd5251b-38a8-4f0e-8b33-4b2e5f7041ab": "391280d0-b4d2-47d5-9a34-e9d993067213",
"8b94182b-9ac1-4646-8f8c-d3188a804946": "9f7e2cee-2331-47ca-8188-2a33630267d5",
"8546ae27-6c60-4e32-b613-760bc20bd651": "eb68193a-9338-4598-b12e-16ae5e53c255",
"064ba569-c0b4-48ac-8ab4-a5c4d63b1a30": "5ce66eb8-f11b-42df-8b74-7c0bec829628",
"50b368f3-d27b-4408-a66b-a9d852e6fbae": "c7fc3e9f-2388-4e69-89b4-a1b559a9beb7"
}
},
{
"__guid": "ef158b83-fa9f-4774-9eb1-36651c8b08a9",
"__version": 1,
@ -577,18 +718,18 @@
"e5e018f2-9cad-4ece-b160-ab2aa3aeb7ec": "ef158b83-fa9f-4774-9eb1-36651c8b08a9",
"ee9d15a8-ffe9-43f1-b6b4-2f04ce55c908": "c1b4d1db-34b2-4dd2-986c-0ca47ee367c6",
"5830c995-d747-4c8c-abd7-b0366fa2a2aa": "688d5b7a-3628-411c-bce4-7e71c36b65c8",
"eeca4029-990c-43e6-aa16-1df8fc69fa1c": "32cb01e1-fc77-431b-ae65-96f807c4580e",
"a8bc6a6d-dc7b-441a-8191-79e83a998981": "1aa4e1fb-9d82-4691-bab8-eecf3e6527bb",
"4d97a077-f187-44f4-967b-d346530c38d9": "621b7ca2-7ae7-4867-9251-30e27db49025",
"beaec0c2-ccc3-48b0-8459-5a3f3fe679f1": "57855c6f-9f2c-45a8-a493-b4144dabbdae",
"e428ecbc-40fd-4ec5-b1af-373bce265f3e": "f421713f-ba53-49ef-9299-e43dfbafcb96",
"ce6aaed8-3ae5-41a4-a21c-1386b86a158a": "3d8d56a5-3400-4f27-bfd6-ea9bdca3d1fc",
"1ef0f21d-1147-4a46-97e8-97c587a99040": "75e8850c-7f68-42f8-b708-5cee771c0712",
"038bd275-df09-422f-9f02-8448b02706f8": "248d9927-b022-4daa-aa13-222b1e5a4a96",
"edaf7116-38ed-4e2f-91d6-b20aa9a1a009": "1bb154cf-2ec2-484b-8d4a-9cd6e3513172",
"1bb4075f-849c-4761-93bc-38f31cd11650": "72218084-be9b-4bf0-986a-166ca09da287",
"0b67d1c5-594a-49fa-8c23-e7a3ed9edb2c": "7f607022-8e99-4761-9e9b-72a71ae4d5a8",
"3cd5251b-38a8-4f0e-8b33-4b2e5f7041ab": "a766afdb-5b02-4407-96f7-0a0e345ba3c1",
"8b94182b-9ac1-4646-8f8c-d3188a804946": "67c84159-9ad0-43fb-880c-3ad680d09cd3",
"c4a3df64-7ff1-483a-9f9e-e181152d7645": "deaf34f3-b848-4556-ab94-f9c93cadf1bc",
"8546ae27-6c60-4e32-b613-760bc20bd651": "4b0938e9-2c6f-4c70-887f-dcc815aa4907",
"064ba569-c0b4-48ac-8ab4-a5c4d63b1a30": "bd311d99-63b5-4a80-8fc6-7debe7012e8d",
"50b368f3-d27b-4408-a66b-a9d852e6fbae": "a5a33b69-7390-4492-8dfd-a52766b99b88"
}
@ -624,20 +765,15 @@
"dec3b7f3-79ae-4bb4-b868-8de9d0306ebb": "1034f502-c912-439a-ac04-247c569da01d",
"6017d24d-39d0-4acf-bf9f-010c345fd13d": "4a6feb0c-3798-41fd-b68f-9f43df293833",
"be95c906-5f2f-4239-8fd6-a42a148dea6e": "7844d416-a403-43e6-b473-c337d1be6fc5",
"fc38d078-995b-443a-b409-e877618fcf09": "428482a2-31e0-4f7b-a587-eb91a6027627",
"f5968c60-ed2e-47d1-a2bf-353e0398f234": "257dce97-2921-4cf9-95de-e06525bd0492",
"ce60c131-01f0-4aa3-a84c-c93eac1d1c2d": "cb13417e-2527-40b7-9ddf-2c017f9a8a49",
"8a705640-2966-489e-a41a-2bf6f2cc62f0": "a5f8a313-cccc-4c11-98c0-e82b09badcd3",
"8b4ca11f-8cd7-4bb5-bb63-df86dac15ab9": "43445fd1-090e-49c9-8ed7-80ee31b7e783",
"eda01dbe-7e56-4e66-af99-673e197e7dc0": "2b8b3252-0ecd-4f4b-9330-abc2f28b1a41",
"1e1e54b4-ebf1-4211-9ca9-0eaa37f7bf7e": "5a7aa1bb-b972-401d-ab32-fc2d5e8b7ed6",
"d81748e9-bc3d-4d68-97b5-5602bf5e0e15": "ce0cb119-4e70-4cc4-acbb-fb6d427da560",
"47bb3ba1-b0de-4af4-b639-235a5ad2c312": "b9e29a07-c32c-43df-9b07-ec3e476aae4f",
"862e0738-e57f-456a-b0c8-ff03a165faf9": "60c3cc77-fcc1-40a5-b59f-e6d95928d1c3",
"a9d8c3d0-cbcb-4ebe-994c-5f4c36f08996": "01aaf3a8-35b9-42ed-92b6-ca6ebab54da4",
"e1b93001-f96d-474d-bd6f-aaa2acb0d33e": "869a166b-198b-415e-bf4b-4c2fb433c0db",
"0e9f41d3-8000-4c3c-9cdd-076056da9d0a": "18f82aba-24fa-4b6e-837b-fd1ec2476eed",
"3803bdb5-aa92-46f7-91a6-1dfad9549cf4": "78aa5d8b-aa80-4567-a4c6-e1a2a68ce75d"
"3803bdb5-aa92-46f7-91a6-1dfad9549cf4": "78aa5d8b-aa80-4567-a4c6-e1a2a68ce75d",
"7350112e-dea3-4c22-b9fc-76eaed3d2e57": "fba83d2a-9c99-4675-bfa4-bdb2a625a89d",
"b5ffb918-23a1-419f-a24f-fc29537de2fc": "6ef6b2f8-b552-4007-9df0-0f2b2842ed5e"
}
},
{
@ -679,20 +815,15 @@
"dec3b7f3-79ae-4bb4-b868-8de9d0306ebb": "b87ddd8d-e792-4e56-808d-edfe666a9dfa",
"6017d24d-39d0-4acf-bf9f-010c345fd13d": "a04677d0-af09-4eb5-bda6-9019c17389d2",
"be95c906-5f2f-4239-8fd6-a42a148dea6e": "204255d7-7330-4b3d-b0fd-e648a4b8c728",
"fc38d078-995b-443a-b409-e877618fcf09": "ff3f86ae-660f-4a43-a0b0-1c7e87d1e642",
"f5968c60-ed2e-47d1-a2bf-353e0398f234": "2c56a4c8-eb8d-44aa-95fa-6c27d6391e4d",
"ce60c131-01f0-4aa3-a84c-c93eac1d1c2d": "4157870e-5b90-40cb-a0ba-3c61a7805d06",
"8a705640-2966-489e-a41a-2bf6f2cc62f0": "1eb22b1c-ab75-4553-9470-f5e3e4eef369",
"8b4ca11f-8cd7-4bb5-bb63-df86dac15ab9": "f9cec441-fa67-4932-a804-41c9beebf07e",
"eda01dbe-7e56-4e66-af99-673e197e7dc0": "992ea752-8961-4068-9eab-d35e51bc240f",
"1e1e54b4-ebf1-4211-9ca9-0eaa37f7bf7e": "b3f8207d-7199-468e-989a-72b07e3677c8",
"d81748e9-bc3d-4d68-97b5-5602bf5e0e15": "50248e35-b382-47fe-93df-d76bb692a7a9",
"47bb3ba1-b0de-4af4-b639-235a5ad2c312": "c79ec4c2-e9cf-4199-81e8-fdf08bde20f9",
"862e0738-e57f-456a-b0c8-ff03a165faf9": "2f84939e-7c85-4728-8b3e-a837e45b9be0",
"a9d8c3d0-cbcb-4ebe-994c-5f4c36f08996": "6df11cad-369d-452f-8369-26c29a5ae85a",
"e1b93001-f96d-474d-bd6f-aaa2acb0d33e": "b2222db5-cc8b-4d65-af65-af81c58fb513",
"0e9f41d3-8000-4c3c-9cdd-076056da9d0a": "bb16be7f-8738-447c-af5e-7a13e7d37496",
"3803bdb5-aa92-46f7-91a6-1dfad9549cf4": "40650dba-c62c-4cad-b758-8f93888fd18a"
"3803bdb5-aa92-46f7-91a6-1dfad9549cf4": "40650dba-c62c-4cad-b758-8f93888fd18a",
"7350112e-dea3-4c22-b9fc-76eaed3d2e57": "a190d639-c064-4db7-b45c-b1321ac7df19",
"b5ffb918-23a1-419f-a24f-fc29537de2fc": "871fc5b1-f10c-43c4-969e-da41517af821"
}
},
{
@ -734,20 +865,15 @@
"dec3b7f3-79ae-4bb4-b868-8de9d0306ebb": "4c079c5e-e371-418f-9a37-9b5d1118d5a4",
"6017d24d-39d0-4acf-bf9f-010c345fd13d": "b2d698cd-6aee-497b-bfa9-163d21d2e0b5",
"be95c906-5f2f-4239-8fd6-a42a148dea6e": "fa129559-6f5f-40ee-87f0-9ab69ee70743",
"fc38d078-995b-443a-b409-e877618fcf09": "16b190ad-d52f-403d-882b-bff9261232ae",
"f5968c60-ed2e-47d1-a2bf-353e0398f234": "7f88a632-e787-4609-8a8b-ecd3f555872a",
"ce60c131-01f0-4aa3-a84c-c93eac1d1c2d": "e59c9852-cd4c-4475-9385-4fd32ad4b876",
"8a705640-2966-489e-a41a-2bf6f2cc62f0": "aa7217af-d2b3-440f-9852-c8c047c096c6",
"8b4ca11f-8cd7-4bb5-bb63-df86dac15ab9": "1ad59142-d2a2-47c6-88ee-4ed5817cb5c6",
"eda01dbe-7e56-4e66-af99-673e197e7dc0": "a1daf45d-3c28-410e-99ac-bd46423d460d",
"1e1e54b4-ebf1-4211-9ca9-0eaa37f7bf7e": "c720be7c-379a-423e-93c0-27cb95e0f5da",
"d81748e9-bc3d-4d68-97b5-5602bf5e0e15": "8b332009-dcae-4b4c-a7fd-3516d124a8e0",
"47bb3ba1-b0de-4af4-b639-235a5ad2c312": "fa7761a6-39cd-4a52-9e79-02b814a93513",
"862e0738-e57f-456a-b0c8-ff03a165faf9": "64583c12-6561-414c-8e46-c5da3b76441f",
"a9d8c3d0-cbcb-4ebe-994c-5f4c36f08996": "b57ab630-575f-40d7-8c79-a58a3fc11714",
"e1b93001-f96d-474d-bd6f-aaa2acb0d33e": "ac520095-a46f-41df-a98f-dcb0c2c4fc1b",
"0e9f41d3-8000-4c3c-9cdd-076056da9d0a": "6f1cd41b-072f-4ca9-86be-ea3e169e01be",
"3803bdb5-aa92-46f7-91a6-1dfad9549cf4": "9712ecae-2ba2-4476-97ca-70129d6f141b"
"3803bdb5-aa92-46f7-91a6-1dfad9549cf4": "9712ecae-2ba2-4476-97ca-70129d6f141b",
"7350112e-dea3-4c22-b9fc-76eaed3d2e57": "37b10582-4dce-421a-b292-1f48daaf3443",
"b5ffb918-23a1-419f-a24f-fc29537de2fc": "46d83bee-de04-427e-9f67-7afa1eac8fb9"
}
},
{
@ -5120,6 +5246,333 @@
"c888eaab-cb05-4469-bf5f-7c23ede5c25f": "799f4a0c-f42b-46e6-ba2b-44de0a85255e",
"a90f059e-5c0a-4122-b742-9dd12e5d8494": "d14d3f67-52e9-4ff1-9348-66990b170c0f"
}
},
{
"__guid": "2499dcc5-fb26-4924-b563-6ecb05df2dc3",
"__version": 1,
"__Prefab": "prefabs/weapon/rifle.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Position",
"Value": "-208,-13.85934,26.00335"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Rotation",
"Value": "0.7071067,0,0,0.7071068"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"ce810e36-c1c4-4ea3-be56-46c1d13e5273": "2499dcc5-fb26-4924-b563-6ecb05df2dc3",
"b925eab6-e868-4a8b-98d2-253a888c8b61": "01f91416-76bc-40ac-b670-ca117c22abb6",
"bd83be18-ee6a-4de8-b3eb-5faee04b353c": "c5fdbef3-eeb9-4200-82e9-5b6b5515974f",
"d9bc44c9-fb0c-423f-abe7-313a9004f75f": "5164271e-68f3-4805-875a-d0ea6b39c9fa",
"22b20b29-fe55-4216-b753-3e0133f7fdeb": "b61089c3-00a5-4781-bbe1-bf752f003d07",
"7107268f-7ddf-4ecd-95c7-476f0245e407": "b0d8899c-121b-42a1-9c63-df2860a1493a",
"7fb74dde-10e5-42fe-a8ee-204e88d9191b": "5f6df403-c654-4be7-8aaf-c208a4f3130f",
"cff6f843-9ace-46d0-b3bf-cf882762b913": "276dd906-367f-449a-b5a1-dfb041feeb4d",
"d0fd09c4-795e-48f1-a8e0-d842e34a08b4": "46248e67-0af7-4e77-902a-e75ef1202d43"
}
},
{
"__guid": "e23945c0-235c-4642-befd-7f58558ef0b5",
"__version": 1,
"__Prefab": "prefabs/weapon/rifle.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Name",
"Value": "rifle (1)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Position",
"Value": "-208.9104,-39.05935,26.00336"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Rotation",
"Value": "0.7071067,0,0,0.7071068"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"ce810e36-c1c4-4ea3-be56-46c1d13e5273": "e23945c0-235c-4642-befd-7f58558ef0b5",
"b925eab6-e868-4a8b-98d2-253a888c8b61": "010a6dad-2fe1-4d11-ac26-759762e797a7",
"bd83be18-ee6a-4de8-b3eb-5faee04b353c": "aac79729-e403-4a48-844e-eefbde508a0d",
"d9bc44c9-fb0c-423f-abe7-313a9004f75f": "d216c2f0-6a89-4866-b603-1e5457b395eb",
"22b20b29-fe55-4216-b753-3e0133f7fdeb": "303c3eae-b7cc-405c-8bcc-317512e225dc",
"7107268f-7ddf-4ecd-95c7-476f0245e407": "c1b9af59-87d8-4adb-ab82-d0c3539e8e1d",
"7fb74dde-10e5-42fe-a8ee-204e88d9191b": "5478ea76-dfa6-4a7a-b41e-58fdebe2fca7",
"cff6f843-9ace-46d0-b3bf-cf882762b913": "33c3ede2-63ff-4013-9ffd-8529e7325348",
"d0fd09c4-795e-48f1-a8e0-d842e34a08b4": "8f878f51-1f1a-4b59-a06f-5952e3053599"
}
},
{
"__guid": "512d0db7-6be3-4581-a79d-dca09c417850",
"__version": 1,
"__Prefab": "prefabs/weapon/rifle.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Name",
"Value": "rifle (2)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Position",
"Value": "-209.404,51.58465,26.00338"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Rotation",
"Value": "0.7071067,0,0,0.7071068"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"ce810e36-c1c4-4ea3-be56-46c1d13e5273": "512d0db7-6be3-4581-a79d-dca09c417850",
"b925eab6-e868-4a8b-98d2-253a888c8b61": "9919f394-a282-44fe-80b3-f261d27e1700",
"bd83be18-ee6a-4de8-b3eb-5faee04b353c": "07022d82-c2b0-4b86-9cfc-2b857c279ac9",
"d9bc44c9-fb0c-423f-abe7-313a9004f75f": "bd8a2e28-d210-43f0-81dd-3b13263dab3f",
"22b20b29-fe55-4216-b753-3e0133f7fdeb": "bebc3d6c-40a2-4ea0-a9cf-dd87656860df",
"7107268f-7ddf-4ecd-95c7-476f0245e407": "8837a81e-1379-483f-b883-8945f8137af2",
"7fb74dde-10e5-42fe-a8ee-204e88d9191b": "5ba76d69-72de-4036-a3ab-6eb2c7c7d231",
"cff6f843-9ace-46d0-b3bf-cf882762b913": "d834a9db-6a5a-4105-a33f-128907a3307d",
"d0fd09c4-795e-48f1-a8e0-d842e34a08b4": "29bf53ee-55b5-434e-bb41-aeac37ff005d"
}
},
{
"__guid": "5b93b68d-71e7-4cbc-8056-968b95b8445a",
"__version": 1,
"__Prefab": "prefabs/weapon/rifle_ammo.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "4ff6f615-319d-4ec0-a44e-b41f043aba92"
},
"Property": "Position",
"Value": "-217.1469,-5.468893,25.56124"
},
{
"Target": {
"Type": "Component",
"IdValue": "07adf41b-f453-45e5-9235-7f372563b8f7"
},
"Property": "Count",
"Value": 14
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"4ff6f615-319d-4ec0-a44e-b41f043aba92": "5b93b68d-71e7-4cbc-8056-968b95b8445a",
"9ef3a8e5-9305-4390-91ba-9c58981bb8ec": "c902b0b2-9ec7-4f03-b82f-7f40efc04b6a",
"e8bf0351-5b2f-46be-aba4-6fe5862578e7": "df220559-759d-4ab3-b15c-c13b47a28386",
"c22be7d5-6e97-46f1-b4d4-ceadfd9c0c45": "88936a05-2693-46b0-83ce-ffda951f3905",
"d6491a9e-6cdd-4c0f-8153-97b7a4b4a83d": "e0d91cbe-c5b9-4110-a324-dd024b167f03",
"07adf41b-f453-45e5-9235-7f372563b8f7": "1a6a6073-1f8e-4993-8e6a-b51d7c065217"
}
},
{
"__guid": "4d943eb3-f8b8-45e5-9b4e-278f4f351409",
"__version": 1,
"__Prefab": "prefabs/weapon/rifle_ammo.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "4ff6f615-319d-4ec0-a44e-b41f043aba92"
},
"Property": "Name",
"Value": "rifle_ammo (1)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "4ff6f615-319d-4ec0-a44e-b41f043aba92"
},
"Property": "Position",
"Value": "-199.6675,16.48223,25.56122"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"4ff6f615-319d-4ec0-a44e-b41f043aba92": "4d943eb3-f8b8-45e5-9b4e-278f4f351409",
"9ef3a8e5-9305-4390-91ba-9c58981bb8ec": "c2e62036-ab51-4972-8631-6b36a84e8b39",
"e8bf0351-5b2f-46be-aba4-6fe5862578e7": "330da1e7-7644-4afd-86b6-7b0723bf2a8e",
"c22be7d5-6e97-46f1-b4d4-ceadfd9c0c45": "4ed5a889-8a33-499f-87e5-88ceb6bbb73a",
"d6491a9e-6cdd-4c0f-8153-97b7a4b4a83d": "030db021-795e-441a-a504-5aa268d2a9e1",
"07adf41b-f453-45e5-9235-7f372563b8f7": "f816e542-f148-4b37-aad8-1e37851fc1d4"
}
},
{
"__guid": "9fd8f5b0-5cdc-4ab7-9a6b-ea78f751ea0b",
"__version": 1,
"__Prefab": "prefabs/weapon/rifle_ammo.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "4ff6f615-319d-4ec0-a44e-b41f043aba92"
},
"Property": "Name",
"Value": "rifle_ammo (2)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "4ff6f615-319d-4ec0-a44e-b41f043aba92"
},
"Property": "Position",
"Value": "-198.7243,80.48689,25.56121"
}
],
"MovedObjects": []
},
"__PrefabIdToInstanceId": {
"4ff6f615-319d-4ec0-a44e-b41f043aba92": "9fd8f5b0-5cdc-4ab7-9a6b-ea78f751ea0b",
"9ef3a8e5-9305-4390-91ba-9c58981bb8ec": "d71d19d0-046f-40b5-8d05-f5c070a7343d",
"e8bf0351-5b2f-46be-aba4-6fe5862578e7": "6264c534-ba6c-4fd0-add4-f414260edece",
"c22be7d5-6e97-46f1-b4d4-ceadfd9c0c45": "1a1edea4-a02e-4316-85bb-ac79fe496ac2",
"d6491a9e-6cdd-4c0f-8153-97b7a4b4a83d": "79e99158-1c51-40b0-b10b-313908b745d8",
"07adf41b-f453-45e5-9235-7f372563b8f7": "7d0617d9-333f-486d-aec5-12f8b15154ff"
}
},
{
"__guid": "e607bfcb-5213-4619-917b-d46537ab1892",
"__version": 1,
"__Prefab": "prefabs/weapon/rifle.prefab",
"__PrefabInstancePatch": {
"AddedObjects": [
{
"Id": {
"Type": "Component",
"IdValue": "eb5130b9-321a-4858-bc91-c682b22580ba"
},
"Parent": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"PreviousElement": {
"Type": "Component",
"IdValue": "b925eab6-e868-4a8b-98d2-253a888c8b61"
},
"ContainerProperty": "Components",
"IsContainerArray": true,
"Data": {
"__type": "Sasalka.InventoryItem",
"__guid": "eb5130b9-321a-4858-bc91-c682b22580ba",
"__enabled": true,
"Count": 1,
"Definition": "items/rifle.weapon",
"OnComponentDestroy": null,
"OnComponentDisabled": null,
"OnComponentEnabled": null,
"OnComponentFixedUpdate": null,
"OnComponentStart": null,
"OnComponentUpdate": null
}
}
],
"RemovedObjects": [],
"PropertyOverrides": [
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Name",
"Value": "rifle (3)"
},
{
"Target": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"Property": "Position",
"Value": "-160,0,3.65008"
}
],
"MovedObjects": [
{
"Id": {
"Type": "Component",
"IdValue": "7107268f-7ddf-4ecd-95c7-476f0245e407"
},
"NewParent": {
"Type": "GameObject",
"IdValue": "ce810e36-c1c4-4ea3-be56-46c1d13e5273"
},
"NewContainerProperty": "Components",
"IsNewContainerArray": true,
"NewPreviousElement": {
"Type": "Component",
"IdValue": "eb5130b9-321a-4858-bc91-c682b22580ba"
}
}
]
},
"__PrefabIdToInstanceId": {
"ce810e36-c1c4-4ea3-be56-46c1d13e5273": "e607bfcb-5213-4619-917b-d46537ab1892",
"b925eab6-e868-4a8b-98d2-253a888c8b61": "89dc490e-fe2c-4fb7-92c5-f6299b047343",
"7107268f-7ddf-4ecd-95c7-476f0245e407": "eb0d8009-8496-4d0e-9a0d-f158a36cb1f0",
"bd83be18-ee6a-4de8-b3eb-5faee04b353c": "9834df62-90f0-4830-b048-294a44f26ddc",
"d9bc44c9-fb0c-423f-abe7-313a9004f75f": "9d8e601e-e574-477d-a819-03c461370f61",
"22b20b29-fe55-4216-b753-3e0133f7fdeb": "0dbb72f1-e163-4dce-8322-b1c088e0169c",
"7fb74dde-10e5-42fe-a8ee-204e88d9191b": "bb4c4d4f-0f56-4c45-a03b-084374dde4ea",
"cff6f843-9ace-46d0-b3bf-cf882762b913": "8fecfa58-c7fb-445e-8e74-ad3dd151c024",
"d0fd09c4-795e-48f1-a8e0-d842e34a08b4": "b5030d94-b7ba-4836-84d6-a89385426682"
}
}
],
"SceneProperties": {

View File

@ -19,7 +19,7 @@ public class WeaponItemDefinition : BaseItemDefinition, IEquipable
public float Damage { get; set; } = 10f;
[Property, Category( "Weapon Properties" )]
public float FireRate { get; set; } = 1f;
public float FireRate { get; set; } = 10f; // Выстрелов в секунду
[Property, Category( "Weapon Properties" )]
public float Range { get; set; } = 1000f;
@ -30,6 +30,15 @@ public class WeaponItemDefinition : BaseItemDefinition, IEquipable
[Property, Category( "Weapon Properties" )]
public string AmmoType { get; set; } = "Pistol";
[Property, Category( "Weapon Properties" )]
public float ReloadTime { get; set; } = 2f;
[Property, Category( "Weapon Properties" )]
public float Spread { get; set; } = 0.02f; // Разброс при стрельбе
[Property, Category( "Weapon Properties" )]
public bool IsAutomatic { get; set; } = true; // Всегда автоматический режим
public override Inventar.InventorySlot? GetSlot() => Slot;
public override ItemCategory Category => ItemCategory.Weapon;

View File

@ -65,36 +65,37 @@ public class Inventar : Component
/// <summary>
/// Добавляет предмет в инвентарь, распределяя по существующим и новым стекам. Возвращает остаток, который не удалось добавить (или 0, если всё добавлено).
/// </summary>
public int AddItem(InventoryItem item)
public int AddItem( InventoryItem item )
{
if (item == null || item.Definition == null || item.Count <= 0)
if ( item == null || item.Definition == null || item.Count <= 0 )
return item.Count;
int toAdd = item.Count;
// 1. Заполняем существующие стаки
foreach (var stack in Items.Where(x => x.Definition == item.Definition && x.Count < x.Definition.MaxCount))
foreach ( var stack in Items.Where( x => x.Definition == item.Definition && x.Count < x.Definition.MaxCount ) )
{
int canAdd = Math.Min(toAdd, stack.Definition.MaxCount - stack.Count);
if (canAdd > 0)
int canAdd = Math.Min( toAdd, stack.Definition.MaxCount - stack.Count );
if ( canAdd > 0 )
{
stack.Count += canAdd;
toAdd -= canAdd;
OnChanged?.Invoke();
OnItemAdded?.Invoke(stack);
OnItemAdded?.Invoke( stack );
}
if (toAdd <= 0) return 0;
if ( toAdd <= 0 ) return 0;
}
// 2. Добавляем новые стаки, если есть место
while (toAdd > 0 && (UnlimitedSlots || Items.Count < MaxInventorySlots))
while ( toAdd > 0 && (UnlimitedSlots || Items.Count < MaxInventorySlots) )
{
int stackCount = Math.Min(toAdd, item.Definition.MaxCount);
int stackCount = Math.Min( toAdd, item.Definition.MaxCount );
var newStack = new InventoryItem { Definition = item.Definition, Count = stackCount };
Items.Add(newStack);
Items.Add( newStack );
toAdd -= stackCount;
OnChanged?.Invoke();
OnItemAdded?.Invoke(newStack);
OnItemAdded?.Invoke( newStack );
}
// 3. Возвращаем остаток, если не всё удалось добавить
@ -149,6 +150,7 @@ public class Inventar : Component
// Экипировать новый предмет
EquippedItems[slot.Value] = item;
item.Equipped = true;
item.OnEquipped();
OnEquipped?.Invoke( item );
OnChanged?.Invoke();
return true;
@ -159,19 +161,19 @@ public class Inventar : Component
if ( item == null || !Items.Contains( item ) )
return;
// Создаем копию предмета для выбрасывания
var droppedItem = new InventoryItem
{
Definition = item.Definition,
Count = item.Count // Выбрасываем всю стопку
};
// // Создаем копию предмета для выбрасывания
// var droppedItem = new InventoryItem
// {
// Definition = item.Definition,
// Count = item.Count // Выбрасываем всю стопку
// };
GameObject gO = item.Definition.Prefab.Clone( position );
if ( gO.Components.TryGet<InventoryItem>( out var inventoryItem ) )
{
inventoryItem.Count = droppedItem.Count;
inventoryItem.Definition = droppedItem.Definition;
inventoryItem.Count = item.Count;
inventoryItem.Definition = item.Definition;
}
gO.NetworkSpawn();
@ -191,6 +193,7 @@ public class Inventar : Component
{
EquippedItems.Remove( slotToRemove );
item.Equipped = false;
item.OnUnEquipped();
OnUnEquipped?.Invoke( item );
OnChanged?.Invoke();
}

View File

@ -13,7 +13,18 @@ public class InventoryItem : Component
{
if ( GameObject.Components.TryGet<PickupItem>( out var item ) )
{
item.Label = Definition?.Name ?? "Unknown Item";
string itemName = Definition?.Name;
if ( string.IsNullOrEmpty( itemName ) )
{
item.Label = "Unknown Item";
}
else
{
item.Label = Count > 1
? $"{itemName} x{Count}"
: itemName;
}
}
}
@ -58,6 +69,22 @@ public class InventoryItem : Component
return clone;
}
/// <summary>
/// Виртуальный метод для экипировки предмета
/// </summary>
public virtual void OnEquipped()
{
Equipped = true;
}
/// <summary>
/// Виртуальный метод для снятия предмета
/// </summary>
public virtual void OnUnEquipped()
{
Equipped = false;
}
public override string ToString()
{
return $"{Definition?.Name ?? "Unknown"} x{Count}";

View File

@ -1,85 +1,14 @@
namespace Sasalka;
/// <summary>
/// Базовый класс для предметов, которые используют патроны
/// Теперь используется только для совместимости со старой системой
/// </summary>
public abstract class AmmoUseableBase : UseableBase
{
private WeaponItemDefinition _cachedWeaponDef;
private InventoryItem _cachedAmmoItem;
protected InventoryItem AmmoItem => FindAmmoItem();
private InventoryItem FindAmmoItem()
protected override void OnUse()
{
var player = Dedugan.Local;
if (player?.Inventory == null)
{
return null;
}
// Кэшируем WeaponDefinition для избежания повторных вызовов
if (_cachedWeaponDef == null)
{
_cachedWeaponDef = GetWeaponDefinition();
if (_cachedWeaponDef == null)
{
return null;
}
}
// Проверяем кэшированный результат
if (_cachedAmmoItem != null && _cachedAmmoItem.Count > 0)
{
return _cachedAmmoItem;
}
// Ищем патроны
foreach (var item in player.Inventory.Items)
{
if (item.Definition is AmmoItemDefinition ammoDef && ammoDef.IsCompatibleWith(_cachedWeaponDef.AmmoType))
{
_cachedAmmoItem = item;
return item;
}
}
_cachedAmmoItem = null;
return null;
}
protected virtual WeaponItemDefinition GetWeaponDefinition()
{
// Переопределите в наследниках для возврата определения оружия
return null;
}
public override bool CanUse()
{
var ammo = AmmoItem;
var baseCanUse = base.CanUse();
var hasAmmo = ammo != null && ammo.Count > 0;
return baseCanUse && hasAmmo;
}
public override void Use()
{
if (!CanUse())
return;
OnUse();
var ammo = AmmoItem;
if (ammo != null)
{
// Уменьшаем количество патронов
if (ammo.TryRemoveCount(1))
{
// Если патроны закончились, удаляем предмет из инвентаря
if (ammo.Count <= 0)
{
Dedugan.Local.Inventory.RemoveItem(ammo);
_cachedAmmoItem = null; // Очищаем кэш
}
}
}
// Базовая реализация - ничего не делает
// Логика использования патронов теперь в BaseWeapon
}
}

View File

@ -18,7 +18,9 @@ public sealed class PickupItem : InteractionButton
// Устанавливаем правильную метку для предмета
if ( GameObject.Components.TryGet<InventoryItem>( out var inventoryItem ) )
{
Label = inventoryItem.Definition?.Name ?? "Подобрать";
Label = inventoryItem.Definition?.Name != ""
? $"{inventoryItem.Definition.Name} x{inventoryItem.Count}"
: "Подобрать";
}
}

View File

@ -10,33 +10,17 @@ public sealed partial class Dedugan : Component
[Sync] private bool InAds { get; set; } = false;
private AttachmentSlotResolver _resolver;
// Автоматическая стрельба
private bool _isShooting = false;
private TimeSince _lastShootTime = 0f;
void InventoryStart()
{
if (!Network.IsOwner) return;
if ( !Network.IsOwner ) return;
// Создаем инвентарь как компонент
Inventory = GameObject.Components.GetOrCreate<Inventar>();
_resolver = new AttachmentSlotResolver(Renderer.GetAttachmentObject);
// Добавляем тестовые предметы (раскомментируйте для тестирования)
var clothingItem = new InventoryItem
{
Definition = ResourceLibrary.Get<ClothingItemDefinition>("Items/Cloth/cloth_pijama.clitem")
};
Inventory.AddItem(clothingItem);
var weaponItem = new InventoryItem
{
Definition = ResourceLibrary.Get<WeaponItemDefinition>("Items/pistol_test.weapon")
};
Inventory.AddItem(weaponItem);
var ammoItem = new InventoryItem
{
Definition = ResourceLibrary.Get<AmmoItemDefinition>("Items/pistol_ammo.inv")
};
ammoItem.Count = 30;
Inventory.AddItem(ammoItem);
_resolver = new AttachmentSlotResolver( Renderer.GetAttachmentObject );
Inventory.OnEquipped += OnItemEquipped;
Inventory.OnUnEquipped += OnItemUnEquipped;
@ -44,29 +28,29 @@ public sealed partial class Dedugan : Component
Inventory.OnItemRemoved += OnItemRemoved;
}
private void OnItemEquipped(InventoryItem item)
private void OnItemEquipped( InventoryItem item )
{
// Очищаем кэши при экипировке предмета
_useableCache.Clear();
_resolver?.ClearCache();
if (item?.Definition is WeaponItemDefinition weaponDef && weaponDef.Prefab.IsValid())
if ( item?.Definition is WeaponItemDefinition weaponDef && weaponDef.Prefab.IsValid() )
{
var go = weaponDef.Prefab.Clone();
AnimationHelper.HoldType = weaponDef.HoldType;
switch (weaponDef.Slot)
switch ( weaponDef.Slot )
{
case Inventar.InventorySlot.LeftHand | Inventar.InventorySlot.RightHand:
case Inventar.InventorySlot.RightHand:
go.Parent = Renderer.GetAttachmentObject("hold_R");
go.Parent = Renderer.GetAttachmentObject( "hold_R" );
break;
case Inventar.InventorySlot.LeftHand:
go.Parent = Renderer.GetAttachmentObject("hold_L");
go.Parent = Renderer.GetAttachmentObject( "hold_L" );
break;
default:
go.Parent = Renderer.GetAttachmentObject("forward_reference_modelspace");
go.Parent = Renderer.GetAttachmentObject( "forward_reference_modelspace" );
break;
}
@ -74,9 +58,11 @@ public sealed partial class Dedugan : Component
go.LocalRotation = weaponDef.WeaponDefinition.Rotation;
go.LocalScale = weaponDef.WeaponDefinition.Scale;
if (go.Components.TryGet<UseableBase>(out var useable))
// Получаем компонент оружия и вызываем экипировку
if ( go.Components.TryGet<BaseWeapon>( out var weapon ) )
{
useable.Equipped = true;
weapon.OnEquipped();
_useableCache[weaponDef.Slot] = (go, weapon);
}
go.NetworkSpawn();
@ -90,65 +76,70 @@ public sealed partial class Dedugan : Component
};
AnimationHelper.Handedness = hand;
RpcSetHoldAnimation(weaponDef.HoldType, hand);
RpcSetHoldAnimation( weaponDef.HoldType, hand );
InAds = true;
}
else if (item?.Definition is ClothingItemDefinition clothingDef)
else if ( item?.Definition is ClothingItemDefinition clothingDef )
{
WearWorkshop(new List<string>() { clothingDef.ClothUrl });
WearWorkshop( new List<string>() { clothingDef.ClothUrl } );
}
}
private void OnItemUnEquipped(InventoryItem item)
private void OnItemUnEquipped( InventoryItem item )
{
// Очищаем кэши при снятии предмета
_useableCache.Clear();
_resolver?.ClearCache();
if (item?.Definition is WeaponItemDefinition weaponDef && weaponDef.Prefab.IsValid())
if ( item?.Definition is WeaponItemDefinition weaponDef && weaponDef.Prefab.IsValid() )
{
switch (weaponDef.Slot)
// Вызываем OnUnEquipped для оружия
if ( _useableCache.TryGetValue( weaponDef.Slot, out var cached ) )
{
if ( cached.useable is BaseWeapon weapon )
{
weapon.OnUnEquipped();
}
}
switch ( weaponDef.Slot )
{
case Inventar.InventorySlot.LeftHand | Inventar.InventorySlot.RightHand:
case Inventar.InventorySlot.RightHand:
case Inventar.InventorySlot.LeftHand:
var attachmentName = !weaponDef.Slot.HasFlag(Inventar.InventorySlot.RightHand)
var attachmentName = !weaponDef.Slot.HasFlag( Inventar.InventorySlot.RightHand )
? "hold_L"
: "hold_R";
Renderer.GetAttachmentObject(attachmentName).Children.ForEach(child => child.Destroy());
RpcSetHoldAnimation(CitizenAnimationHelper.HoldTypes.None, CitizenAnimationHelper.Hand.Both);
Renderer.GetAttachmentObject( attachmentName ).Children.ForEach( child => child.Destroy() );
RpcSetHoldAnimation( CitizenAnimationHelper.HoldTypes.None, CitizenAnimationHelper.Hand.Both );
break;
default:
Renderer.GetAttachmentObject("forward_reference_modelspace").Children
.ForEach(child => child.Destroy());
Renderer.GetAttachmentObject( "forward_reference_modelspace" ).Children
.ForEach( child => child.Destroy() );
break;
}
InAds = false;
}
else if (item?.Definition is ClothingItemDefinition clothingDef)
else if ( item?.Definition is ClothingItemDefinition clothingDef )
{
StripByName(clothingDef.Description);
StripByName( clothingDef.Description );
}
}
private void OnItemAdded(InventoryItem item)
private void OnItemAdded( InventoryItem item )
{
// Очищаем кэши при добавлении предмета
_useableCache.Clear();
_resolver?.ClearCache();
// Кэш не очищаем при добавлении предметов, чтобы не нарушить работу оружия
}
private void OnItemRemoved(InventoryItem item)
private void OnItemRemoved( InventoryItem item )
{
// Очищаем кэши при удалении предмета
_useableCache.Clear();
_resolver?.ClearCache();
// Кэш не очищаем при удалении предметов, чтобы не нарушить работу оружия
}
[Rpc.Broadcast]
public void RpcSetHoldAnimation(CitizenAnimationHelper.HoldTypes HoldType, CitizenAnimationHelper.Hand hand)
public void RpcSetHoldAnimation( CitizenAnimationHelper.HoldTypes HoldType, CitizenAnimationHelper.Hand hand )
{
AnimationHelper.HoldType = HoldType;
AnimationHelper.Handedness = hand;
@ -156,59 +147,158 @@ public sealed partial class Dedugan : Component
void InventoryUpdate()
{
if (!Network.IsOwner) return;
if ( !Network.IsOwner ) return;
if (Input.Pressed("Attack1"))
// Обработка автоматической стрельбы
HandleAutomaticShooting();
// Обработка перезарядки
if ( Input.Pressed( "Reload" ) )
{
if (UseSystem.TryUse(this))
{
Attack();
}
TryReloadWeapon();
}
}
public IEnumerable<IUseable> GetUsables()
/// <summary>
/// Обработка автоматической стрельбы
/// </summary>
private void HandleAutomaticShooting()
{
// Кэшируем слоты для избежания повторного создания массива
var slots = new[] { Inventar.InventorySlot.LeftHand, Inventar.InventorySlot.RightHand };
var weapon = GetEquippedWeapon();
if ( weapon == null ) return;
foreach (var slot in slots)
var weaponDef = weapon.GetWeaponDefinition();
if ( weaponDef == null ) return;
// Начало стрельбы
if ( Input.Pressed( "Attack1" ) )
{
if (!Inventory.EquippedItems.TryGetValue(slot, out var item))
{
continue;
}
_isShooting = true;
TryUseWeapon();
}
var holder = _resolver.GetSlotObject(slot);
if (holder == null) continue;
// Продолжение стрельбы (только если оружие автоматическое)
if ( Input.Down( "Attack1" ) && _isShooting && weaponDef.IsAutomatic )
{
TryUseWeapon();
}
var heldObject = holder.Children.FirstOrDefault();
if (heldObject == null)
{
continue;
}
// Остановка стрельбы
if ( Input.Released( "Attack1" ) )
{
_isShooting = false;
}
}
// Проверяем кэш
if (_useableCache.TryGetValue(slot, out var cached) && cached.obj == heldObject)
{
if (cached.useable != null)
yield return cached.useable;
}
else
{
var useable = heldObject.Components.Get<IUseable>();
_useableCache[slot] = (heldObject, useable);
/// <summary>
/// Попытка использования экипированного предмета
/// </summary>
private void TryUseWeapon()
{
var useable = GetEquippedUseable();
if ( useable != null && useable.CanUse() )
{
useable.Use();
Attack(); // Анимация атаки
}
}
if (useable != null)
yield return useable;
/// <summary>
/// Попытка перезарядки экипированного оружия
/// </summary>
private void TryReloadWeapon()
{
var weapon = GetEquippedWeapon();
if ( weapon != null && !weapon.IsReloading )
{
weapon.StartReload();
}
}
/// <summary>
/// Получить экипированный используемый предмет
/// </summary>
private IUseable GetEquippedUseable()
{
// Проверяем правую руку
if ( Inventory.EquippedItems.TryGetValue( Inventar.InventorySlot.RightHand, out var rightHandItem ) )
{
if ( _useableCache.TryGetValue( Inventar.InventorySlot.RightHand, out var cached ) &&
cached.useable != null )
{
return cached.useable;
}
}
// Проверяем левую руку
if ( Inventory.EquippedItems.TryGetValue( Inventar.InventorySlot.LeftHand, out var leftHandItem ) )
{
if ( _useableCache.TryGetValue( Inventar.InventorySlot.LeftHand, out var cached ) &&
cached.useable != null )
{
return cached.useable;
}
}
// Проверяем обе руки
if ( Inventory.EquippedItems.TryGetValue( Inventar.InventorySlot.LeftHand | Inventar.InventorySlot.RightHand,
out var bothHandsItem ) )
{
if ( _useableCache.TryGetValue( Inventar.InventorySlot.LeftHand | Inventar.InventorySlot.RightHand,
out var cached ) && cached.useable != null )
{
return cached.useable;
}
}
return null;
}
/// <summary>
/// Получить экипированное оружие
/// </summary>
private BaseWeapon GetEquippedWeapon()
{
var useable = GetEquippedUseable();
return useable as BaseWeapon;
}
/// <summary>
/// Получить информацию о патронах для UI
/// </summary>
public (int current, int max, int totalInInventory) GetAmmoInfo()
{
var weapon = GetEquippedWeapon();
if ( weapon == null )
{
return (0, 0, 0);
}
return weapon.GetAmmoInfo();
}
/// <summary>
/// Получить общее количество патронов в инвентаре (для UI)
/// </summary>
public int GetTotalInInventory()
{
var ammoInfo = GetAmmoInfo();
return ammoInfo.totalInInventory;
}
/// <summary>
/// Получить прогресс перезарядки
/// </summary>
public float GetReloadProgress()
{
var weapon = GetEquippedWeapon();
return weapon?.GetReloadProgress() ?? 1f;
}
[Rpc.Broadcast]
void Attack()
{
Renderer.Set("b_attack", true);
Renderer.Set( "b_attack", true );
}
}

View File

@ -3,6 +3,8 @@ using Sandbox;
using Sandbox.Citizen;
using Sasalka;
using ShrimpleCharacterController;
using System.Collections.Generic;
using System.Linq;
public sealed partial class Dedugan : Component, IUseContext, Component.INetworkSpawn
{
@ -121,4 +123,14 @@ public sealed partial class Dedugan : Component, IUseContext, Component.INetwork
{
DrawDebugGizmos();
}
/// <summary>
/// Реализация интерфейса IUseContext
/// Возвращает список используемых предметов
/// </summary>
public IEnumerable<IUseable> GetUsables()
{
// Возвращаем пустой список, так как теперь оружие управляется через новую систему
return Enumerable.Empty<IUseable>();
}
}

View File

@ -5,6 +5,24 @@
<root>
<div class="crosshair"></div>
<div class="@( HasWeapon ? "" : "hidden" )">
<div class="ammo-counter">
<div class="ammo-info">
<div class="current-ammo">@CurrentAmmo</div>
<div class="separator">/</div>
<div class="max-ammo">@TotalInInventory</div>
@* <div class="inventory-ammo">(@MaxAmmo - вместимость магазина)</div> *@
</div>
</div>
@if ( IsReloading )
{
<div class="reload-progress">
<div class="reload-bar" style="width: @( ReloadProgress * 100 )%"></div>
</div>
}
</div>
</root>
<style>
@ -19,7 +37,107 @@
transform: translate(-50%, -50%);
pointer-events: none;
}
.ammo-counter {
position: absolute;
bottom: 100px;
right: 50px;
background: rgba(0, 0, 0, 0.7);
border-radius: 8px;
padding: 10px 15px;
color: white;
font-family: 'Arial', sans-serif;
font-weight: bold;
font-size: 18px;
min-width: 80px;
text-align: center;
.ammo-info {
display: flex;
justify-content: center;
align-items: center;
gap: 5px;
.current-ammo {
color: #ff6b6b;
}
.separator {
color: #666;
}
.max-ammo {
color: #999;
}
.inventory-ammo {
color: #4CAF50;
font-size: 14px;
margin-left: 8px;
}
}
}
.reload-progress {
position: absolute;
bottom: 100px;
right: 50px;
height: 4px;
width: 50px;
background: rgba(255, 255, 255, 0.2);
border-radius: 2px;
overflow: hidden;
.reload-bar {
height: 100%;
background: linear-gradient(90deg, #ff6b6b, #ff8e8e);
transition: width 0.1s ease;
}
}
.hidden {
display: none;
}
</style>
@code {
private int CurrentAmmo { get; set; } = 0;
private int MaxAmmo { get; set; } = 0;
private bool IsReloading { get; set; } = false;
private float ReloadProgress { get; set; } = 0f;
private int TotalInInventory { get; set; } = 0;
private bool HasWeapon { get; set; } = false;
protected override void OnUpdate()
{
if ( Dedugan.Local == null ) return;
var ammoInfo = Dedugan.Local.GetAmmoInfo();
CurrentAmmo = ammoInfo.current;
MaxAmmo = ammoInfo.max;
TotalInInventory = ammoInfo.totalInInventory;
ReloadProgress = Dedugan.Local.GetReloadProgress();
IsReloading = ReloadProgress < 1f;
// Проверяем, есть ли оружие в руках (если MaxAmmo > 0, значит есть оружие)
HasWeapon = MaxAmmo > 0;
}
protected override int BuildHash()
{
if ( Dedugan.Local == null || !HasWeapon )
return -1;
var hash = new System.HashCode();
hash.Add( CurrentAmmo );
hash.Add( MaxAmmo );
hash.Add( TotalInInventory );
hash.Add( IsReloading );
hash.Add( ReloadProgress );
hash.Add( HasWeapon );
return hash.ToHashCode();
}
}

532
Code/Weapons/BaseWeapon.cs Normal file
View File

@ -0,0 +1,532 @@
using System.Threading.Tasks;
using Sandbox;
using Sandbox.Citizen;
using Sasalka;
using System.Collections.Generic;
namespace Sandbox.Weapons;
/// <summary>
/// Базовый класс для всех видов оружия
/// Содержит всю логику стрельбы и управления патронами
/// </summary>
public class BaseWeapon : InventoryItem, IUseable
{
[Property] public SkinnedModelRenderer GunRenderer { get; private set; }
[Property] public GameObject MuzzleLight { get; private set; }
[Property] public GameObject ParticlePrefab { get; set; }
[Property] public GameObject BloodParticle { get; set; }
[Property] public GameObject MuzzleFlashPrefab { get; set; }
[Property] public GameObject EjectShellPrefab { get; set; }
[Property] public GameObject MuzzleTransform { get; set; }
[Property] public GameObject EjectTransform { get; set; }
// Состояние оружия
[Sync] public int CurrentAmmo { get; set; }
[Sync] public bool IsReloading { get; set; }
[Sync] public TimeSince TimeSinceLastShot { get; set; }
[Sync] public TimeSince TimeSinceReloadStart { get; set; }
// Компоненты
private SoundPointComponent _sound;
private Rigidbody _rigidbody;
private PickupItem _pickupItem;
// Кэш для производительности
private WeaponItemDefinition _weaponDefinition;
private bool _isInitialized;
// IUseable реализация - Cooldown вычисляется на основе FireRate
public float Cooldown
{
get
{
var weaponDef = GetWeaponDefinition();
return weaponDef != null ? 1f / weaponDef.FireRate : 0.1f;
}
}
protected override void OnStart()
{
base.OnStart();
// Получаем компоненты
_sound = GameObject.GetComponent<SoundPointComponent>( true );
_pickupItem = GameObject.Components.Get<PickupItem>();
// Инициализируем оружие
InitializeWeapon();
}
protected override void OnUpdate()
{
base.OnUpdate();
if ( !IsValid || !Equipped ) return;
// Проверяем завершение перезарядки
if ( IsReloading && TimeSinceReloadStart >= GetWeaponDefinition()?.ReloadTime )
{
FinishReload();
}
// Обновляем эффекты
UpdateEffects();
}
/// <summary>
/// Инициализация оружия
/// </summary>
private void InitializeWeapon()
{
if ( _isInitialized ) return;
_weaponDefinition = Definition as WeaponItemDefinition;
if ( _weaponDefinition == null )
{
Log.Error( $"BaseWeapon: Definition is not WeaponItemDefinition for {GameObject.Name}" );
return;
}
// Оружие начинается с пустым магазином - патроны нужно зарядить
CurrentAmmo = 0;
_isInitialized = true;
}
/// <summary>
/// Получить определение оружия
/// </summary>
public WeaponItemDefinition GetWeaponDefinition()
{
return _weaponDefinition ??= Definition as WeaponItemDefinition;
}
/// <summary>
/// Экипировка оружия
/// </summary>
public override void OnEquipped()
{
base.OnEquipped();
// Получаем Rigidbody в момент экипировки
_rigidbody = GameObject.Components.Get<Rigidbody>();
if ( _rigidbody != null )
_rigidbody.Enabled = false;
if ( _pickupItem != null )
_pickupItem.Enabled = false;
}
/// <summary>
/// Снятие оружия
/// </summary>
public override void OnUnEquipped()
{
base.OnUnEquipped();
// Получаем Rigidbody в момент снятия
_rigidbody = GameObject.Components.Get<Rigidbody>();
if ( _rigidbody != null )
_rigidbody.Enabled = true;
if ( _pickupItem != null )
_pickupItem.Enabled = true;
}
// IUseable реализация
/// <summary>
/// Проверка возможности использования
/// </summary>
public virtual bool CanUse()
{
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return false;
return IsValid && Equipped && !IsReloading && TimeSinceLastShot >= 1f / weaponDef.FireRate;
}
/// <summary>
/// Использование оружия (выстрел)
/// </summary>
public virtual void Use()
{
if ( !CanUse() ) return;
TryShoot();
}
/// <summary>
/// Попытка выстрела
/// </summary>
public bool TryShoot()
{
if ( !CanShoot() ) return false;
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return false;
// Проверяем время между выстрелами из определения
if ( TimeSinceLastShot < 1f / weaponDef.FireRate ) return false;
// Проверяем патроны в магазине
if ( CurrentAmmo <= 0 )
{
return false;
}
// Выполняем выстрел
PerformShot();
return true;
}
/// <summary>
/// Проверка возможности выстрела
/// </summary>
public bool CanShoot()
{
if ( !IsValid || !Equipped || IsReloading ) return false;
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return false;
// Проверяем только патроны в магазине
return CurrentAmmo > 0 && TimeSinceLastShot >= 1f / weaponDef.FireRate;
}
/// <summary>
/// Проверка наличия патронов в инвентаре
/// </summary>
private bool HasAmmoInInventory()
{
var player = Dedugan.Local;
if ( player?.Inventory == null ) return false;
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return false;
foreach ( var item in player.Inventory.Items )
{
if ( item?.Definition is AmmoItemDefinition ammoDef && ammoDef.IsCompatibleWith( weaponDef.AmmoType ) )
{
if ( item.Count > 0 ) return true;
}
}
return false;
}
/// <summary>
/// Выполнение выстрела
/// </summary>
protected virtual void PerformShot()
{
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return;
// Уменьшаем патроны в магазине
CurrentAmmo--;
TimeSinceLastShot = 0;
// Эффекты выстрела
PlayShootEffects();
// Трассировка пули
PerformBulletTrace( weaponDef );
}
/// <summary>
/// Трассировка пули
/// </summary>
protected virtual void PerformBulletTrace( WeaponItemDefinition weaponDef )
{
var startPos = Scene.Camera.WorldPosition;
var direction = Scene.Camera.WorldRotation.Forward;
// Добавляем разброс
if ( weaponDef.Spread > 0 )
{
direction += Vector3.Random * weaponDef.Spread;
direction = direction.Normal;
}
var tr = Scene.Trace
.Ray( startPos, startPos + direction * weaponDef.Range )
.IgnoreGameObjectHierarchy( Dedugan.Local.GameObject )
.WithoutTags( "weapon" )
.UseHitboxes()
.Run();
if ( tr.Hit )
{
HandleHit( tr, weaponDef );
}
}
/// <summary>
/// Обработка попадания
/// </summary>
protected virtual void HandleHit( SceneTraceResult tr, WeaponItemDefinition weaponDef )
{
if ( tr.Hitbox != null )
{
var boneIndex = tr.Hitbox.Bone.Index;
var components = tr.GameObject.Components;
// Кэшируем компоненты для избежания повторных поисков
var dedugan = components.Get<Dedugan>();
var enemy = components.Get<Enemy>();
var hasTarget = dedugan.IsValid() || enemy.IsValid();
if ( hasTarget )
{
CreateHitEffects( tr.EndPosition, tr.Normal, true );
}
if ( dedugan.IsValid() )
{
dedugan.ReportHit( tr.Direction, boneIndex, (int)weaponDef.Damage );
}
if ( enemy.IsValid() )
{
enemy.ReportHit( tr.Direction, boneIndex, (int)weaponDef.Damage );
}
}
else
{
CreateHitEffects( tr.EndPosition, tr.Normal );
}
}
/// <summary>
/// Начать перезарядку
/// </summary>
public virtual void StartReload()
{
if ( IsReloading || CurrentAmmo >= GetWeaponDefinition()?.MagazineSize ) return;
IsReloading = true;
TimeSinceReloadStart = 0;
// Эффекты перезарядки
PlayReloadEffects();
}
/// <summary>
/// Завершить перезарядку
/// </summary>
protected virtual void FinishReload()
{
IsReloading = false;
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return;
// Загружаем патроны из инвентаря
LoadAmmoFromInventory( weaponDef.MagazineSize );
}
/// <summary>
/// Загрузить патроны из инвентаря
/// </summary>
private void LoadAmmoFromInventory( int maxAmmo )
{
var player = Dedugan.Local;
if ( player?.Inventory == null )
{
Log.Warning( "LoadAmmoFromInventory: Player or Inventory is null" );
return;
}
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null )
{
Log.Warning( "LoadAmmoFromInventory: Weapon definition is null" );
return;
}
// Проверяем, есть ли патроны в инвентаре
if ( !HasAmmoInInventory() )
{
return;
}
int ammoToLoad = maxAmmo - CurrentAmmo;
if ( ammoToLoad <= 0 )
{
return;
}
// Создаем копию списка для безопасной итерации
var itemsToProcess = player.Inventory.Items.ToList();
var itemsToRemove = new List<InventoryItem>();
int totalLoaded = 0;
foreach ( var item in itemsToProcess )
{
if ( item?.Definition is AmmoItemDefinition ammoDef && ammoDef.IsCompatibleWith( weaponDef.AmmoType ) )
{
if ( item.Count > 0 )
{
int canLoad = Math.Min( ammoToLoad, item.Count );
if ( item.TryRemoveCount( canLoad ) )
{
CurrentAmmo += canLoad;
ammoToLoad -= canLoad;
totalLoaded += canLoad;
// Если патроны закончились, помечаем для удаления
if ( item.Count <= 0 )
{
itemsToRemove.Add( item );
}
if ( ammoToLoad <= 0 )
{
break;
}
}
}
}
}
// Удаляем пустые предметы после итерации
foreach ( var item in itemsToRemove )
{
try
{
player.Inventory.RemoveItem( item );
}
catch ( System.Exception ex )
{
Log.Warning( $"LoadAmmoFromInventory: Failed to remove item {item.Definition.Name}: {ex.Message}" );
}
}
}
/// <summary>
/// Воспроизведение эффектов выстрела
/// </summary>
protected virtual void PlayShootEffects()
{
// Звук
_sound?.StartSound();
// Свет
if ( MuzzleLight != null )
{
MuzzleLight.Enabled = true;
GameTask.DelaySeconds( 0.05f ).ContinueWith( _ => MuzzleLight.Enabled = false );
}
// Анимация
if ( GunRenderer != null )
{
GunRenderer.Set( "Fire", true );
}
// Вспышка
if ( MuzzleFlashPrefab != null && MuzzleTransform != null )
{
var flash = MuzzleFlashPrefab.Clone( MuzzleTransform.WorldPosition, MuzzleTransform.WorldRotation );
DestroyAsync( flash, 0.1f );
}
// Гильза
if ( EjectShellPrefab != null && EjectTransform != null )
{
var shell = EjectShellPrefab.Clone( EjectTransform.WorldPosition, EjectTransform.WorldRotation );
DestroyAsync( shell, 3f );
}
}
/// <summary>
/// Воспроизведение эффектов перезарядки
/// </summary>
protected virtual void PlayReloadEffects()
{
// Можно добавить звук перезарядки
}
/// <summary>
/// Создание эффектов попадания
/// </summary>
[Rpc.Broadcast]
protected virtual void CreateHitEffects( Vector3 position, Vector3 normal, bool blood = false )
{
var rot = Rotation.LookAt( normal );
var effectPrefab = blood ? BloodParticle : ParticlePrefab;
if ( effectPrefab != null )
{
var effect = effectPrefab.Clone( position, rot );
DestroyAsync( effect, 0.5f );
}
}
/// <summary>
/// Обновление эффектов
/// </summary>
protected virtual void UpdateEffects()
{
// Можно добавить дополнительные эффекты
}
/// <summary>
/// Асинхронное уничтожение объекта
/// </summary>
protected async void DestroyAsync( GameObject go, float delay )
{
if ( go == null ) return;
await GameTask.DelaySeconds( delay );
if ( go.IsValid )
go.Destroy();
}
/// <summary>
/// Получить информацию о патронах для UI
/// </summary>
public (int current, int max, int totalInInventory) GetAmmoInfo()
{
var weaponDef = GetWeaponDefinition();
var totalInInventory = GetTotalAmmoInInventory();
return (CurrentAmmo, weaponDef?.MagazineSize ?? 0, totalInInventory);
}
/// <summary>
/// Получить общее количество патронов в инвентаре
/// </summary>
private int GetTotalAmmoInInventory()
{
var player = Dedugan.Local;
if ( player?.Inventory == null ) return 0;
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return 0;
int total = 0;
foreach ( var item in player.Inventory.Items )
{
if ( item?.Definition is AmmoItemDefinition ammoDef && ammoDef.IsCompatibleWith( weaponDef.AmmoType ) )
{
total += item.Count;
}
}
return total;
}
/// <summary>
/// Получить прогресс перезарядки (0-1)
/// </summary>
public float GetReloadProgress()
{
if ( !IsReloading ) return 1f;
var weaponDef = GetWeaponDefinition();
if ( weaponDef == null ) return 1f;
return MathX.Clamp( TimeSinceReloadStart / weaponDef.ReloadTime, 0f, 1f );
}
}

View File

@ -0,0 +1,72 @@
using Sandbox;
using Sasalka;
namespace Sandbox.Weapons;
/// <summary>
/// Пример фонарика - используемого предмета с собственной логикой
/// Показывает универсальность системы IUseable
/// </summary>
public sealed class Flashlight : Component, IUseable
{
[Property] public GameObject LightSource { get; set; }
[Property] public SoundPointComponent ToggleSound { get; set; }
[Property] public float Cooldown { get; set; } = 0.5f;
private bool _isOn = false;
private TimeSince _lastUseTime;
protected override void OnStart()
{
base.OnStart();
// Изначально фонарик выключен
if (LightSource != null)
{
LightSource.Enabled = false;
}
}
/// <summary>
/// Проверка возможности использования
/// </summary>
public bool CanUse()
{
return IsValid && _lastUseTime >= Cooldown;
}
/// <summary>
/// Использование фонарика (включение/выключение)
/// </summary>
public void Use()
{
if (!CanUse()) return;
_lastUseTime = 0;
ToggleLight();
}
/// <summary>
/// Переключение света
/// </summary>
private void ToggleLight()
{
_isOn = !_isOn;
if (LightSource != null)
{
LightSource.Enabled = _isOn;
}
// Воспроизводим звук
ToggleSound?.StartSound();
// Можно добавить дополнительные эффекты
Log.Info($"Фонарик {( _isOn ? "включен" : "выключен" )}");
}
/// <summary>
/// Получить состояние фонарика
/// </summary>
public bool IsOn => _isOn;
}

108
Code/Weapons/Pistol.cs Normal file
View File

@ -0,0 +1,108 @@
using Sandbox;
using Sasalka;
namespace Sandbox.Weapons;
/// <summary>
/// Конкретная реализация пистолета
/// Наследуется от BaseWeapon и может переопределять специфичное поведение
/// </summary>
public sealed class Pistol : BaseWeapon
{
[Property] public float RecoilForce { get; set; } = 5f;
[Property] public float RecoilRecoverySpeed { get; set; } = 2f;
private Vector3 _currentRecoil;
private Vector3 _targetRecoil;
protected override void OnStart()
{
base.OnStart();
// Специфичная инициализация для пистолета
_currentRecoil = Vector3.Zero;
_targetRecoil = Vector3.Zero;
}
protected override void OnUpdate()
{
base.OnUpdate();
// Восстановление отдачи
if (!IsReloading && Equipped)
{
RecoverRecoil();
}
}
/// <summary>
/// Переопределяем эффекты выстрела для пистолета
/// </summary>
protected override void PlayShootEffects()
{
base.PlayShootEffects();
// Добавляем отдачу
AddRecoil();
}
/// <summary>
/// Добавление отдачи
/// </summary>
private void AddRecoil()
{
var weaponDef = GetWeaponDefinition();
if (weaponDef == null) return;
// Вертикальная отдача
_targetRecoil += Vector3.Up * RecoilForce;
// Горизонтальная отдача (случайная)
_targetRecoil += Vector3.Random * RecoilForce * 0.3f;
// Применяем отдачу к камере
if (Dedugan.Local?.Camera != null)
{
var camera = Dedugan.Local.Camera;
camera.LocalRotation *= Rotation.From(new Angles(_targetRecoil.x, _targetRecoil.y, _targetRecoil.z));
}
}
/// <summary>
/// Восстановление отдачи
/// </summary>
private void RecoverRecoil()
{
if (_targetRecoil.Length < 0.1f) return;
_targetRecoil = Vector3.Lerp(_targetRecoil, Vector3.Zero, Time.Delta * RecoilRecoverySpeed);
// Применяем восстановление к камере
if (Dedugan.Local?.Camera != null)
{
var camera = Dedugan.Local.Camera;
camera.LocalRotation *= Rotation.From(new Angles(-_targetRecoil.x * Time.Delta * RecoilRecoverySpeed, -_targetRecoil.y * Time.Delta * RecoilRecoverySpeed, -_targetRecoil.z * Time.Delta * RecoilRecoverySpeed));
}
}
/// <summary>
/// Переопределяем трассировку для пистолета (можно добавить специфичную логику)
/// </summary>
protected override void PerformBulletTrace(WeaponItemDefinition weaponDef)
{
base.PerformBulletTrace(weaponDef);
// Дополнительная логика для пистолета может быть добавлена здесь
}
/// <summary>
/// Переопределяем эффекты перезарядки для пистолета
/// </summary>
protected override void PlayReloadEffects()
{
base.PlayReloadEffects();
// Специфичные эффекты перезарядки пистолета
// Например, звук перезарядки пистолета
}
}

265
Code/Weapons/README.md Normal file
View File

@ -0,0 +1,265 @@
# Универсальная система используемых предметов
## Обзор
Система построена на принципах наследования и интерфейсов. Любой предмет в руках может реализовывать интерфейс `IUseable` и иметь свою уникальную логику использования.
## Архитектура
### IUseable
Интерфейс для всех используемых предметов:
- `CanUse()` - проверка возможности использования
- `Use()` - выполнение действия
- `Cooldown` - время перезарядки между использованиями
### BaseWeapon
Базовый класс для оружия, **наследуется от InventoryItem** и реализует `IUseable`. Содержит:
- Логику стрельбы и трассировки пуль
- Управление патронами (магазин + инвентарь)
- Систему перезарядки
- Эффекты выстрела и попадания
- Автоматическую стрельбу
- **Физику** - автоматическое отключение RigidBody при экипировке
### Flashlight
Пример другого используемого предмета - фонарика. Показывает:
- Как создавать предметы с собственной логикой
- Переключение состояний (вкл/выкл)
- Звуковые эффекты
### WeaponFactory
Универсальная фабрика для создания любых используемых предметов.
## Ключевые особенности
### 1. Наследование от InventoryItem
- **BaseWeapon наследуется от InventoryItem** - не нужно вешать 2 компонента на префаб
- Один компонент = один предмет в инвентаре
- Автоматическое управление состоянием экипировки
### 2. Автоматическая стрельба
- Оружие стреляет автоматически при удержании кнопки мыши **только если IsAutomatic = true**
- Для полуавтоматического оружия (IsAutomatic = false) - только одиночные выстрелы
- **Частота стрельбы берется из WeaponItemDefinition.FireRate**
### 3. Система патронов
- **Оружие начинается с пустым магазином** - патроны нужно зарядить
- **Сохранение патронов в магазине** - при выбрасывании оружия патроны остаются
- Патроны хранятся в инвентаре как отдельные предметы
- **Стрельба зависит ТОЛЬКО от патронов в магазине** - CurrentAmmo
- **HUD показывает патроны в магазине** - не зависит от инвентаря
- **Патроны тратятся только из магазина при выстреле** - CurrentAmmo уменьшается
- **Патроны тратятся из инвентаря только при перезарядке** - загружаются в магазин
- **Перезарядка только вручную** - кнопка R или автоматически при пустом магазине
- **Безопасная обработка неполных магазинов** - загружается столько патронов, сколько есть в инвентаре
### 4. HUD и UI
- **Отображение патронов в магазине** (текущие/максимум)
- **Отображение патронов в инвентаре** (общее количество)
- **Прогресс перезарядки** в реальном времени
- Формат: `15/30 (45)` - где 15 в магазине, 30 максимум, 45 всего в инвентаре
### 5. Физика
- **Автоматическое отключение RigidBody при экипировке**
- **Включение физики при снятии оружия**
- Предметы не падают когда в руках
### 6. Настройка в префабах
- Не нужно создавать отдельные файлы для каждого оружия
- Настройка происходит прямо в инстансе префаба
- Компоненты добавляются автоматически
## Практическое использование
### 1. Создание оружия в редакторе
#### Шаг 1: Создание префаба
1. Создайте новый GameObject в сцене
2. Добавьте модель оружия (SkinnedModelRenderer)
3. Добавьте компонент `BaseWeapon`
4. Настройте параметры в инспекторе:
- `GunRenderer` - ссылка на рендерер оружия
- `MuzzleLight` - свет вспышки
- `ParticlePrefab` - эффекты попадания
- `BloodParticle` - эффекты крови
- `Cooldown` - время между выстрелами
#### Шаг 2: Создание WeaponItemDefinition
1. В Project Settings создайте новый ресурс типа "Weapon Item Definition"
2. Настройте параметры:
```
Name: "Pistol"
Slot: RightHand
HoldType: Pistol
Damage: 25
FireRate: 8
Range: 1000
MagazineSize: 15
AmmoType: "Pistol"
ReloadTime: 2.0
Spread: 0.02
```
3. Укажите префаб в поле `Prefab`
#### Шаг 3: Добавление в игру
```csharp
// В коде игрока или менеджера
var weaponDef = ResourceLibrary.Get<WeaponItemDefinition>("Items/pistol.weapon");
var weaponItem = WeaponFactory.CreateWeaponItem(weaponDef);
player.Inventory.AddItem(weaponItem);
```
### 2. Создание фонарика
#### Шаг 1: Создание префаба фонарика
1. Создайте GameObject с моделью фонарика
2. Добавьте компонент `Flashlight`
3. Настройте параметры:
- `LightSource` - GameObject с источником света
- `ToggleSound` - звук включения/выключения
- `Cooldown` - время между переключениями
#### Шаг 2: Создание ItemDefinition
```csharp
// Создайте BaseItemDefinition или WeaponItemDefinition
// Name: "Flashlight"
// Slot: LeftHand
// Prefab: ссылка на префаб фонарика
```
#### Шаг 3: Использование
```csharp
var flashlightDef = ResourceLibrary.Get<BaseItemDefinition>("Items/flashlight.item");
var flashlightItem = WeaponFactory.CreateItem(flashlightDef);
player.Inventory.AddItem(flashlightItem);
```
### 3. Создание собственного предмета
```csharp
// Создайте новый класс
public sealed class Medkit : Component, IUseable
{
[Property] public float Cooldown { get; set; } = 5f;
[Property] public int HealAmount { get; set; } = 50;
private TimeSince _lastUseTime;
public bool CanUse()
{
return IsValid && _lastUseTime >= Cooldown;
}
public void Use()
{
if (!CanUse()) return;
_lastUseTime = 0;
// Логика лечения
var player = Dedugan.Local;
if (player != null)
{
player.Health = Math.Min(player.Health + HealAmount, 100);
Log.Info($"Игрок вылечен на {HealAmount} HP");
}
}
}
```
## WeaponFactory - подробное руководство
### Основные методы:
#### 1. `CreateUseableItem(BaseItemDefinition, InventoryItem)`
Создает любой используемый предмет:
```csharp
var itemDef = ResourceLibrary.Get<BaseItemDefinition>("path/to/item");
var item = WeaponFactory.CreateUseableItem(itemDef, inventoryItem);
```
#### 2. `CreateWeapon(WeaponItemDefinition, InventoryItem)`
Создает оружие (для обратной совместимости):
```csharp
var weaponDef = ResourceLibrary.Get<WeaponItemDefinition>("path/to/weapon");
var weapon = WeaponFactory.CreateWeapon(weaponDef, inventoryItem);
```
#### 3. `CreateItem(BaseItemDefinition)`
Создает предмет для инвентаря:
```csharp
var itemDef = ResourceLibrary.Get<BaseItemDefinition>("path/to/item");
var inventoryItem = WeaponFactory.CreateItem(itemDef);
```
### Автоматическое определение типа
WeaponFactory автоматически определяет тип предмета по имени:
- **Оружие**: содержит "pistol", "rifle", "gun" → создается `BaseWeapon`
- **Фонарик**: содержит "flashlight", "light" → создается `Flashlight`
- **По умолчанию**: создается `BaseWeapon`
### Примеры использования
#### Создание пистолета:
```csharp
// 1. Создаем предмет для инвентаря
var pistolDef = ResourceLibrary.Get<WeaponItemDefinition>("Items/pistol.weapon");
var pistolItem = WeaponFactory.CreateWeaponItem(pistolDef);
// 2. Добавляем в инвентарь
player.Inventory.AddItem(pistolItem);
// 3. Экипируем
player.Inventory.EquipItem(pistolItem);
```
#### Создание фонарика:
```csharp
// 1. Создаем предмет
var flashlightDef = ResourceLibrary.Get<BaseItemDefinition>("Items/flashlight.item");
var flashlightItem = WeaponFactory.CreateItem(flashlightDef);
// 2. Добавляем в инвентарь
player.Inventory.AddItem(flashlightItem);
```
#### Создание аптечки:
```csharp
// 1. Создаем предмет
var medkitDef = ResourceLibrary.Get<BaseItemDefinition>("Items/medkit.item");
var medkitItem = WeaponFactory.CreateItem(medkitDef);
// 2. Добавляем в инвентарь
player.Inventory.AddItem(medkitItem);
```
## Настройка в префабах
### Для оружия:
1. Добавьте компонент `BaseWeapon`
2. Настройте все необходимые ссылки (рендерер, звуки, эффекты)
3. Установите параметры стрельбы (Cooldown, FireRate и т.д.)
### Для других предметов:
1. Добавьте компонент, реализующий `IUseable`
2. Настройте специфичные параметры
3. Реализуйте логику в методах `CanUse()` и `Use()`
## Преимущества системы
1. **Универсальность** - один интерфейс для всех предметов
2. **Гибкость** - каждый предмет может иметь свою логику
3. **Простота** - настройка в префабах, без создания отдельных файлов
4. **Расширяемость** - легко добавлять новые типы предметов
5. **Производительность** - кэширование и оптимизация
6. **Читаемость** - понятная структура и документация
## Примеры предметов
- **Оружие** - стрельба, перезарядка, патроны
- **Фонарик** - включение/выключение света
- **Аптечка** - лечение игрока
- **Инструменты** - ремонт, строительство
- **Еда** - восстановление здоровья/голода

View File

@ -1,118 +0,0 @@
using System.Threading.Tasks;
using Sandbox.UI;
using Sasalka;
namespace Sandbox.Weapons;
public sealed class Weapon : AmmoUseableBase
{
[Property] public SkinnedModelRenderer GunRenderer { get; private set; }
[Property] public GameObject MuzzleLight { get; private set; }
[Property] public GameObject particlePrefab { get; set; }
[Property] public GameObject bloodParticle { get; set; }
[Property] public WeaponItemDefinition WeaponDefinition { get; set; }
private SoundPointComponent _sound;
private Rigidbody _rigidbody;
protected override void OnStart()
{
base.OnStart();
_sound = GameObject.GetComponent<SoundPointComponent>(true);
}
public override void OnEquipped()
{
_rigidbody = GameObject.Components.Get<Rigidbody>();
_rigidbody.Enabled = false;
GameObject.Components.Get<PickupItem>().Enabled = false;
}
protected override WeaponItemDefinition GetWeaponDefinition()
{
return WeaponDefinition;
}
public void Attack()
{
AttackEffects();
Vector3 startPos = Scene.Camera.WorldPosition;
Vector3 dir = Scene.Camera.WorldRotation.Forward;
float maxDistance = WeaponDefinition?.Range ?? 1000f;
var tr = Scene.Trace
.Ray(startPos, startPos + dir * maxDistance)
.IgnoreGameObjectHierarchy(Dedugan.Local.GameObject)
.WithoutTags("weapon")
.UseHitboxes()
.Run();
if (tr.Hit)
{
if (tr.Hitbox != null)
{
var boneIndex = tr.Hitbox.Bone.Index;
var components = tr.GameObject.Components;
// Кэшируем компоненты для избежания повторных поисков
var dedugan = components.Get<Dedugan>();
var enemy = components.Get<Enemy>();
var hasTarget = dedugan.IsValid() || enemy.IsValid();
if (hasTarget)
{
CreateHitEffects(tr.EndPosition, tr.Normal, true);
}
if (dedugan.IsValid())
{
dedugan.ReportHit(dir, boneIndex);
}
if (enemy.IsValid())
{
enemy.ReportHit(dir, boneIndex);
}
}
else
{
CreateHitEffects(tr.EndPosition, tr.Normal);
}
}
}
[Rpc.Broadcast]
private void CreateHitEffects(Vector3 position, Vector3 normal, bool blood = false)
{
var rot = Rotation.LookAt(normal);
DestroyAsync(
blood
? bloodParticle.Clone(position, rot)
: particlePrefab.Clone(position, rot), 0.5f);
}
async void DestroyAsync(GameObject go, float delay)
{
await GameTask.DelaySeconds(delay);
go.Destroy();
}
[Rpc.Broadcast]
public void AttackEffects()
{
_sound?.StartSound();
MuzzleLight.Enabled = true;
GunRenderer.Set("Fire", true);
GameTask.DelaySeconds(0.05f).ContinueWith((_) =>
{
MuzzleLight.Enabled = false;
});
}
protected override void OnUse()
{
Attack();
}
}

View File

@ -0,0 +1,114 @@
using Sandbox;
using Sasalka;
namespace Sandbox.Weapons;
/// <summary>
/// Фабрика для создания используемых предметов с правильной настройкой компонентов
/// </summary>
public static class WeaponFactory
{
/// <summary>
/// Создать используемый предмет с правильной настройкой
/// </summary>
public static GameObject CreateUseableItem(BaseItemDefinition itemDef, InventoryItem inventoryItem = null)
{
if (itemDef?.Prefab == null) return null;
var itemGo = itemDef.Prefab.Clone();
// Проверяем, есть ли уже компонент оружия
if (!itemGo.Components.TryGet<BaseWeapon>(out var weapon))
{
// Определяем тип предмета по имени или другим параметрам
if (itemDef.Name.ToLower().Contains("pistol") || itemDef.Name.ToLower().Contains("rifle") || itemDef.Name.ToLower().Contains("gun"))
{
// Создаем оружие как InventoryItem
weapon = itemGo.Components.Create<BaseWeapon>();
weapon.Definition = itemDef;
}
else if (itemDef.Name.ToLower().Contains("flashlight") || itemDef.Name.ToLower().Contains("light"))
{
// Создаем фонарик
var flashlight = itemGo.Components.Create<Flashlight>();
}
else
{
// По умолчанию создаем базовое оружие
weapon = itemGo.Components.Create<BaseWeapon>();
weapon.Definition = itemDef;
}
}
// Настраиваем компоненты
SetupItemComponents(itemGo, itemDef);
return itemGo;
}
/// <summary>
/// Создать оружие с правильной настройкой (для обратной совместимости)
/// </summary>
public static GameObject CreateWeapon(WeaponItemDefinition weaponDef, InventoryItem inventoryItem = null)
{
return CreateUseableItem(weaponDef, inventoryItem);
}
/// <summary>
/// Настройка компонентов предмета
/// </summary>
private static void SetupItemComponents(GameObject itemGo, BaseItemDefinition itemDef)
{
// Настраиваем рендерер
if (itemGo.Components.TryGet<SkinnedModelRenderer>(out var renderer))
{
// Можно добавить специфичную настройку рендерера
}
// Настраиваем звук
if (itemGo.Components.TryGet<SoundPointComponent>(out var sound))
{
// Можно добавить специфичную настройку звука
}
// Настраиваем физику
if (itemGo.Components.TryGet<Rigidbody>(out var rigidbody))
{
// Можно добавить специфичную настройку физики
}
}
/// <summary>
/// Создать предмет для инвентаря
/// </summary>
public static InventoryItem CreateItem(BaseItemDefinition itemDef)
{
// Для оружия создаем BaseWeapon, для остального - обычный InventoryItem
if (itemDef is WeaponItemDefinition)
{
return new BaseWeapon
{
Definition = itemDef,
Count = 1
};
}
return new InventoryItem
{
Definition = itemDef,
Count = 1
};
}
/// <summary>
/// Создать предмет оружия для инвентаря (для обратной совместимости)
/// </summary>
public static InventoryItem CreateWeaponItem(WeaponItemDefinition weaponDef)
{
return new BaseWeapon
{
Definition = weaponDef,
Count = 1
};
}
}