Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemExplosivesBlockBehavior.cs
浏览该文件的文档.
1using System.Globalization;
2using Engine;
3using Engine.Audio;
5
6namespace Game {
8 public class ExplosiveData {
9 public Point3 Point;
10
11 public float TimeToExplosion;
12
14 }
15
17
19
21
23
25
26 public Random m_random = new();
27
28 public Dictionary<Point3, ExplosiveData> m_explosiveDataByPoint = [];
29
31
33
34 public override int[] HandledBlocks => [];
35
36 public bool IgniteFuse(int x, int y, int z) {
37 int cellContents = m_subsystemTerrain.Terrain.GetCellContents(x, y, z);
38 if (BlocksManager.Blocks[cellContents] is GunpowderKegBlock) {
39 AddExplosive(new Point3(x, y, z), m_random.Float(6f, 7f));
40 return true;
41 }
42 if (BlocksManager.Blocks[cellContents] is DetonatorBlock) {
43 AddExplosive(new Point3(x, y, z), m_random.Float(0.8f, 1.2f));
44 return true;
45 }
46 return false;
47 }
48
49 public virtual void Update(float dt) {
50 float num = float.MaxValue;
51 if (m_explosiveDataByPoint.Count > 0) {
52 ExplosiveData[] array = m_explosiveDataByPoint.Values.ToArray();
53 foreach (ExplosiveData explosiveData in array) {
54 Point3 point = explosiveData.Point;
55 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(point.X, point.Y, point.Z);
56 int num2 = Terrain.ExtractContents(cellValue);
57 Block block = BlocksManager.Blocks[num2];
58 if (explosiveData.FuseParticleSystem == null) {
59 if (block is GunpowderKegBlock gunpowderKegBlock) {
60 explosiveData.FuseParticleSystem = new FuseParticleSystem(
61 new Vector3(point.X, point.Y, point.Z) + gunpowderKegBlock.FuseOffset
62 );
63 m_subsystemParticles.AddParticleSystem(explosiveData.FuseParticleSystem);
64 }
65 }
66 explosiveData.TimeToExplosion -= dt;
67 if (explosiveData.TimeToExplosion <= 0f) {
68 m_subsystemExplosions.TryExplodeBlock(explosiveData.Point.X, explosiveData.Point.Y, explosiveData.Point.Z, cellValue);
69 }
70 float x = m_subsystemAudio.CalculateListenerDistance(new Vector3(point.X, point.Y, point.Z) + new Vector3(0.5f));
71 num = MathUtils.Min(num, x);
72 }
73 }
74 if (m_fuseSound != null) {
75 m_fuseSound.Volume = SettingsManager.SoundsVolume * m_subsystemAudio.CalculateVolume(num, 2f);
77 m_fuseSound.Play();
78 }
79 else {
80 m_fuseSound.Pause();
81 }
82 }
83 }
84
85 public override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ) {
86 if (m_subsystemFireBlockBehavior.IsCellOnFire(x, y, z)) {
87 IgniteFuse(x, y, z);
88 }
89 }
90
91 public override void OnBlockRemoved(int value, int newValue, int x, int y, int z) {
92 Point3 point = new(x, y, z);
93 RemoveExplosive(point);
94 }
95
96 public override void OnChunkDiscarding(TerrainChunk chunk) {
97 List<Point3> list = new();
98 foreach (Point3 key in m_explosiveDataByPoint.Keys) {
99 if (key.X >= chunk.Origin.X
100 && key.X < chunk.Origin.X + 16
101 && key.Z >= chunk.Origin.Y
102 && key.Z < chunk.Origin.Y + 16) {
103 list.Add(key);
104 }
105 }
106 foreach (Point3 item in list) {
107 RemoveExplosive(item);
108 }
109 }
110
111 public override void OnExplosion(int value, int x, int y, int z, float damage) {
112 int num = Terrain.ExtractContents(value);
113 Block block = BlocksManager.Blocks[num];
114 if (block.GetExplosionPressure(value) > 0f
115 && MathUtils.Saturate(damage / block.ExplosionResilience) > 0.01f
116 && m_random.Float(0f, 1f) < 0.5f) {
117 IgniteFuse(x, y, z);
118 }
119 }
120
121 public override void Load(ValuesDictionary valuesDictionary) {
122 base.Load(valuesDictionary);
123 m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
124 m_subsystemParticles = Project.FindSubsystem<SubsystemParticles>(true);
127 m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
128 m_fuseSound = m_subsystemAudio.CreateSound("Audio/Fuse");
129 m_fuseSound.IsLooped = true;
130 foreach (ValuesDictionary value3 in valuesDictionary.GetValue<ValuesDictionary>("Explosives").Values) {
131 Point3 value = value3.GetValue<Point3>("Point");
132 float value2 = value3.GetValue<float>("TimeToExplosion");
133 AddExplosive(value, value2);
134 }
135 }
136
137 public override void Save(ValuesDictionary valuesDictionary) {
138 base.Save(valuesDictionary);
139 int num = 0;
140 ValuesDictionary valuesDictionary2 = new();
141 valuesDictionary.SetValue("Explosives", valuesDictionary2);
142 foreach (ExplosiveData value in m_explosiveDataByPoint.Values) {
143 ValuesDictionary valuesDictionary3 = new();
144 valuesDictionary2.SetValue(num++.ToString(CultureInfo.InvariantCulture), valuesDictionary3);
145 valuesDictionary3.SetValue("Point", value.Point);
146 valuesDictionary3.SetValue("TimeToExplosion", value.TimeToExplosion);
147 }
148 }
149
150 public override void Dispose() {
151 Utilities.Dispose(ref m_fuseSound);
152 }
153
154 public void AddExplosive(Point3 point, float timeToExplosion) {
155 if (!m_explosiveDataByPoint.ContainsKey(point)) {
156 ExplosiveData explosiveData = new() { Point = point, TimeToExplosion = timeToExplosion };
157 m_explosiveDataByPoint.Add(point, explosiveData);
158 }
159 }
160
161 public void RemoveExplosive(Point3 point) {
162 if (m_explosiveDataByPoint.Remove(point, out ExplosiveData value)) {
163 if (value.FuseParticleSystem != null) {
164 m_subsystemParticles.RemoveParticleSystem(value.FuseParticleSystem);
165 }
166 }
167 }
168 }
169}
Engine.Vector3 Vector3
static int Min(int x1, int x2)
static float Saturate(float x)
static float MinAudibleVolume
float ExplosionResilience
virtual float GetExplosionPressure(int value)
override void Load(ValuesDictionary valuesDictionary)
override void OnNeighborBlockChanged(int x, int y, int z, int neighborX, int neighborY, int neighborZ)
void AddExplosive(Point3 point, float timeToExplosion)
override void Save(ValuesDictionary valuesDictionary)
override void OnBlockRemoved(int value, int newValue, int x, int y, int z)
override void OnExplosion(int value, int x, int y, int z, float damage)
static int ExtractContents(int value)
ValuesDictionary ValuesDictionary