Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
SubsystemProjectiles.cs
浏览该文件的文档.
1using System.Globalization;
2using Engine;
7
8namespace Game {
11
13
15
17
19
21
23
25
27
29
31
33
35
37
38 public List<Projectile> m_projectiles = [];
39
40 public List<Projectile> m_projectilesToRemove = [];
41
43
44 public Random m_random = new();
45
47
48 public const float BodyInflateAmount = 0.2f;
49
50 public static int[] m_drawOrders = [10];
51
52 public ReadOnlyList<Projectile> Projectiles => new(m_projectiles);
53
54 public int[] DrawOrders => m_drawOrders;
55
56 public virtual Action<Projectile> ProjectileAdded { get; set; }
57
58 public virtual Action<Projectile> ProjectileRemoved { get; set; }
59
61
62 readonly Lock m_lock = new();
63
64 public virtual Projectile AddProjectile(Projectile projectile) {
65 if (projectile == null) {
66 return null;
67 }
68 projectile.CreationTime = m_subsystemGameInfo.TotalElapsedGameTime;
69 projectile.IsInFluid = IsWater(projectile.Position);
71 "OnProjectileAdded",
72 loader => {
73 loader.OnProjectileAdded(this, ref projectile, null);
74 return false;
75 }
76 );
77 lock (m_lock) {
78 m_projectiles.Add(projectile);
79 }
80 if (projectile.Owner != null
81 && projectile.Owner.PlayerStats != null) {
82 projectile.Owner.PlayerStats.RangedAttacks++;
83 }
84 ProjectileAdded?.Invoke(projectile);
85 return projectile;
86 }
87
88 public virtual Projectile AddProjectile(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner) =>
89 AddProjectile<Projectile>(value, position, velocity, angularVelocity, owner);
90
91 public virtual Projectile CreateProjectile(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner) =>
92 CreateProjectile<Projectile>(value, position, velocity, angularVelocity, owner);
93
94 public virtual T CreateProjectile<T>(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
95 where T : Projectile, new() {
96 try {
97 T projectile = new();
98 projectile.InitializeData(
99 () => m_subsystemTerrain.Terrain,
101 () => m_subsystemSky.VisibilityRange,
102 () => m_subsystemSky.CalculateFog,
104 );
105 projectile.Initialize(value, position, velocity, angularVelocity, owner);
106 return projectile;
107 }
108 catch (Exception ex) {
109 Log.Error($"Projectile create error: {ex}");
110 return null;
111 }
112 }
113
114 public virtual T AddProjectile<T>(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
115 where T : Projectile, new() {
116 try {
117 T projectile = CreateProjectile<T>(value, position, velocity, angularVelocity, owner);
118 Projectile projectile2 = AddProjectile(projectile);
119 return projectile2 as T;
120 }
121 catch (Exception ex) {
122 Log.Error($"Projectile add error: {ex}");
123 return null;
124 }
125 }
126
127 public virtual Projectile FireProjectile(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner) =>
128 FireProjectile<Projectile>(value, position, velocity, angularVelocity, owner);
129
130 public virtual bool CanFireProjectile(int value, Vector3 position, Vector3 velocity, ComponentCreature owner, out Vector3 firePosition) {
131 int num = Terrain.ExtractContents(value);
132 Block block = BlocksManager.Blocks[num];
133 Vector3 v = Vector3.Normalize(velocity);
134 firePosition = position;
135 if (owner != null) {
136 Ray3 ray = new(position + v * 5f, -v);
137 BoundingBox boundingBox = owner.ComponentBody.BoundingBox;
138 boundingBox.Min -= new Vector3(0.4f);
139 boundingBox.Max += new Vector3(0.4f);
140 float? num2 = ray.Intersection(boundingBox);
141 if (num2.HasValue) {
142 if (num2.Value == 0f) {
143 firePosition = Vector3.Zero;
144 return false;
145 }
146 firePosition = position + v * (5f - num2.Value + 0.1f);
147 }
148 }
149 Vector3 end = firePosition + v * block.ProjectileTipOffset;
150 return !m_subsystemTerrain.Raycast(
151 position,
152 end,
153 false,
154 true,
155 (testValue, _) => BlocksManager.Blocks[Terrain.ExtractContents(testValue)].IsCollidable_(testValue)
156 )
157 .HasValue;
158 }
159
160 public virtual T FireProjectile<T>(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
161 where T : Projectile, new() {
162 if (CanFireProjectile(value, position, velocity, owner, out Vector3 firePosition)) {
163 T projectile = CreateProjectile<T>(value, firePosition, velocity, angularVelocity, owner);
164 FireProjectileFast(projectile);
165 return projectile;
166 }
167 return null;
168 }
169
170 public virtual void FireProjectileFast(Projectile projectile) {
171 projectile = AddProjectile(projectile);
172 if (projectile == null) {
173 return;
174 }
175 SubsystemBlockBehavior[] blockBehaviors = m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(projectile.Value));
176 for (int i = 0; i < blockBehaviors.Length; i++) {
177 blockBehaviors[i].OnFiredAsProjectile(projectile);
178 }
179 }
180
181 public virtual void AddTrail(Projectile projectile, Vector3 offset, ITrailParticleSystem particleSystem) {
182 RemoveTrail(projectile);
183 projectile.TrailParticleSystem = particleSystem;
184 projectile.TrailOffset = offset;
185 }
186
187 public virtual void RemoveTrail(Projectile projectile) {
188 if (projectile.TrailParticleSystem != null) {
189 if (m_subsystemParticles.ContainsParticleSystem((ParticleSystemBase)projectile.TrailParticleSystem)) {
190 m_subsystemParticles.RemoveParticleSystem((ParticleSystemBase)projectile.TrailParticleSystem);
191 }
192 projectile.TrailParticleSystem = null;
193 }
194 }
195
196 public virtual void Draw(Camera camera, int drawOrder) {
197 m_drawBlockEnvironmentData.SubsystemTerrain = m_subsystemTerrain;
198 m_drawBlockEnvironmentData.InWorldMatrix = Matrix.Identity;
199 for (int i = 0; i < m_projectiles.Count; i++) {
200 Projectile projectile = m_projectiles[i];
201 try {
202 projectile.Project = Project;
203 projectile.Draw(camera, drawOrder);
204 }
205 catch (Exception e) {
206 if (projectile.LogDrawError) {
207 Log.Error($"Projectile draw error: {e}");
208 projectile.LogDrawError = false;
209 }
210 }
211 }
213 }
214
215 public virtual void Update(float dt) {
216 lock (m_lock) {
217 foreach (Projectile projectile in m_projectiles) {
218 if (projectile != null) {
219 if (projectile.ToRemove) {
220 m_projectilesToRemove.Add(projectile);
221 }
222 else {
223 try {
224 projectile.Project = Project;
225 projectile.Update(dt);
226 }
227 catch (Exception ex) {
228 Log.Error("Projectile update error: ");
229 Log.Error(ex);
230 projectile.ToRemove = true;
231 }
232 }
233 }
234 }
235 foreach (Projectile item in m_projectilesToRemove) {
236 if (item.TrailParticleSystem != null) {
237 item.TrailParticleSystem.IsStopped = true;
238 }
239 item.OnRemove?.Invoke();
240 m_projectiles.Remove(item);
241 ProjectileRemoved?.Invoke(item);
242 }
243 m_projectilesToRemove.Clear();
244 }
245 }
246
247 public override void Load(ValuesDictionary valuesDictionary) {
248 m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
250 m_subsystemParticles = Project.FindSubsystem<SubsystemParticles>(true);
251 m_subsystemPickables = Project.FindSubsystem<SubsystemPickables>(true);
252 m_subsystemBodies = Project.FindSubsystem<SubsystemBodies>(true);
253 m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
254 m_subsystemSky = Project.FindSubsystem<SubsystemSky>(true);
255 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
256 m_subsystemNoise = Project.FindSubsystem<SubsystemNoise>(true);
258 m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(true);
262 foreach (ValuesDictionary item in valuesDictionary.GetValue<ValuesDictionary>("Projectiles").Values.Where(v => v is ValuesDictionary)) {
263 try {
264 string className = item.GetValue("Class", typeof(Projectile).FullName);
265 Type type = TypeCache.FindType(className, false, true);
266#pragma warning disable IL2072
267 Projectile projectile = (Projectile)Activator.CreateInstance(type);
268#pragma warning restore IL2072
269 if (projectile == null) {
270 continue;
271 }
272 projectile.Project = Project;
273 projectile.InitializeData(
274 () => m_subsystemTerrain.Terrain,
276 () => m_subsystemSky.VisibilityRange,
277 () => m_subsystemSky.CalculateFog,
279 );
280 projectile.Load(item);
282 "OnProjectileAdded",
283 loader => {
284 loader.OnProjectileAdded(this, ref projectile, item);
285 return false;
286 }
287 );
288 m_projectiles.Add(projectile);
289 }
290 catch (Exception ex) {
291 Log.Error("Projectile Loaded Error");
292 Log.Error(ex);
293 }
294 }
295 }
296
297 public override void Save(ValuesDictionary valuesDictionary) {
298 ValuesDictionary valuesDictionary2 = new();
299 valuesDictionary.SetValue("Projectiles", valuesDictionary2);
300 int num = 0;
301 foreach (Projectile projectile in m_projectiles) {
302 try {
303 ValuesDictionary valuesDictionary3 = new();
304 projectile.Save(this, valuesDictionary3);
305 valuesDictionary2.SetValue(num.ToString(CultureInfo.InvariantCulture), valuesDictionary3);
306 num++;
307 }
308 catch (Exception ex) {
309 Log.Error($"Projectile Save Error: {ex}");
310 }
311 }
312 }
313
314 public virtual bool IsWater(Vector3 position) {
315 int cellContents = m_subsystemTerrain.Terrain.GetCellContents(
316 Terrain.ToCell(position.X),
317 Terrain.ToCell(position.Y),
318 Terrain.ToCell(position.Z)
319 );
320 return BlocksManager.Blocks[cellContents] is FluidBlock;
321 }
322
323 [Obsolete("SubsystemProjectiles不再提供射弹更新,请转移到Projectile.Update()中")]
324 public virtual bool IsMagma(Vector3 position) {
325 int cellContents = m_subsystemTerrain.Terrain.GetCellContents(
326 Terrain.ToCell(position.X),
327 Terrain.ToCell(position.Y),
328 Terrain.ToCell(position.Z)
329 );
330 return BlocksManager.Blocks[cellContents] is MagmaBlock;
331 }
332
333 [Obsolete("SubsystemProjectiles不再提供射弹更新,请转移到Projectile.Update()中")]
334 public virtual void MakeProjectileNoise(Projectile projectile) {
335 if (m_subsystemTime.GameTime - projectile.LastNoiseTime > 0.5) {
336 m_subsystemNoise.MakeNoise(projectile.Position, 0.25f, 6f);
337 projectile.LastNoiseTime = m_subsystemTime.GameTime;
338 }
339 }
340
341 public static void CalculateVelocityAlignMatrix(Block projectileBlock, Vector3 position, Vector3 velocity, out Matrix matrix) {
342 matrix = Matrix.Identity;
343 matrix.Up = Vector3.Normalize(velocity);
344 matrix.Right = Vector3.Normalize(Vector3.Cross(matrix.Up, Vector3.UnitY));
345 matrix.Forward = Vector3.Normalize(Vector3.Cross(matrix.Up, matrix.Right));
346 matrix.Translation = position;
347 }
348 }
349}
Engine.Vector3 Vector3
static void Error(object message)
定义 Log.cs:80
static Type FindType(string typeName, bool skipSystemAssemblies, bool throwIfNotFound)
float ProjectileTipOffset
virtual bool IsCollidable_(int value)
Matrix ViewProjectionMatrix
virtual BoundingBox BoundingBox
virtual void InitializeData(Func< Terrain > terrain, Func< DrawBlockEnvironmentData > drawBlockEnvironmentData, Func< float > calcVisibilityRange, Func< SubsystemSky.CalculateFogDelegate > calculateFog, Func< PrimitivesRenderer3D > primitivesRenderer)
ComponentCreature Owner
virtual void Draw(Camera camera, int drawOrder)
virtual void Save(SubsystemProjectiles subsystemProjectiles, ValuesDictionary valuesDictionary)
override void Load(ValuesDictionary valuesDictionary)
在进入加载存档时执行
virtual void Update(float dt)
ITrailParticleSystem TrailParticleSystem
virtual void OnFiredAsProjectile(Projectile projectile)
virtual Projectile AddProjectile(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
virtual Projectile CreateProjectile(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
virtual void RemoveTrail(Projectile projectile)
virtual bool CanFireProjectile(int value, Vector3 position, Vector3 velocity, ComponentCreature owner, out Vector3 firePosition)
virtual bool IsWater(Vector3 position)
virtual T FireProjectile< T >(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
SubsystemBlockBehaviors m_subsystemBlockBehaviors
static void CalculateVelocityAlignMatrix(Block projectileBlock, Vector3 position, Vector3 velocity, out Matrix matrix)
DrawBlockEnvironmentData m_drawBlockEnvironmentData
override void Save(ValuesDictionary valuesDictionary)
virtual Action< Projectile > ProjectileRemoved
virtual Projectile FireProjectile(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
virtual void AddTrail(Projectile projectile, Vector3 offset, ITrailParticleSystem particleSystem)
SubsystemSoundMaterials m_subsystemSoundMaterials
virtual Action< Projectile > ProjectileAdded
virtual void MakeProjectileNoise(Projectile projectile)
PrimitivesRenderer3D m_primitivesRenderer
virtual void Draw(Camera camera, int drawOrder)
virtual void FireProjectileFast(Projectile projectile)
SubsystemFluidBlockBehavior m_subsystemFluidBlockBehavior
virtual T AddProjectile< T >(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
ReadOnlyList< Projectile > Projectiles
virtual bool IsMagma(Vector3 position)
override void Load(ValuesDictionary valuesDictionary)
virtual T CreateProjectile< T >(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
virtual Projectile AddProjectile(Projectile projectile)
SubsystemFireBlockBehavior m_subsystemFireBlockBehavior
static int ExtractContents(int value)
static int ToCell(float x)
ValuesDictionary ValuesDictionary
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
static readonly Matrix Identity
float? Intersection(BoundingBox box)
定义 Ray3.cs:20
static Vector3 Cross(Vector3 v1, Vector3 v2)
static Vector3 Normalize(Vector3 v)
static readonly Vector3 Zero
static readonly Vector3 UnitY