Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
ComponentMiner.cs
浏览该文件的文档.
1using System.Globalization;
2using Engine;
5
6namespace Game {
9
11
13
15
17
19
21
23
25
26 public Random m_random = new();
27
28 public static Random s_random = new();
29
30 public double m_digStartTime;
31
32 public float m_digProgress;
33
34 public double m_lastHitTime;
35
36 public static string fName = "ComponentMiner";
37
39
40 public float m_lastPokingPhase;
41
43
47 public virtual double HitInterval {
48 get => m_basicHitInterval / ComponentFactors.GetOtherFactorResult("AttackSpeed");
49 [Obsolete("Do not set the added hit interval, set m_basicHitInterval instead.")]
50 set => m_basicHitInterval = value;
51 }
52
53 public double m_basicHitInterval;
54
56
57 public ComponentPlayer ComponentPlayer { get; set; }
58
60
61 public IInventory Inventory { get; set; }
62
63 public int ActiveBlockValue {
64 get {
65 if (Inventory == null) {
66 return 0;
67 }
68 return Inventory.GetSlotValue(Inventory.ActiveSlotIndex);
69 }
70 }
71
72 public float AttackPower { get; set; }
73
74 public float AutoInteractRate { get; set; }
75
76 public float StrengthFactor => ComponentFactors?.StrengthFactor ?? 1;
77
82
83 public float DigSpeedFactor {
84 get {
85 float ans = 1f;
87 ans *= StrengthFactor;
88 }
89 if (ComponentFactors?.OtherFactorsResults.TryGetValue("DigSpeed", out float result) ?? false) {
90 ans *= result;
91 }
92 return ans;
93 }
94 }
95
96 public float PokingPhase { get; set; }
97
98 public CellFace? DigCellFace { get; set; }
99
100 public float DigTime {
101 get {
102 if (!DigCellFace.HasValue) {
103 return 0f;
104 }
105 return (float)(m_subsystemTime.GameTime - m_digStartTime);
106 }
107 }
108
109 public float DigProgress {
110 get {
111 if (!DigCellFace.HasValue) {
112 return 0f;
113 }
114 return m_digProgress;
115 }
116 }
117
118 public bool m_canSqueezeBlock = true;
119
120 public bool m_canJumpToPlace = false;
121
123
124 public virtual void Poke(bool forceRestart) {
125 PokingPhase = forceRestart ? 0.0001f : MathUtils.Max(0.0001f, PokingPhase);
126 }
127
128 public bool Dig(TerrainRaycastResult raycastResult) {
129 bool result = false;
131 CellFace cellFace = raycastResult.CellFace;
132 int cellValue = m_subsystemTerrain.Terrain.GetCellValue(cellFace.X, cellFace.Y, cellFace.Z);
133 int cellContents = Terrain.ExtractContents(cellValue);
134 Block cellBlock = BlocksManager.Blocks[cellContents];
135 int activeBlockValue = ActiveBlockValue;
136 int activeBlockContents = Terrain.ExtractContents(activeBlockValue);
137 Block activeBlock = BlocksManager.Blocks[activeBlockContents];
138 if (!DigCellFace.HasValue
139 || DigCellFace.Value.X != cellFace.X
140 || DigCellFace.Value.Y != cellFace.Y
141 || DigCellFace.Value.Z != cellFace.Z) {
143 DigCellFace = cellFace;
144 }
145 float digTimeWithActiveTool = CalculateDigTime(cellValue, activeBlockValue);
146 m_digProgress = digTimeWithActiveTool > 0f
147 ? MathUtils.Saturate((float)(m_subsystemTime.GameTime - m_digStartTime) / digTimeWithActiveTool)
148 : 1f;
149 if (!IsLevelSufficientForTool(activeBlockValue)) {
150 m_digProgress = 0f;
151 if (m_subsystemTime.PeriodicGameTimeEvent(5.0, m_digStartTime + 1.0)) {
152 ComponentPlayer?.ComponentGui.DisplaySmallMessage(
153 string.Format(
155 activeBlock.GetPlayerLevelRequired(activeBlockValue),
156 activeBlock.GetDisplayName(m_subsystemTerrain, activeBlockValue)
157 ),
158 Color.White,
159 true,
160 true
161 );
162 }
163 }
164 bool flag2 = ComponentPlayer != null
165 && !ComponentPlayer.ComponentInput.IsControlledByTouch
166 && m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Creative;
168 "OnMinerDig",
169 modLoader => {
170 modLoader.OnMinerDig(this, raycastResult, ref m_digProgress, out bool flag3);
171 flag2 |= flag3;
172 return false;
173 }
174 );
175 if ((m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Survival || m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Harmless)
176 && ComponentPlayer != null
177 && digTimeWithActiveTool >= 3f
178 && m_digProgress > 0.5f
179 && (m_lastToolHintTime == 0.0 || Time.FrameStartTime - m_lastToolHintTime > 300.0)) {
180 bool flag = digTimeWithActiveTool == CalculateDigTime(cellValue, 0); //flag:该物品挖掘时间和空手相同
181 int bestInventoryToolValue = FindBestInventoryToolForDigging(cellValue);
182 if (bestInventoryToolValue == 0) {
183 if (activeBlockContents != 23 && flag) {
184 ComponentPlayer.ComponentGui.DisplaySmallMessage(LanguageControl.Get(fName, "11"), Color.White, true, true);
186 }
187 }
188 else if (CalculateDigTime(cellValue, bestInventoryToolValue) < 0.5f * digTimeWithActiveTool || flag) {
189 string displayName = BlocksManager.Blocks[Terrain.ExtractContents(bestInventoryToolValue)]
190 .GetDisplayName(m_subsystemTerrain, bestInventoryToolValue);
191 ComponentPlayer.ComponentGui.DisplaySmallMessage(
192 string.Format(LanguageControl.Get(fName, "12"), displayName),
193 Color.White,
194 true,
195 true
196 );
198 }
199 }
200 if (flag2 || (m_lastPokingPhase <= 0.5f && PokingPhase > 0.5f)) {
201 if (m_digProgress >= 1f) {
202 DigCellFace = null;
203 if (flag2) {
204 Poke(true);
205 }
206 BlockPlacementData digValue = cellBlock.GetDigValue(m_subsystemTerrain, this, cellValue, activeBlockValue, raycastResult);
207 m_subsystemTerrain.DestroyCell(
208 activeBlock.GetToolLevel(activeBlockValue),
209 digValue.CellFace.X,
210 digValue.CellFace.Y,
211 digValue.CellFace.Z,
212 digValue.Value,
213 false,
214 false
215 );
216 int durabilityReduction = 1;
217 int playerDataAdd = 1;
218 bool mute_ = false;
220 "OnBlockDug",
221 modLoader => {
222 bool mute = false;
223 modLoader.OnBlockDug(this, digValue, cellValue, ref durabilityReduction, ref mute, ref playerDataAdd);
224 mute_ |= mute;
225 return false;
226 }
227 );
228 if (!mute_) {
229 m_subsystemSoundMaterials.PlayImpactSound(cellValue, new Vector3(cellFace.X, cellFace.Y, cellFace.Z), 2f);
230 }
231 DamageActiveTool(durabilityReduction);
232 if (ComponentCreature.PlayerStats != null) {
233 ComponentCreature.PlayerStats.BlocksDug += playerDataAdd;
234 }
235 result = true;
236 }
237 else {
238 m_subsystemSoundMaterials.PlayImpactSound(cellValue, new Vector3(cellFace.X, cellFace.Y, cellFace.Z), 1f);
239 BlockDebrisParticleSystem particleSystem = cellBlock.CreateDebrisParticleSystem(
241 raycastResult.HitPoint(0.1f),
242 cellValue,
243 0.35f
244 );
245 Project.FindSubsystem<SubsystemParticles>(true).AddParticleSystem(particleSystem);
246 }
247 }
248 return result;
249 }
250
251 public bool Place(TerrainRaycastResult raycastResult) {
252 if (Place(raycastResult, ActiveBlockValue)) {
253 if (Inventory != null) {
254 Inventory.RemoveSlotItems(Inventory.ActiveSlotIndex, 1);
255 }
256 return true;
257 }
258 return false;
259 }
260
261 public bool Place(TerrainRaycastResult raycastResult, int value) {
262 int num = Terrain.ExtractContents(value);
263 if (BlocksManager.Blocks[num].IsPlaceable_(value)) {
264 Block block = BlocksManager.Blocks[num];
265 BlockPlacementData placementData = block.GetPlacementValue(m_subsystemTerrain, this, value, raycastResult);
266 if (placementData.Value != 0) {
267 Point3 point = CellFace.FaceToPoint3(placementData.CellFace.Face);
268 int num2 = placementData.CellFace.X + point.X;
269 int num3 = placementData.CellFace.Y + point.Y;
270 int num4 = placementData.CellFace.Z + point.Z;
271 bool placed = false;
272 bool placementNotAllowed_ = false;
274 "BeforeMinerPlace",
275 loader => {
276 // ReSharper disable AccessToModifiedClosure
277 loader.BeforeMinerPlace(
278 this,
279 raycastResult,
280 num2,
281 num3,
282 num4,
283 placementData,
284 out bool placementNotAllowed
285 );
286 // ReSharper restore AccessToModifiedClosure
287 placementNotAllowed_ |= placementNotAllowed;
288 return false;
289 }
290 );
291 if (placementNotAllowed_) {
292 return false;
293 }
295 "OnMinerPlace",
296 modLoader => {
297#pragma warning disable CS0618 // 类型或成员已过时
298 modLoader.OnMinerPlace(
299 this,
300 raycastResult,
301 num2,
302 num3,
303 num4,
304 value,
305 out bool Placed
306 );
307#pragma warning restore CS0618 // 类型或成员已过时
308 placed |= Placed;
309 return false;
310 }
311 );
313 "OnMinerPlace",
314 modLoader => {
315 modLoader.OnMinerPlace(
316 this,
317 raycastResult,
318 num2,
319 num3,
320 num4,
321 value,
322 placementData,
323 out bool Placed
324 );
325 placed |= Placed;
326 return false;
327 }
328 );
329 if (placed) {
330 return true;
331 }
332 if (!m_canSqueezeBlock) {
333 if (m_subsystemTerrain.Terrain.GetCellContents(num2, num3, num4) != 0) {
334 return false;
335 }
336 }
337 if (num3 > 0
341 || m_subsystemGameInfo.WorldSettings.GameMode <= GameMode.Survival)) {
342 bool flag = false;
343 if (block.IsCollidable_(value)) {
344 BoundingBox boundingBox = ComponentCreature.ComponentBody.BoundingBox;
345 boundingBox.Min += new Vector3(0.2f);
346 boundingBox.Max -= new Vector3(0.2f);
347 BoundingBox[] customCollisionBoxes = block.GetCustomCollisionBoxes(m_subsystemTerrain, placementData.Value);
348 for (int i = 0; i < customCollisionBoxes.Length; i++) {
349 BoundingBox box = customCollisionBoxes[i];
350 box.Min += new Vector3(num2, num3, num4);
351 box.Max += new Vector3(num2, num3, num4);
352 if (boundingBox.Intersection(box)) {
353 flag = true;
354 break;
355 }
356 }
357 }
358 if (!flag) {
359 SubsystemBlockBehavior[] blockBehaviors =
360 m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(placementData.Value));
361 for (int i = 0; i < blockBehaviors.Length; i++) {
362 blockBehaviors[i].OnItemPlaced(num2, num3, num4, ref placementData, value);
363 }
364 m_subsystemTerrain.DestroyCell(
365 0,
366 num2,
367 num3,
368 num4,
369 placementData.Value,
370 false,
371 false
372 );
373 m_subsystemAudio.PlaySound(
374 "Audio/BlockPlaced",
375 1f,
376 0f,
377 new Vector3(placementData.CellFace.X, placementData.CellFace.Y, placementData.CellFace.Z),
378 5f,
379 false
380 );
381 Poke(false);
382 if (ComponentCreature.PlayerStats != null) {
383 ComponentCreature.PlayerStats.BlocksPlaced++;
384 }
385 return true;
386 }
387 }
388 }
389 }
390 return false;
391 }
392
393 public bool Use(Ray3 ray) {
395 Block block = BlocksManager.Blocks[num];
397 ComponentPlayer?.ComponentGui.DisplaySmallMessage(
398 string.Format(
402 ),
403 Color.White,
404 true,
405 true
406 );
407 Poke(false);
408 return false;
409 }
411 for (int i = 0; i < blockBehaviors.Length; i++) {
412 if (blockBehaviors[i].OnUse(ray, this)) {
413 Poke(false);
414 return true;
415 }
416 }
417 return false;
418 }
419
420 public bool Interact(TerrainRaycastResult raycastResult) {
421 SubsystemBlockBehavior[] blockBehaviors = m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(raycastResult.Value));
422 for (int i = 0; i < blockBehaviors.Length; i++) {
423 if (blockBehaviors[i].OnInteract(raycastResult, this)) {
424 if (ComponentCreature.PlayerStats != null) {
425 ComponentCreature.PlayerStats.BlocksInteracted++;
426 }
427 Poke(false);
428 return true;
429 }
430 }
431 return false;
432 }
433
434 public bool Interact(MovingBlocksRaycastResult raycastResult) {
435 if (raycastResult.MovingBlock == null) {
436 return false;
437 }
438 SubsystemBlockBehavior[] blockBehaviors = m_subsystemBlockBehaviors.GetBlockBehaviors(
440 );
441 for (int i = 0; i < blockBehaviors.Length; i++) {
442 if (blockBehaviors[i].OnInteract(raycastResult, this)) {
443 if (ComponentCreature.PlayerStats != null) {
444 ComponentCreature.PlayerStats.BlocksInteracted++;
445 }
446 Poke(false);
447 return true;
448 }
449 }
450 return false;
451 }
452
453 public void Hit(ComponentBody componentBody, Vector3 hitPoint, Vector3 hitDirection) {
454 double hitInterval = HitInterval;
456 "SetHitInterval",
457 modLoader => {
458 modLoader.SetHitInterval(this, ref hitInterval);
459 return false;
460 }
461 );
462 if (!(m_subsystemTime.GameTime - m_lastHitTime > hitInterval)) {
463 return;
464 }
468 ComponentPlayer?.ComponentGui.DisplaySmallMessage(
469 string.Format(
473 ),
474 Color.White,
475 true,
476 true
477 );
478 Poke(false);
479 return;
480 }
481 float num; //伤害
482 float num2; //玩家命中率
483 float num3 = 1f; //生物命中率
484 if (ActiveBlockValue != 0) {
485 num = block.GetMeleePower(ActiveBlockValue) * AttackPower * m_random.Float(0.8f, 1.2f);
487 }
488 else {
489 num = AttackPower * m_random.Float(0.8f, 1.2f);
490 num2 = 0.66f;
491 }
492 num2 *= componentBody.Velocity.Length() < 0.05f ? 2f : 1f;
493 bool flag;
495 "OnMinerHit",
496 modLoader => {
497 // ReSharper disable AccessToModifiedClosure
498 modLoader.OnMinerHit(
499 this,
500 componentBody,
501 hitPoint,
502 hitDirection,
503 ref num,
504 ref num2,
505 ref num3,
506 out bool _
507 );
508 // ReSharper restore AccessToModifiedClosure
509 return false;
510 }
511 );
512 if (ComponentPlayer != null) {
513 m_subsystemAudio.PlaySound("Audio/Swoosh", 1f, m_random.Float(-0.2f, 0.2f), componentBody.Position, 3f, false);
514 flag = m_random.Bool(num2);
515 }
516 else {
517 flag = m_random.Bool(num3);
518 }
519 num *= StrengthFactor;
520 if (flag) {
521 int durabilityReduction = 1;
522 Attackment attackment = new MeleeAttackment(componentBody, Entity, hitPoint, hitDirection, num);
524 "OnMinerHit2",
525 loader => {
526 loader.OnMinerHit2(this, componentBody, hitPoint, hitDirection, ref durabilityReduction, ref attackment);
527 return false;
528 }
529 );
530 AttackBody(attackment);
531 DamageActiveTool(durabilityReduction);
532 }
534 HitValueParticleSystem particleSystem = new(
535 hitPoint + 0.75f * hitDirection,
536 1f * hitDirection + ComponentCreature.ComponentBody.Velocity,
537 Color.White,
539 );
541 "SetHitValueParticleSystem",
542 modLoader => {
543 modLoader.SetHitValueParticleSystem(particleSystem, null);
544 return false;
545 }
546 );
547 Project.FindSubsystem<SubsystemParticles>(true).AddParticleSystem(particleSystem);
548 }
549 if (ComponentCreature.PlayerStats != null) {
550 ComponentCreature.PlayerStats.MeleeAttacks++;
551 if (flag) {
552 ComponentCreature.PlayerStats.MeleeHits++;
553 }
554 }
555 Poke(false);
556 }
557
558 public bool Aim(Ray3 aim, AimState state) {
560 Block block = BlocksManager.Blocks[num];
561 if (block.IsAimable_(ActiveBlockValue)) {
563 ComponentPlayer?.ComponentGui.DisplaySmallMessage(
564 string.Format(
568 ),
569 Color.White,
570 true,
571 true
572 );
573 Poke(false);
574 return true;
575 }
577 for (int i = 0; i < blockBehaviors.Length; i++) {
578 if (blockBehaviors[i].OnAim(aim, this, state)) {
579 return true;
580 }
581 }
582 }
583 return false;
584 }
585
596 public virtual object Raycast(Ray3 ray,
597 RaycastMode mode,
598 bool raycastTerrain = true,
599 bool raycastBodies = true,
600 bool raycastMovingBlocks = true,
601 float? Reach = null) {
602 float reach = m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Creative ? SettingsManager.CreativeReach : 5f;
603 if (Reach.HasValue) {
604 reach = Reach.Value;
605 }
606 reach = Math.Min(reach, SettingsManager.VisibilityRange);
607 Vector3 creaturePosition = ComponentCreature.ComponentCreatureModel.EyePosition;
608 Vector3 start = ray.Position;
609 Vector3 direction = Vector3.Normalize(ray.Direction);
610 Vector3 end = ray.Position + direction * (reach + 1f);
611 Point3 startCell = Terrain.ToCell(start);
612 BodyRaycastResult? bodyRaycastResult = null;
613 if (raycastBodies) {
614 bodyRaycastResult = m_subsystemBodies.Raycast(
615 start,
616 end,
617 0.35f,
618 (body, distance) => Vector3.DistanceSquared(start + distance * direction, creaturePosition) <= reach * reach
619 && body.Entity != Entity
620 && !body.IsChildOfBody(ComponentCreature.ComponentBody)
621 && !ComponentCreature.ComponentBody.IsChildOfBody(body)
622 && Vector3.Dot(Vector3.Normalize(body.BoundingBox.Center() - start), direction) > 0.7f
623 );
624 }
625 MovingBlocksRaycastResult? movingBlocksRaycastResult = null;
626 if (raycastMovingBlocks) {
627 movingBlocksRaycastResult = m_subsystemMovingBlocks.Raycast(start, end, true);
628 }
629 TerrainRaycastResult? terrainRaycastResult = null;
630 if (raycastTerrain) {
631 terrainRaycastResult = m_subsystemTerrain.Raycast(
632 start,
633 end,
634 true,
635 true,
636 (value, distance) => {
637 if (Vector3.DistanceSquared(start + distance * direction, creaturePosition) <= reach * reach) {
639 if (distance == 0f
640 && block is CrossBlock
641 && Vector3.Dot(direction, new Vector3(startCell) + new Vector3(0.5f) - start) < 0f) {
642 return false;
643 }
644 if (mode == RaycastMode.Digging) {
645 return !block.GetIsDiggingTransparent(value);
646 }
647 if (mode == RaycastMode.Interaction) {
648 if (block.IsPlacementTransparent_(value)) {
649 return block.IsInteractive(m_subsystemTerrain, value);
650 }
651 return true;
652 }
653 if (mode == RaycastMode.Gathering) {
654 return block.IsGatherable_(value);
655 }
656 }
657 return false;
658 }
659 );
660 }
661 float num = bodyRaycastResult?.Distance ?? float.PositiveInfinity;
662 float num2 = movingBlocksRaycastResult?.Distance ?? float.PositiveInfinity;
663 float num3 = terrainRaycastResult?.Distance ?? float.PositiveInfinity;
664 if (bodyRaycastResult.HasValue
665 && num < num2
666 && num < num3) {
667 return bodyRaycastResult.Value;
668 }
669 if (movingBlocksRaycastResult.HasValue
670 && num2 < num
671 && num2 < num3) {
672 return movingBlocksRaycastResult.Value;
673 }
674 if (terrainRaycastResult.HasValue
675 && num3 < num
676 && num3 < num2) {
677 return terrainRaycastResult.Value;
678 }
679 return new Ray3(start, direction);
680 }
681
682 public T? Raycast<T>(Ray3 ray,
683 RaycastMode mode,
684 bool raycastTerrain = true,
685 bool raycastBodies = true,
686 bool raycastMovingBlocks = true,
687 float? reach = null) where T : struct {
688 object obj = Raycast(ray, mode, raycastTerrain, raycastBodies, raycastMovingBlocks, reach);
689 return obj is T obj1 ? obj1 : null;
690 }
691
692 public virtual void RemoveActiveTool(int removeCount) {
693 if (Inventory != null) {
694 Inventory.RemoveSlotItems(Inventory.ActiveSlotIndex, removeCount);
695 }
696 }
697
698 public virtual void DamageActiveTool(int damageCount) {
699 if (m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Creative
700 || Inventory == null) {
701 return;
702 }
703 int num = BlocksManager.DamageItem(ActiveBlockValue, damageCount, Entity);
704 if (num != 0) {
705 int slotCount = Inventory.GetSlotCount(Inventory.ActiveSlotIndex);
706 Inventory.RemoveSlotItems(Inventory.ActiveSlotIndex, slotCount);
707 if (Inventory.GetSlotCount(Inventory.ActiveSlotIndex) == 0) {
708 Inventory.AddSlotItems(Inventory.ActiveSlotIndex, num, slotCount);
709 }
710 }
711 else {
712 Inventory.RemoveSlotItems(Inventory.ActiveSlotIndex, 1);
713 }
714 }
715
716 public static void AttackBody(Attackment attackment) {
717 try {
718 attackment.ProcessAttackment();
719 }
720 catch (Exception e) {
721 Log.Error($"Attack execute error: {e}");
722 }
723 }
724
725 public static void AttackBody(ComponentBody target,
726 ComponentCreature attacker,
727 Vector3 hitPoint,
728 Vector3 hitDirection,
729 float attackPower,
730 bool isMeleeAttack) {
731 if (isMeleeAttack) {
732 AttackBody(new MeleeAttackment(target?.Entity, attacker?.Entity, hitPoint, hitDirection, attackPower));
733 }
734 else {
735 AttackBody(new ProjectileAttackment(target?.Entity, attacker?.Entity, hitPoint, hitDirection, attackPower, null));
736 }
737 }
738
739 [Obsolete("Use AddHitValueParticleSystem() in Attackment instead.", true)]
740 public static void AddHitValueParticleSystem(float damage, Entity attacker, Entity attacked, Vector3 hitPoint, Vector3 hitDirection) {
741 ComponentBody attackerBody = attacker?.FindComponent<ComponentBody>();
742 ComponentPlayer attackerComponentPlayer = attacker?.FindComponent<ComponentPlayer>();
743 ComponentHealth attackedComponentHealth = attacked?.FindComponent<ComponentHealth>();
744 string text2 = (0f - damage).ToString("0", CultureInfo.InvariantCulture);
745 Vector3 hitValueParticleVelocity = Vector3.Zero;
746 if (attackerBody != null) {
747 hitValueParticleVelocity = attackerBody.Velocity;
748 }
749 Color color = attackerComponentPlayer != null && damage > 0f && attackedComponentHealth != null ? Color.White : Color.Transparent;
750 HitValueParticleSystem particleSystem = new(hitPoint + 0.75f * hitDirection, 1f * hitDirection + hitValueParticleVelocity, color, text2);
752 "SetHitValueParticleSystem",
753 modLoader => {
754 modLoader.SetHitValueParticleSystem(particleSystem, null);
755 return false;
756 }
757 );
758 attacked?.Project.FindSubsystem<SubsystemParticles>(true).AddParticleSystem(particleSystem);
759 }
760
761 public virtual void Update(float dt) {
762 float num = m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Creative ? 1f / SettingsManager.CreativeDigTime : 4f;
764 if (DigCellFace.HasValue
765 || PokingPhase > 0f) {
766 PokingPhase += num * m_subsystemTime.GameTimeDelta;
767 if (PokingPhase > 1f) {
768 PokingPhase = DigCellFace.HasValue ? MathUtils.Remainder(PokingPhase, 1f) : 0f;
769 }
770 }
771 if (DigCellFace.HasValue
773 DigCellFace = null;
774 }
775 if ((m_componentHealth != null && !(m_componentHealth.Health > 0f))
776 || !(AutoInteractRate > 0f)
777 || !m_random.Bool(AutoInteractRate)
778 || !m_subsystemTime.PeriodicGameTimeEvent(1.0, GetHashCode() % 100 / 100f)) {
779 return;
780 }
781 ComponentCreatureModel componentCreatureModel = ComponentCreature.ComponentCreatureModel;
782 Vector3 eyePosition = componentCreatureModel.EyePosition;
783 Vector3 forwardVector = componentCreatureModel.EyeRotation.GetForwardVector();
784 for (int i = 0; i < 10; i++) {
786 new Ray3(eyePosition, forwardVector + m_random.Vector3(0.75f)),
787 RaycastMode.Interaction
788 );
789 if (terrainRaycastResult.HasValue
790 && terrainRaycastResult.Value.Distance < 1.5f
791 && Terrain.ExtractContents(terrainRaycastResult.Value.Value) != 57
792 && Interact(terrainRaycastResult.Value)) {
793 break;
794 }
795 }
796 }
797
798 public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
799 m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
800 m_subsystemBodies = Project.FindSubsystem<SubsystemBodies>(true);
802 m_subsystemGameInfo = Project.FindSubsystem<SubsystemGameInfo>(true);
803 m_subsystemTime = Project.FindSubsystem<SubsystemTime>(true);
804 m_subsystemAudio = Project.FindSubsystem<SubsystemAudio>(true);
807 ComponentCreature = Entity.FindComponent<ComponentCreature>(true);
808 ComponentPlayer = Entity.FindComponent<ComponentPlayer>();
809 m_componentHealth = Entity.FindComponent<ComponentHealth>();
810 ComponentFactors = Entity.FindComponent<ComponentFactors>(true);
811 Inventory = m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Creative && ComponentPlayer != null
812 ? Entity.FindComponent<ComponentCreativeInventory>()
813 : Entity.FindComponent<ComponentInventory>();
814 AttackPower = valuesDictionary.GetValue<float>("AttackPower");
815#pragma warning disable CS0618
816 HitInterval = valuesDictionary.GetValue<float>("HitInterval");
817#pragma warning restore CS0618
818 AutoInteractRate = valuesDictionary.GetValue<float>("AutoInteractRate");
819 if (string.CompareOrdinal(m_subsystemGameInfo.WorldSettings.OriginalSerializationVersion, "2.4") < 0
820 || m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Harmless
821 || m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Survival) {
822 AutoInteractRate = 0f;
823 }
824 }
825
826 public override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap) {
827 valuesDictionary.SetValue("AttackPower", AttackPower);
828 }
829
830 public static bool IsBlockPlacingAllowed(ComponentBody componentBody) {
831 if (componentBody.StandingOnBody != null
832 || componentBody.StandingOnValue.HasValue) {
833 return true;
834 }
835 if (componentBody.ImmersionFactor > 0.01f) {
836 return true;
837 }
838 if (componentBody.ParentBody != null
839 && IsBlockPlacingAllowed(componentBody.ParentBody)) {
840 return true;
841 }
842 ComponentLocomotion componentLocomotion = componentBody.Entity.FindComponent<ComponentLocomotion>();
843 if (componentLocomotion != null
844 && componentLocomotion.LadderValue.HasValue) {
845 return true;
846 }
847 return false;
848 }
849
850 public virtual float CalculateDigTime(int digValue, int toolValue) {
853 float digResilience = block2.GetDigResilience(digValue);
854 BlockDigMethod digBlockMethod = block2.GetBlockDigMethod(digValue);
855 float ShovelPower = block.GetShovelPower(toolValue);
856 float QuarryPower = block.GetQuarryPower(toolValue);
857 float HackPower = block.GetHackPower(toolValue);
858 if (ComponentPlayer != null
859 && m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Creative) {
860 if (digResilience < float.PositiveInfinity) {
861 return 0f;
862 }
863 return float.PositiveInfinity;
864 }
865 if (ComponentPlayer != null
866 && m_subsystemGameInfo.WorldSettings.GameMode == GameMode.Adventure) {
867 float num = 0f;
868 if (digBlockMethod == BlockDigMethod.Shovel
869 && ShovelPower >= 2f) {
870 num = ShovelPower;
871 }
872 else if (digBlockMethod == BlockDigMethod.Quarry
873 && QuarryPower >= 2f) {
874 num = QuarryPower;
875 }
876 else if (digBlockMethod == BlockDigMethod.Hack
877 && HackPower >= 2f) {
878 num = HackPower;
879 }
880 num *= StrengthFactor;
881 if (!(num > 0f)) {
882 return float.PositiveInfinity;
883 }
884 return MathUtils.Max(digResilience / num, 0f);
885 }
886 float num2 = 1f;
887 if (digBlockMethod == BlockDigMethod.Shovel) {
888 num2 = ShovelPower;
889 }
890 else if (digBlockMethod == BlockDigMethod.Quarry) {
891 num2 = QuarryPower;
892 }
893 else if (digBlockMethod == BlockDigMethod.Hack) {
894 num2 = HackPower;
895 }
896 num2 *= DigSpeedFactor;
897 if (!(num2 > 0f)) {
898 return float.PositiveInfinity;
899 }
900 return MathUtils.Max(digResilience / num2, 0f);
901 }
902
903 public virtual bool IsLevelSufficientForTool(int toolValue) {
904 bool canUse = false;
905 bool skip = false;
907 "IsLevelSufficientForTool",
908 modLoader => {
909 modLoader.IsLevelSufficientForTool(this, toolValue, ref canUse, out skip);
910 return false;
911 }
912 );
913 if (skip) {
914 return canUse;
915 }
916 if (m_subsystemGameInfo.WorldSettings.GameMode != 0
917 && m_subsystemGameInfo.WorldSettings.AreAdventureSurvivalMechanicsEnabled) {
919 if (ComponentPlayer != null
920 && ComponentPlayer.PlayerData.Level < block.GetPlayerLevelRequired(toolValue)) {
921 return false;
922 }
923 }
924 return true;
925 }
926
927 public virtual int FindBestInventoryToolForDigging(int digValue) {
928 int result = 0;
929 float num = CalculateDigTime(digValue, 0);
930 foreach (IInventory item in Entity.FindComponents<IInventory>()) {
931 if (item is ComponentCreativeInventory) {
932 continue;
933 }
934 for (int i = 0; i < item.SlotsCount; i++) {
935 int slotValue = item.GetSlotValue(i);
936 if (IsLevelSufficientForTool(slotValue)) {
937 float num2 = CalculateDigTime(digValue, slotValue);
938 if (num2 < num) {
939 num = num2;
940 result = slotValue;
941 }
942 }
943 }
944 }
945 return result;
946 }
947 }
948}
Engine.Vector3 Vector3
static void Error(object message)
定义 Log.cs:80
static float Remainder(float x, float y)
static float Saturate(float x)
static int Max(int x1, int x2)
static int FrameIndex
定义 Time.cs:26
static double FrameStartTime
定义 Time.cs:42
The spell "Attackment" is wrong, But it is not recommended to change it because many mods rely on thi...
virtual void ProcessAttackment()
virtual BlockDebrisParticleSystem CreateDebrisParticleSystem(SubsystemTerrain subsystemTerrain, Vector3 position, int value, float strength)
virtual float GetDigResilience(int value)
virtual bool IsGatherable_(int value)
virtual BlockPlacementData GetPlacementValue(SubsystemTerrain subsystemTerrain, ComponentMiner componentMiner, int value, TerrainRaycastResult raycastResult)
方块放置方向
virtual float GetHackPower(int value)
virtual int GetToolLevel(int value)
virtual bool IsInteractive(SubsystemTerrain subsystemTerrain, int value)
virtual float GetMeleePower(int value)
virtual float GetQuarryPower(int value)
virtual bool IsAimable_(int value)
virtual bool IsPlacementTransparent_(int value)
virtual int GetPlayerLevelRequired(int value)
virtual bool IsPlaceable_(int value)
virtual BlockPlacementData GetDigValue(SubsystemTerrain subsystemTerrain, ComponentMiner componentMiner, int value, int toolValue, TerrainRaycastResult raycastResult)
virtual float GetShovelPower(int value)
virtual bool GetIsDiggingTransparent(int value)
virtual float GetMeleeHitProbability(int value)
virtual bool IsCollidable_(int value)
virtual string GetDisplayName(SubsystemTerrain subsystemTerrain, int value)
virtual BlockDigMethod GetBlockDigMethod(int value)
virtual BoundingBox[] GetCustomCollisionBoxes(SubsystemTerrain terrain, int value)
static int DamageItem(int value, int damageCount, Entity owner=null)
virtual float ImmersionFactor
virtual ComponentBody ParentBody
virtual ComponentBody StandingOnBody
virtual ? int StandingOnValue
virtual double HitInterval
伤害间隔(原版为0.66f)
SubsystemAudio m_subsystemAudio
ComponentPlayer ComponentPlayer
ComponentCreature ComponentCreature
virtual void RemoveActiveTool(int removeCount)
bool m_digSpeedBasedOnStrengthFactor
挖掘速度是否受玩家力量属性加成
bool Aim(Ray3 aim, AimState state)
static void AddHitValueParticleSystem(float damage, Entity attacker, Entity attacked, Vector3 hitPoint, Vector3 hitDirection)
SubsystemGameInfo m_subsystemGameInfo
virtual void Poke(bool forceRestart)
virtual int FindBestInventoryToolForDigging(int digValue)
static void AttackBody(Attackment attackment)
SubsystemTerrain m_subsystemTerrain
bool Place(TerrainRaycastResult raycastResult)
static void AttackBody(ComponentBody target, ComponentCreature attacker, Vector3 hitPoint, Vector3 hitDirection, float attackPower, bool isMeleeAttack)
bool Interact(TerrainRaycastResult raycastResult)
SubsystemBodies m_subsystemBodies
virtual float CalculateDigTime(int digValue, int toolValue)
ComponentFactors ComponentFactors
override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap)
T? Raycast< T >(Ray3 ray, RaycastMode mode, bool raycastTerrain=true, bool raycastBodies=true, bool raycastMovingBlocks=true, float? reach=null)
void Hit(ComponentBody componentBody, Vector3 hitPoint, Vector3 hitDirection)
virtual object Raycast(Ray3 ray, RaycastMode mode, bool raycastTerrain=true, bool raycastBodies=true, bool raycastMovingBlocks=true, float? Reach=null)
发出射线检测,检测玩家点击到的目标
bool Place(TerrainRaycastResult raycastResult, int value)
static bool IsBlockPlacingAllowed(ComponentBody componentBody)
virtual bool IsLevelSufficientForTool(int toolValue)
virtual void Update(float dt)
ComponentHealth m_componentHealth
override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap)
SubsystemSoundMaterials m_subsystemSoundMaterials
virtual void DamageActiveTool(int damageCount)
bool Dig(TerrainRaycastResult raycastResult)
SubsystemMovingBlocks m_subsystemMovingBlocks
SubsystemBlockBehaviors m_subsystemBlockBehaviors
bool Interact(MovingBlocksRaycastResult raycastResult)
static string Get(string className, int key)
获取在当前语言类名键对应的字符串
virtual void OnItemPlaced(int x, int y, int z, ref BlockPlacementData placementData, int itemValue)
static int ExtractContents(int value)
static int ToCell(float x)
ValuesDictionary ValuesDictionary
Component FindComponent(Type type, string name, bool throwOnError)
virtual Subsystem FindSubsystem(Type type, string name, bool throwOnError)
static void HookAction(string HookName, Func< ModLoader, bool > action)
执行Hook
int GetSlotValue(int slotIndex)
bool Intersection(BoundingBox box)
static Color Transparent
定义 Color.cs:5
static Color White
Vector3 Position
定义 Ray3.cs:3
Vector3 Direction
定义 Ray3.cs:5
static float DistanceSquared(Vector3 v1, Vector3 v2)
static Vector3 Normalize(Vector3 v)
static readonly Vector3 Zero
static float Dot(Vector3 v1, Vector3 v2)
static Point3 FaceToPoint3(int face)
Vector3 HitPoint(float offsetFromSurface=0f)