private void SlowDown(MatrixIntersection i, int collisions) { if (i.Matrix1.IsMovable && i.Matrix1.MatrixMove.IsMovingServer) { InternalSlowDown(i.Matrix1); } if (i.Matrix2.IsMovable && i.Matrix2.MatrixMove.IsMovingServer) { InternalSlowDown(i.Matrix2); } void InternalSlowDown(MatrixInfo info) { float slowdownFactor = Mathf.Clamp( 1f - (Mathf.Clamp(collisions, 1, 50) / 100f) + info.Mass, 0.1f, 0.95f ); float speed = (info.MatrixMove.ServerState.Speed * slowdownFactor) - 0.07f; if (speed <= 1f) { info.MatrixMove.StopMovement(); } else { info.MatrixMove.SetSpeed(speed); } } }
public bool Equals(MatrixIntersection other) { return((Matrix1.Equals(other.Matrix1) && Matrix2.Equals(other.Matrix2)) || (Matrix1.Equals(other.Matrix2) && Matrix2.Equals(other.Matrix1))); }
private void CheckTileCollisions(MatrixIntersection i) { byte collisions = 0; foreach (Vector3Int worldPos in i.Rect.ToBoundsInt().allPositionsWithin) { Vector3Int cellPos1 = i.Matrix1.MetaTileMap.WorldToCell(worldPos); if (!i.Matrix1.Matrix.HasTile(cellPos1, true)) { continue; } Vector3Int cellPos2 = i.Matrix2.MetaTileMap.WorldToCell(worldPos); if (!i.Matrix2.Matrix.HasTile(cellPos2, true)) { continue; } float resistance1 = i.Matrix1.MetaTileMap.Resistance(cellPos1, true); if (resistance1 <= 0f) { continue; } float resistance2 = i.Matrix2.MetaTileMap.Resistance(cellPos2, true); if (resistance2 <= 0f) { continue; } collisionLocations.Add(worldPos); // // ******** DESTROY STUFF!!! ******** // //total damage to apply to victim tile if (resistance1 + (10 * i.Matrix1.Speed) >= resistance2 + (10 * i.Matrix2.Speed)) { //attacker tile is stronger: //destroy victim tile TryPushing(i.Matrix2, cellPos2, i.Matrix1.MovementVector, i.Matrix1.Speed); ApplyCritDamage(i.Matrix2, cellPos2, worldPos); //slightly damage adjacent victim tiles ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.up, resistance1 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.down, resistance1 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.left, resistance1 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix2, cellPos2 + Vector3Int.right, resistance1 * 0.4f, worldPos); //damage back attacker TryPushing(i.Matrix1, cellPos1, i.Matrix2.MovementVector, i.Matrix2.Speed); ApplyDamage(i.Matrix1, cellPos1, resistance2, worldPos); if (resistance2 > EXTRA_COLLISION_THRESHOLD) { collisions += (byte)((resistance2 - EXTRA_COLLISION_THRESHOLD) / EXTRA_COLLISION_THRESHOLD); } } else { //victim tile is stronger //destroy weaker tile TryPushing(i.Matrix1, cellPos1, i.Matrix2.MovementVector, i.Matrix2.Speed); ApplyCritDamage(i.Matrix1, cellPos1, worldPos); //slightly damage adjacent tiles ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.up, resistance2 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.down, resistance2 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.left, resistance2 * 0.4f, worldPos); ApplyTilemapDamage(i.Matrix1, cellPos1 + Vector3Int.right, resistance2 * 0.4f, worldPos); //damage back TryPushing(i.Matrix2, cellPos2, i.Matrix1.MovementVector, i.Matrix1.Speed); ApplyDamage(i.Matrix2, cellPos2, resistance1, worldPos); if (resistance1 > EXTRA_COLLISION_THRESHOLD) { collisions += (byte)((resistance1 - EXTRA_COLLISION_THRESHOLD) / EXTRA_COLLISION_THRESHOLD); } } collisions++; //Wires (since they don't have Integrity) ApplyWireDamage(i.Matrix1, cellPos1); ApplyWireDamage(i.Matrix2, cellPos2); //Heat shit up i.Matrix1.ReactionManager.ExposeHotspot(cellPos1); i.Matrix2.ReactionManager.ExposeHotspot(cellPos2); //Other foreach (var layer in layersToRemove) { i.Matrix1.TileChangeManager.RemoveTile(cellPos1, layer); i.Matrix2.TileChangeManager.RemoveTile(cellPos2, layer); } foreach (var layer in effectsToRemove) { i.Matrix1.TileChangeManager.RemoveOverlay(cellPos1, layer); i.Matrix2.TileChangeManager.RemoveOverlay(cellPos2, layer); } } if (collisions > 0) { var epicenter = collisionLocations[collisionLocations.Count / 2]; ExplosionUtils.PlaySoundAndShake( epicenter, (byte)Mathf.Clamp(collisions * 12, 16, byte.MaxValue), Mathf.Clamp(collisions * 8, 15, 127) ); SlowDown(i, collisions); if (collisions > 6 && Mathf.Max(i.Matrix1.Speed, i.Matrix2.Speed) > 6) { i.Matrix1.Matrix.OnEarthquake.Invoke(epicenter, collisions); i.Matrix2.Matrix.OnEarthquake.Invoke(epicenter, collisions); } collisionLocations.Clear(); } //Damage methods void ApplyDamage(MatrixInfo victimMatrix, Vector3Int cellPos, float hitEnergy, Vector3Int worldPos) { //LivingHealthBehaviour hitEnergy -= ApplyLivingDamage(victimMatrix, cellPos, hitEnergy); //TilemapDamage ApplyTilemapDamage(victimMatrix, cellPos, hitEnergy, worldPos); // //Integrity ApplyIntegrityDamage(victimMatrix, cellPos, hitEnergy); } void ApplyCritDamage(MatrixInfo victimMatrix, Vector3Int cellPos, Vector3Int worldPos) { //LivingHealthBehaviour ApplyLivingDamage(victimMatrix, cellPos, 9001); //TilemapDamage ApplyTilemapDamage(victimMatrix, cellPos, 9001, worldPos); //Integrity ApplyIntegrityDamage(victimMatrix, cellPos, 9001); //Underfloor RemoveUnderfloor(victimMatrix, cellPos); } void RemoveUnderfloor(MatrixInfo matrix, Vector3Int cellPos) { var Node = matrix.Matrix.GetMetaDataNode(cellPos); if (Node != null) { foreach (var electricalData in Node.ElectricalData) { electricalData.InData.DestroyThisPlease(); } } } void ApplyTilemapDamage(MatrixInfo matrix, Vector3Int cellPos, float damage, Vector3Int worldPos) { matrix.MetaTileMap.ApplyDamage(cellPos, damage, worldPos); if (damage > 9000) { foreach (var damageableLayer in matrix.MetaTileMap.LayersValues) { if (damageableLayer.LayerType == LayerType.Objects) { continue; } matrix.TileChangeManager.RemoveTile(cellPos, damageableLayer.LayerType); } } } void ApplyWireDamage(MatrixInfo matrix, Vector3Int cellPos) { foreach (var wire in matrix.Matrix.Get <CableInheritance>(cellPos, true)) { if (Random.value >= 0.5) { //Sparks wire.QueueForDemolition(wire); StartCoroutine(DestroyWireWithDelay(wire, (byte)(Random.value * 20f))); } else { //Destruction wire.toDestroy(); } } } float ApplyIntegrityDamage(MatrixInfo matrix, Vector3Int cellPos, float damage) { float resistance = 0f; foreach (var integrity in matrix.Matrix.Get <Integrity>(cellPos, true)) { resistance += integrity.integrity; integrity.ApplyDamage(damage, AttackType.Melee, DamageType.Brute); } return(resistance); } float ApplyLivingDamage(MatrixInfo matrix, Vector3Int cellPos, float damage) { byte count = 0; foreach (var healthBehaviour in matrix.Matrix.Get <LivingHealthBehaviour>(cellPos, true)) { healthBehaviour.ApplyDamageToBodypart(matrix.GameObject, damage, AttackType.Melee, DamageType.Brute); count++; } return(count * 50); } void TryPushing(MatrixInfo matrix, Vector3Int cellPos, Vector2Int pushVector, float speed) { if (pushVector == Vector2Int.zero) { return; } foreach (var pushPull in matrix.Matrix.Get <PushPull>(cellPos, true)) { byte pushes = (byte)Mathf.Clamp(speed / 4, 1, 4); for (int j = 0; j < pushes; j++) { pushPull.QueuePush(pushVector, speed * Random.Range(0.8f, 1.1f)); } } } IEnumerator DestroyWireWithDelay(CableInheritance wire, byte timer) { yield return(WaitFor.Seconds(timer)); if (wire != null) { wire.toDestroy(); } } }
public bool Equals(MatrixIntersection other) => Matrix1 == other.Matrix1 && Matrix2 == other.Matrix2 || Matrix1 == other.Matrix2 && Matrix2 == other.Matrix1;