Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
Projectile.cs
浏览该文件的文档.
1using Engine;
5
6namespace Game {
7 public class Projectile : WorldItem {
9
11
12 public bool IsInFluid;
13
14 [Obsolete("Use IsInFluid instead.")]
15 public bool IsInWater {
16 get => IsInFluid;
17 set => IsInFluid = value;
18 }
19
20 public double LastNoiseTime;
21
23
25
27
28 public bool NoChunk;
29
30 public bool IsIncendiary;
31
32 public Action OnRemove;
33
34 public float Damping = -1f;
35
36 public float DampingInFluid = 0.001f;
37
38 public float Gravity = 10f;
39
40 public float TerrainKnockBack = 0.3f;
41
42 public bool StopTrailParticleInFluid = true;
43
47 public int DamageToPickable = 1;
48
49 public int? TurnIntoPickableBlockValue = null;
50
51 public bool TerrainCollidable = true;
52
53 public bool BodyCollidable = true;
54
55 public float? m_attackPower;
56 public virtual float MinVelocityToAttack { get; set; } = 10f;
58
59 public delegate float CalcVisibilityRangeDelegate();
60
61 #region 必选参数
62
63 public Func<Terrain> CurrnetTerrain;
64
65 public Func<float> CalcVisibilityRange;
66
67 public Func<DrawBlockEnvironmentData> DrawBlockEnvironmentData;
68
70
71 public Func<PrimitivesRenderer3D> PrimitivesRenderer;
72
73 #endregion
74
75 #region 可选参数
76
78
80
82 get => OwnerEntity?.FindComponent<ComponentCreature>();
83 set => OwnerEntity = value?.Entity;
84 }
85
89 public List<ComponentBody> BodiesToIgnore = new();
90
92
94 get {
95 if (m_subsystemProjectiles == null
96 && Project != null) {
98 }
100 }
101 }
102
104
106 get {
107 if (m_subsystemTerrain == null
108 && Project != null) {
110 }
111 return m_subsystemTerrain;
112 }
113 }
114
117 protected SubsystemAudio SubsystemAudio => SubsystemProjectiles?.m_subsystemAudio;
118
119 #endregion
120
124 public override void Load(ValuesDictionary valuesDictionary) {
125 Value = valuesDictionary.GetValue<int>("Value");
126 Position = valuesDictionary.GetValue<Vector3>("Position");
127 Velocity = valuesDictionary.GetValue<Vector3>("Velocity");
128 CreationTime = valuesDictionary.GetValue<double>("CreationTime");
129 ProjectileStoppedAction = valuesDictionary.GetValue("ProjectileStoppedAction", ProjectileStoppedAction);
130 int ownerEntityID = valuesDictionary.GetValue("OwnerID", 0);
131 if (ownerEntityID != 0
132 && Project != null) {
133 OwnerEntity = Project.FindEntity(ownerEntityID);
134 }
135 }
136
137 public virtual void Save(SubsystemProjectiles subsystemProjectiles, ValuesDictionary valuesDictionary) {
138 valuesDictionary.SetValue("Class", GetType().FullName);
139 valuesDictionary.SetValue("Value", Value);
140 valuesDictionary.SetValue("Position", Position);
141 valuesDictionary.SetValue("Velocity", Velocity);
142 valuesDictionary.SetValue("CreationTime", CreationTime);
143 valuesDictionary.SetValue("ProjectileStoppedAction", ProjectileStoppedAction);
144 if (OwnerEntity != null
145 && OwnerEntity.Id != 0) {
146 valuesDictionary.SetValue("OwnerID", OwnerEntity.Id);
147 }
149 "SaveProjectile",
150 loader => {
151 loader.SaveProjectile(subsystemProjectiles, this, ref valuesDictionary);
152 return false;
153 }
154 );
155 }
156
157 public virtual float AttackPower {
159 set => m_attackPower = value;
160 }
161
162 public virtual void InitializeData(Func<Terrain> terrain,
163 Func<DrawBlockEnvironmentData> drawBlockEnvironmentData,
164 Func<float> calcVisibilityRange,
165 Func<SubsystemSky.CalculateFogDelegate> calculateFog,
166 Func<PrimitivesRenderer3D> primitivesRenderer) {
167 CurrnetTerrain = terrain;
168 DrawBlockEnvironmentData = drawBlockEnvironmentData;
169 CalculateFog = calculateFog;
170 CalcVisibilityRange = calcVisibilityRange;
171 PrimitivesRenderer = primitivesRenderer;
172 }
173
174 public virtual void Initialize(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, Entity owner) {
176 Value = value;
177 Position = position;
178 Velocity = velocity;
180 AngularVelocity = angularVelocity;
181 OwnerEntity = owner;
182 Damping = block.GetProjectileDamping(value);
184 }
185
186 public virtual void Initialize(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner) {
187 Initialize(value, position, velocity, angularVelocity, owner?.Entity);
188 }
189
190 public virtual void Raycast(float dt, out BodyRaycastResult? bodyRaycastResult, out TerrainRaycastResult? terrainRaycastResult) {
192 Vector3 position = Position;
193 Vector3 positionAtdt = position + Velocity * dt;
194 Vector3 v = block.ProjectileTipOffset * Vector3.Normalize(Velocity);
195 if (TerrainCollidable) {
196 terrainRaycastResult = SubsystemTerrain == null
197 ? SubsystemTerrain.Raycast(
199 position + v,
200 positionAtdt + v,
201 false,
202 true,
203 (value, _) => BlocksManager.Blocks[Terrain.ExtractContents(value)].IsCollidable_(value)
204 )
205 : SubsystemTerrain.Raycast(
206 position + v,
207 positionAtdt + v,
208 false,
209 true,
210 (value, _) => BlocksManager.Blocks[Terrain.ExtractContents(value)].IsCollidable_(value)
211 );
212 }
213 else {
214 terrainRaycastResult = null;
215 }
216 if (BodyCollidable && Project != null) {
217 bodyRaycastResult = SubsystemProjectiles?.m_subsystemBodies.Raycast(
218 position + v,
219 positionAtdt + v,
220 0.2f,
221 (body, distance) => {
222 bool ignore = false;
224 "OnProjectileRaycastBody",
225 loader => {
226 loader.OnProjectileRaycastBody(body, this, distance, out bool ignoreByThisMod);
227 ignore |= ignoreByThisMod;
228 return false;
229 }
230 );
231 if (BodiesToIgnore.Contains(body) || ignore) {
232 return false;
233 }
234 return true;
235 }
236 );
237 }
238 else {
239 bodyRaycastResult = null;
240 }
241 }
242
243 public virtual void Update(float dt) {
244 if (Project != null) {
246 }
247 TerrainChunk chunkAtCell = CurrnetTerrain().GetChunkAtCell(Terrain.ToCell(Position.X), Terrain.ToCell(Position.Z));
248 if (chunkAtCell == null
249 || chunkAtCell.State <= TerrainChunkState.InvalidContents4) {
250 NoChunk = true;
251 if (TrailParticleSystem != null) {
252 TrailParticleSystem.IsStopped = true;
253 }
254 if (Project != null) {
256 }
257 }
258 else {
259 NoChunk = false;
260 UpdateInChunk(dt);
261 }
262 }
263
264 public virtual void UpdateTimeToRemove() {
265 if (SubsystemProjectiles == null) {
266 return;
267 }
268 double totalElapsedGameTime = SubsystemProjectiles.m_subsystemGameInfo.TotalElapsedGameTime;
269 if (totalElapsedGameTime - CreationTime > (MaxTimeExist ?? 40f)) {
270 ToRemove = true;
271 }
272 }
273
274 public virtual void OnProjectileFlyOutOfLoadedChunks() {
275 if (Project == null) {
276 return;
277 }
279 "OnProjectileFlyOutOfLoadedChunks",
280 loader => {
281 loader.OnProjectileFlyOutOfLoadedChunks(this);
282 return false;
283 }
284 );
285 }
286
287 public virtual bool ProcessOnHitAsProjectileBlockBehavior(CellFace? cellFace, ComponentBody componentBody, float dt) {
288 if (SubsystemProjectiles == null) {
289 return false;
290 }
291 bool flag = false;
293 blockBehaviors = SubsystemProjectiles.m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(Value));
294 for (int i = 0; i < blockBehaviors.Length; i++) {
295 flag |= blockBehaviors[i].OnHitAsProjectile(cellFace, componentBody, this);
296 }
297 return flag;
298 }
299
300 public virtual void HitBody(BodyRaycastResult bodyRaycastResult, ref Vector3 positionAtdt) {
301 float attackPower = Velocity.Length() > MinVelocityToAttack ? AttackPower : 0;
302 Vector3 velocityAfterAttack = Velocity * -0.05f + m_random.Vector3(-0.0166f * Velocity.Length());
303 Vector3 angularVelocityAfterAttack = AngularVelocity * 0.05f;
304 bool ignoreBody = false;
305 Attackment attackment = new ProjectileAttackment(
306 bodyRaycastResult.ComponentBody.Entity,
308 bodyRaycastResult.HitPoint(),
310 attackPower,
311 this
312 );
314 "OnProjectileHitBody",
315 loader => {
316 loader.OnProjectileHitBody(
317 this,
318 bodyRaycastResult,
319 ref attackment,
320 ref velocityAfterAttack,
321 ref angularVelocityAfterAttack,
322 ref ignoreBody
323 );
324 return false;
325 }
326 );
327 if (ignoreBody) {
328 BodiesToIgnore.Add(bodyRaycastResult.ComponentBody);
329 }
330 if (attackPower > 0f) {
331 ComponentMiner.AttackBody(attackment);
332 if (Owner is { PlayerStats: not null }) {
333 Owner.PlayerStats.RangedHits++;
334 }
335 }
336 if (IsIncendiary) {
337 bodyRaycastResult.ComponentBody.Entity.FindComponent<ComponentOnFire>()?.SetOnFire(Owner, m_random.Float(6f, 8f));
338 }
339 if (!ignoreBody) {
340 positionAtdt = Position;
341 }
342 Velocity = velocityAfterAttack;
343 AngularVelocity = angularVelocityAfterAttack;
344 }
345
346 public virtual void HitTerrain(TerrainRaycastResult terrainRaycastResult,
347 CellFace cellFace,
348 ref Vector3 positionAtdt,
349 ref Vector3? pickableStuckMatrix) {
351 int cellValue = CurrnetTerrain().GetCellValue(cellFace.X, cellFace.Y, cellFace.Z);
352 Block blockHitted = BlocksManager.Blocks[Terrain.ExtractContents(cellValue)];
353 float velocityLength = Velocity.Length();
354 Vector3 velocityAfterHit = Velocity;
355 Vector3 angularVelocityAfterHit = AngularVelocity * -0.3f;
356 Plane plane = cellFace.CalculatePlane();
357 if (plane.Normal.X != 0f) {
358 velocityAfterHit *= new Vector3(-TerrainKnockBack, TerrainKnockBack, TerrainKnockBack);
359 }
360 if (plane.Normal.Y != 0f) {
361 velocityAfterHit *= new Vector3(TerrainKnockBack, -TerrainKnockBack, TerrainKnockBack);
362 }
363 if (plane.Normal.Z != 0f) {
364 velocityAfterHit *= new Vector3(TerrainKnockBack, TerrainKnockBack, -TerrainKnockBack);
365 }
366 float num3 = velocityAfterHit.Length();
367 velocityAfterHit = num3 * Vector3.Normalize(velocityAfterHit + m_random.Vector3(num3 / 6f, num3 / 3f));
368 bool triggerBlocksBehavior = true;
369 bool destroyCell = velocityLength > 10f && m_random.Float(0f, 1f) > blockHitted.GetProjectileResilience(cellValue);
370 float impactSoundLoudness = velocityLength > 5f ? 1f : 0f;
371 bool projectileGetStuck = block.IsStickable_(Value)
372 && velocityLength > 10f
373 && m_random.Bool(blockHitted.GetProjectileStickProbability(Value));
375 "OnProjectileHitTerrain",
376 loader => {
377 loader.OnProjectileHitTerrain(
378 this,
379 terrainRaycastResult,
380 ref triggerBlocksBehavior,
381 ref destroyCell,
382 ref impactSoundLoudness,
383 ref projectileGetStuck,
384 ref velocityAfterHit,
385 ref angularVelocityAfterHit
386 );
387 return false;
388 }
389 );
390 //以上为ModLoader接口和ref变量
391 if (triggerBlocksBehavior && SubsystemProjectiles != null) {
392 SubsystemBlockBehavior[] blockBehaviors2 =
393 SubsystemProjectiles.m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(cellValue));
394 for (int j = 0; j < blockBehaviors2.Length; j++) {
395 blockBehaviors2[j].OnHitByProjectile(cellFace, this);
396 }
397 }
398 if (destroyCell
399 && SubsystemTerrain != null
400 && SubsystemProjectiles != null) {
401 SubsystemTerrain.DestroyCell(
402 0,
403 cellFace.X,
404 cellFace.Y,
405 cellFace.Z,
406 0,
407 true,
408 false
409 );
410 SubsystemProjectiles.m_subsystemSoundMaterials.PlayImpactSound(cellValue, Position, 1f);
411 }
412 if (IsIncendiary
413 && SubsystemTerrain != null
414 && SubsystemProjectiles != null) {
415 SubsystemProjectiles.m_subsystemFireBlockBehavior.SetCellOnFire(cellFace.X, cellFace.Y, cellFace.Z, 1f);
416 Vector3 vector3 = Position - 0.75f * Vector3.Normalize(Velocity);
417 for (int k = 0; k < 8; k++) {
418 Vector3 v2 = k == 0 ? Vector3.Normalize(Velocity) : m_random.Vector3(1.5f);
419 TerrainRaycastResult? terrainRaycastResult2 = SubsystemTerrain.Raycast(vector3, vector3 + v2, false, true, (_, _) => true);
420 if (terrainRaycastResult2.HasValue) {
421 SubsystemProjectiles.m_subsystemFireBlockBehavior.SetCellOnFire(
422 terrainRaycastResult2.Value.CellFace.X,
423 terrainRaycastResult2.Value.CellFace.Y,
424 terrainRaycastResult2.Value.CellFace.Z,
425 1f
426 );
427 }
428 }
429 }
430 if (impactSoundLoudness > 0
431 && SubsystemProjectiles != null) {
432 SubsystemProjectiles.m_subsystemSoundMaterials.PlayImpactSound(cellValue, Position, impactSoundLoudness);
433 }
434 if (projectileGetStuck) {
436 float s = MathUtils.Lerp(0.1f, 0.2f, MathUtils.Saturate((velocityLength - 15f) / 20f));
437 pickableStuckMatrix = Position + terrainRaycastResult.Distance * Vector3.Normalize(Velocity) + v3 * s;
438 }
439 else {
440 positionAtdt = Position;
441 AngularVelocity = angularVelocityAfterHit;
442 Velocity = velocityAfterHit;
443 }
444 MakeNoise();
445 }
446
447 public virtual void TurnIntoPickable(Vector3? pickableStuckMatrix) {
449 int damagedBlockValue = BlocksManager.DamageItem(Value, DamageToPickable, OwnerEntity);
450 if (TurnIntoPickableBlockValue.HasValue) {
451 damagedBlockValue = TurnIntoPickableBlockValue.Value;
452 }
453 if (damagedBlockValue != 0
454 && SubsystemPickables != null) {
455 Pickable pickable;
456 if (pickableStuckMatrix.HasValue) {
457 SubsystemProjectiles.CalculateVelocityAlignMatrix(block, pickableStuckMatrix.Value, Velocity, out Matrix matrix);
458 pickable = SubsystemPickables.CreatePickable(damagedBlockValue, 1, Position, Vector3.Zero, matrix, OwnerEntity);
459 }
460 else {
461 pickable = SubsystemPickables.CreatePickable(damagedBlockValue, 1, Position, Vector3.Zero, null, OwnerEntity);
462 }
464 "OnProjectileTurnIntoPickable",
465 loader => {
466 loader.OnProjectileTurnIntoPickable(this, ref pickable);
467 return false;
468 }
469 );
470 if (pickable != null) {
471 SubsystemPickables.AddPickable(pickable);
472 }
473 }
474 else if (SubsystemParticles != null) {
476 }
477 ToRemove = true;
478 }
479
480 public virtual void UpdateInChunk(float dt) {
482 Vector3 position = Position;
483 Vector3 positionAtdt = position + Velocity * dt;
484 Vector3? pickableStuckMatrix = null;
485 Raycast(dt, out BodyRaycastResult? bodyRaycastResult, out TerrainRaycastResult? terrainRaycastResult);
486 CellFace? nullableCellFace = terrainRaycastResult.HasValue ? new CellFace?(terrainRaycastResult.Value.CellFace) : null;
487 ComponentBody componentBody = bodyRaycastResult?.ComponentBody;
488 //这里增加:忽略哪些Body、是否忽略地形
489 bool disintegrate = block.DisintegratesOnHit;
490 //执行各方块的OnHitAsProjectile。
491 if (terrainRaycastResult.HasValue
492 || bodyRaycastResult.HasValue) {
493 disintegrate |= ProcessOnHitAsProjectileBlockBehavior(nullableCellFace, componentBody, dt);
494 ToRemove |= disintegrate;
495 }
496 //如果弹射物命中了Body,进行攻击,并改变速度。
497 if (bodyRaycastResult.HasValue
498 && (!terrainRaycastResult.HasValue || bodyRaycastResult.Value.Distance < terrainRaycastResult.Value.Distance)) {
499 HitBody(bodyRaycastResult.Value, ref positionAtdt);
500 }
501 //如果弹射物命中了地形,进行处理。破坏方块、点燃方块、撞到地形的移动效果。
502 else if (terrainRaycastResult.HasValue) {
503 CellFace cellFace = nullableCellFace.Value;
504 HitTerrain(terrainRaycastResult.Value, cellFace, ref positionAtdt, ref pickableStuckMatrix);
505 }
506 //弹射物转化为掉落物
507 if (terrainRaycastResult.HasValue
508 || bodyRaycastResult.HasValue) {
509 if (disintegrate && SubsystemParticles != null) {
511 }
512 else if (!ToRemove
513 && (pickableStuckMatrix.HasValue || Velocity.Length() < 1f)) {
514 if (ProjectileStoppedAction == ProjectileStoppedAction.TurnIntoPickable) {
515 TurnIntoPickable(pickableStuckMatrix);
516 }
517 else if (ProjectileStoppedAction == ProjectileStoppedAction.Disappear) {
518 ToRemove = true;
519 }
520 }
521 }
522 UpdateMovement(dt, ref positionAtdt);
523 }
524
525 public virtual void UpdateMovement(float dt, ref Vector3 positionAtdt) {
527 if (Damping < 0f) {
529 }
530 float friction = IsInFluid ? MathF.Pow(DampingInFluid, dt) : MathF.Pow(Damping, dt);
531 Velocity.Y += -Gravity * dt;
532 Velocity *= friction;
533 AngularVelocity *= friction;
534 Position = positionAtdt;
536 int cellContents = CurrnetTerrain().GetCellContents(Terrain.ToCell(Position.X), Terrain.ToCell(Position.Y), Terrain.ToCell(Position.Z));
537 Block blockTheProjectileIn = BlocksManager.Blocks[cellContents];
538 bool isProjectileInFluid = blockTheProjectileIn is FluidBlock;
539 if (TrailParticleSystem != null) {
541 }
542 if (isProjectileInFluid && !IsInFluid) {
543 if (DampingInFluid <= 0.001f) {
544 float horizontalSpeed = new Vector2(Velocity.X + Velocity.Z).Length();
545 if (horizontalSpeed > 6f
546 && horizontalSpeed > 4f * MathF.Abs(Velocity.Y)) {
547 Velocity *= 0.5f;
548 Velocity.Y *= -1f;
549 isProjectileInFluid = false;
550 }
551 else {
552 Velocity *= 0.2f;
553 }
554 }
555 float? surfaceHeight = SubsystemProjectiles?.m_subsystemFluidBlockBehavior.GetSurfaceHeight(
559 );
560 if (surfaceHeight.HasValue
561 && SubsystemParticles != null
562 && SubsystemAudio != null) {
563 if (blockTheProjectileIn is MagmaBlock) {
565 SubsystemAudio.PlayRandomSound("Audio/Sizzles", 1f, m_random.Float(-0.2f, 0.2f), Position, 3f, true);
566 if (!IsFireProof) {
567 ToRemove = true;
568 SubsystemProjectiles?.m_subsystemExplosions.TryExplodeBlock(
572 Value
573 );
574 }
575 }
576 else {
577 SubsystemParticles.AddParticleSystem(
578 new WaterSplashParticleSystem(SubsystemTerrain, new Vector3(Position.X, surfaceHeight.Value, Position.Z), false)
579 );
580 SubsystemAudio.PlayRandomSound("Audio/Splashes", 1f, m_random.Float(-0.2f, 0.2f), Position, 6f, true);
581 }
582 MakeNoise();
583 }
584 }
585 IsInFluid = isProjectileInFluid;
586 if (SubsystemProjectiles != null
587 && SubsystemAudio != null) {
588 if (!IsFireProof
589 && SubsystemProjectiles.m_subsystemTime.PeriodicGameTimeEvent(1.0, GetHashCode() % 100 / 100.0)
590 && (SubsystemProjectiles.m_subsystemFireBlockBehavior.IsCellOnFire(
592 Terrain.ToCell(Position.Y + 0.1f),
594 )
595 || SubsystemProjectiles.m_subsystemFireBlockBehavior.IsCellOnFire(
597 Terrain.ToCell(Position.Y + 0.1f) - 1,
599 ))) {
600 SubsystemAudio.PlayRandomSound("Audio/Sizzles", 1f, m_random.Float(-0.2f, 0.2f), Position, 3f, true);
601 ToRemove = true;
602 SubsystemProjectiles.m_subsystemExplosions.TryExplodeBlock(
606 Value
607 );
608 }
609 }
610 }
611
612 public virtual void UpdateTrailParticleSystem(float dt) {
613 if (SubsystemParticles == null) {
614 return;
615 }
616 if (!SubsystemParticles.ContainsParticleSystem((ParticleSystemBase)TrailParticleSystem)) {
618 }
619 Vector3 v4 = TrailOffset != Vector3.Zero
621 : Vector3.Zero;
622 TrailParticleSystem.Position = Position + v4;
624 TrailParticleSystem.IsStopped = true;
625 }
626 }
627
628 public virtual void MakeNoise() {
629 if (SubsystemProjectiles == null) {
630 return;
631 }
632 if (SubsystemProjectiles.m_subsystemTime.GameTime - LastNoiseTime > 0.5) {
633 SubsystemProjectiles.m_subsystemNoise.MakeNoise(Position, 0.25f, 6f);
634 LastNoiseTime = SubsystemProjectiles.m_subsystemTime.GameTime;
635 }
636 }
637
638 public override void UnderExplosion(Vector3 impulse, float damage) {
639 Velocity += (impulse + new Vector3(0f, 0.1f * impulse.Length(), 0f)) * m_random.Float(0.75f, 1f);
640 }
641
642 public virtual void Draw(Camera camera, int drawOrder) {
643 float num = MathUtils.Sqr(CalcVisibilityRange());
644 Vector3 position = Position;
645 if (!NoChunk
646 && Vector3.DistanceSquared(camera.ViewPosition, position) < num
647 && camera.ViewFrustum.Intersection(position)) {
648 int x = Terrain.ToCell(position.X);
649 int num2 = Terrain.ToCell(position.Y);
650 int z = Terrain.ToCell(position.Z);
651 int num3 = Terrain.ExtractContents(Value);
652 Block block = BlocksManager.Blocks[num3];
653 TerrainChunk chunkAtCell = CurrnetTerrain().GetChunkAtCell(x, z);
654 if (chunkAtCell != null
655 && chunkAtCell.State >= TerrainChunkState.InvalidVertices1
656 && num2 >= 0
657 && num2 < 255) {
658 DrawBlockEnvironmentData().Humidity = CurrnetTerrain().GetSeasonalHumidity(x, z);
659 DrawBlockEnvironmentData().Temperature = CurrnetTerrain().GetSeasonalTemperature(x, z)
661 Light = CurrnetTerrain().GetCellLightFast(x, num2, z);
662 }
664 DrawBlockEnvironmentData().BillboardDirection = block.GetAlignToVelocity(Value) ? null : new Vector3?(camera.ViewDirection);
665 DrawBlockEnvironmentData().InWorldMatrix.Translation = position;
666 Matrix matrix;
667 if (block.GetAlignToVelocity(Value)) {
668 SubsystemProjectiles.CalculateVelocityAlignMatrix(block, position, Velocity, out matrix);
669 }
670 else if (Rotation != Vector3.Zero) {
672 matrix.Translation = Position;
673 }
674 else {
676 }
677 bool shouldDrawBlock = true;
678 float drawBlockSize = 0.3f;
679 Color drawBlockColor = Color.MultiplyNotSaturated(Color.White, 1f - CalculateFog()(camera.ViewPosition, Position));
680 if (SubsystemProjectiles != null) {
682 "OnProjectileDraw",
683 loader => {
684 loader.OnProjectileDraw(
685 this,
687 camera,
688 drawOrder,
689 ref shouldDrawBlock,
690 ref drawBlockSize,
691 ref drawBlockColor
692 );
693 return false;
694 }
695 );
696 }
697 if (shouldDrawBlock) {
698 block.DrawBlock(PrimitivesRenderer(), Value, drawBlockColor, drawBlockSize, ref matrix, DrawBlockEnvironmentData());
699 }
700 }
701 }
702 }
703}
Engine.Vector3 Vector3
bool Intersection(Vector3 point)
static float Saturate(float x)
static int Sqr(int x)
static float Lerp(float x1, float x2, float f)
The spell "Attackment" is wrong, But it is not recommended to change it because many mods rely on thi...
virtual BlockDebrisParticleSystem CreateDebrisParticleSystem(SubsystemTerrain subsystemTerrain, Vector3 position, int value, float strength)
virtual float GetProjectileStickProbability(int value)
virtual bool GetAlignToVelocity(int value)
virtual float GetProjectilePower(int value)
void DrawBlock(PrimitivesRenderer3D primitivesRenderer, int value, Color color, float size, ref Matrix matrix, DrawBlockEnvironmentData environmentData)
绘制方块_用于绘制方块物品形态
virtual bool IsStickable_(int value)
bool DisintegratesOnHit
virtual bool IsCollidable_(int value)
virtual float GetProjectileResilience(int value)
virtual float GetProjectileDamping(int value)
static int DamageItem(int value, int damageCount, Entity owner=null)
Vector3 ViewPosition
BoundingFrustum ViewFrustum
Vector3 ViewDirection
static void AttackBody(Attackment attackment)
SubsystemTerrain SubsystemTerrain
virtual void InitializeData(Func< Terrain > terrain, Func< DrawBlockEnvironmentData > drawBlockEnvironmentData, Func< float > calcVisibilityRange, Func< SubsystemSky.CalculateFogDelegate > calculateFog, Func< PrimitivesRenderer3D > primitivesRenderer)
ComponentCreature Owner
Func< DrawBlockEnvironmentData > DrawBlockEnvironmentData
virtual void Draw(Camera camera, int drawOrder)
SubsystemProjectiles SubsystemProjectiles
int DamageToPickable
弹射物结算时掉的耐久
virtual float MinVelocityToAttack
SubsystemProjectiles m_subsystemProjectiles
Func< SubsystemSky.CalculateFogDelegate > CalculateFog
Func< float > CalcVisibilityRange
virtual void UpdateMovement(float dt, ref Vector3 positionAtdt)
ProjectileStoppedAction ProjectileStoppedAction
virtual void Save(SubsystemProjectiles subsystemProjectiles, ValuesDictionary valuesDictionary)
virtual void MakeNoise()
delegate float CalcVisibilityRangeDelegate()
SubsystemParticles SubsystemParticles
virtual void OnProjectileFlyOutOfLoadedChunks()
override void Load(ValuesDictionary valuesDictionary)
在进入加载存档时执行
virtual float AttackPower
virtual void Update(float dt)
override void UnderExplosion(Vector3 impulse, float damage)
virtual void Raycast(float dt, out BodyRaycastResult? bodyRaycastResult, out TerrainRaycastResult? terrainRaycastResult)
ITrailParticleSystem TrailParticleSystem
Func< PrimitivesRenderer3D > PrimitivesRenderer
virtual void UpdateTimeToRemove()
SubsystemAudio SubsystemAudio
virtual void HitBody(BodyRaycastResult bodyRaycastResult, ref Vector3 positionAtdt)
SubsystemPickables SubsystemPickables
virtual void HitTerrain(TerrainRaycastResult terrainRaycastResult, CellFace cellFace, ref Vector3 positionAtdt, ref Vector3? pickableStuckMatrix)
virtual bool ProcessOnHitAsProjectileBlockBehavior(CellFace? cellFace, ComponentBody componentBody, float dt)
virtual void Initialize(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, Entity owner)
virtual void UpdateInChunk(float dt)
Func< Terrain > CurrnetTerrain
virtual void UpdateTrailParticleSystem(float dt)
virtual void TurnIntoPickable(Vector3? pickableStuckMatrix)
List< ComponentBody > BodiesToIgnore
弹射物飞行的时候会忽略List中的ComponentBody
virtual void Initialize(int value, Vector3 position, Vector3 velocity, Vector3 angularVelocity, ComponentCreature owner)
SubsystemTerrain m_subsystemTerrain
virtual bool OnHitAsProjectile(CellFace? cellFace, ComponentBody componentBody, WorldItem worldItem)
virtual void OnHitByProjectile(CellFace cellFace, WorldItem worldItem)
delegate float CalculateFogDelegate(Vector3 viewPosition, Vector3 position)
static Func< int, int > GetTemperatureAdjustmentAtHeight
TerrainChunkState State
static int ExtractContents(int value)
static int ToCell(float x)
Component FindComponent(Type type, string name, bool throwOnError)
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
static Color White
static Color MultiplyNotSaturated(Color c, float s)
static Matrix CreateTranslation(float x, float y, float z)
static Matrix CreateFromAxisAngle(Vector3 axis, float angle)
Vector3 Normal
定义 Plane.cs:3
static float DistanceSquared(Vector3 v1, Vector3 v2)
static Vector3 TransformNormal(Vector3 v, Matrix m)
static Vector3 Normalize(Vector3 v)
static readonly Vector3 Zero
Plane CalculatePlane()