public override void Explode(Explosion explosion) { base.Explode(explosion); // Shake camera float distToCam = (explosion.Origin - Camera.Active.Position).Length; float factor = 5f / (distToCam * 0.3f); // maxShake / (distToCam * falloff) if (factor > 0.15f) // factor > minShake { Player.ShakeCamera(0.5f, factor); } // Damage player PlayerRaycastResult eResult = RaycastPlayer(explosion.Origin, Player, explosion.PlayerRadius); if (eResult.Intersects) { /* * Curve: * max(min((fa/max(x,0)) - (fa/d), a), 0) * where f = falloff rate, a = max damage, d = max distance, * x = distance */ //float damage = MathHelper.Clamp( // explosion.Damage / (eResult.IntersectionDistance.Value * explosion.DamageFalloff), // 0, explosion.Damage); float damage = explosion.Damage * (float)Math.Cos(eResult.IntersectionDistance.Value / ((2 * explosion.PlayerRadius) / Math.PI)); //float fa = explosion.DamageFalloff * explosion.Damage; // float damage = MathHelper.Clamp((fa / eResult.IntersectionDistance.Value) - (fa / 200f), 0, explosion.Damage); Player.Damage(damage, "Explosion"); } }
public override void Explode(Explosion explosion) { // Destroy terrain Vector3 origin = explosion.Origin; float radius = explosion.BlockRadius; IndexPosition cpos = FixedTerrain.WorldToChunkCoords(origin); IndexPosition blockPos = Chunk.WorldToBlockCoords(origin); blockPos -= cpos * Chunk.SIZE; Chunk chunk; if (Terrain.Chunks.TryGetValue(cpos, out chunk)) { int blockRadius = (int)(radius / Block.CUBE_SIZE); for (int x = -blockRadius; x <= blockRadius; x++) { for (int y = -blockRadius; y <= blockRadius; y++) { for (int z = -blockRadius; z <= blockRadius; z++) { int nx = x + blockPos.X; int ny = y + blockPos.Y; int nz = z + blockPos.Z; IndexPosition ncpos = chunk.WrapBlockCoords(ref nx, ref ny, ref nz); if (!chunk.IsBlockCoordInRange(nx, ny, nz)) { continue; } Vector3 apos = Chunk.ChunkBlockToWorldCoords(ncpos, new IndexPosition(nx, ny, nz)) - Block.HALF_CUBE_3D_SIZE; float dist = Maths.Distance(apos, origin); if (dist > radius) { continue; } int damage = (int)(14 * (1f - (dist / radius))); if (ncpos != cpos) { Chunk otherChunk; if (Terrain.Chunks.TryGetValue(ncpos, out otherChunk)) { otherChunk.DamageBlock(new IndexPosition(nx, ny, nz), damage); } } else { chunk.DamageBlock(new IndexPosition(nx, ny, nz), damage); } } } } } // Apply grenade damage bool ff = DashCMD.GetCVar <bool>("mp_friendlyfire"); if (!DashCMD.GetCVar <bool>("ch_infhealth")) { foreach (ServerMPPlayer player in players.Values) { if (player.Health <= 0 || !ff && explosion.Owner.Team == player.Team && explosion.Owner != player) { continue; } PlayerRaycastResult eResult = RaycastPlayer(explosion.Origin, player, explosion.PlayerRadius); if (eResult.Intersects) { /* * Curve: * max(min((fa/max(x,0)) - (fa/d), a), 0) * where f = falloff rate, a = max damage, d = max distance, * x = distance */ //float damage = MathHelper.Clamp( // explosion.Damage / (eResult.IntersectionDistance.Value * explosion.DamageFalloff), // 0, explosion.Damage); float damage = explosion.Damage * (float)Math.Cos(eResult.IntersectionDistance.Value / ((2 * explosion.PlayerRadius) / Math.PI)); //float fa = explosion.DamageFalloff * explosion.Damage; // float damage = MathHelper.Clamp((fa / eResult.IntersectionDistance.Value) - (fa / 200f), 0, explosion.Damage); DamagePlayer((ServerMPPlayer)explosion.Owner, explosion.EntityName, player, damage, origin); } } } // Fling other grenades radius = explosion.PlayerRadius; for (int i = 0; i < grenades.Count; i++) { GrenadeEntity grenade = grenades[i]; Vector3 dirTo = grenade.Transform.Position - origin; float dist = dirTo.Length; if (dist > radius) { continue; } dirTo += new Vector3(0, 1, 0); dirTo = dirTo.Normalize(); float kickBack = 60 * (1f - (dist / radius)); grenade.PhysicsBody.Velocity += dirTo * kickBack; grenade.Transform.Position.Y += 0.01f; } }
public override void FireBullet(Player _player, Vector3 origin, Vector3 dir, Vector3 recoil, int blockDamage, float playerDamage, float maxDist = float.MaxValue) { ServerMPPlayer player = (ServerMPPlayer)_player; bool sv_impacts = DashCMD.GetCVar <bool>("sv_impacts"); bool sv_hitboxes = DashCMD.GetCVar <bool>("sv_hitboxes"); int shooterPing = player.StateInfo.Owner.Stats.Ping; int rollbackOffset = DashCMD.GetCVar <int>("rp_rollback_offset"); int bulletDelta = player.LastBulletDeltaTime; if (sv_hitboxes) { DashCMD.WriteLine("[RB] Starting bullet {0}ms delta with {1}ms offset", ConsoleColor.Green, bulletDelta, rollbackOffset); } // Raycast BeginRollback(shooterPing + bulletDelta + rollbackOffset); Ray ray = new Ray(origin, dir + recoil); WorldRaycastResult result = Raycast(ray, true, maxDist, player); EndRollback(); // Handle intersection if (result.Intersects) { if (result.HitTerrain) { // Damage terrain TerrainRaycastResult tResult = result.TerrainResult; if (blockDamage > 0) { tResult.Chunk.DamageBlock(tResult.BlockIndex.Value, blockDamage); } } else if (result.HitPlayer) { // Damage player PlayerRaycastResult pResult = result.PlayerResult; bool ff = DashCMD.GetCVar <bool>("mp_friendlyfire"); bool infh = DashCMD.GetCVar <bool>("ch_infhealth"); if (!infh && (ff || player.Team != pResult.Player.Team)) { DamagePlayer(player, player.ItemManager.SelectedItem.GetType().Name, (ServerMPPlayer)pResult.Player, playerDamage, origin); if (sv_impacts) { DashCMD.WriteLine("[IMP] Hit player for {0} damage. Health After: {1}", playerDamage, pResult.Player.Health); } } } ImpactAt(result.IntersectionPosition.Value); } }