diff --git a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs index 0babeb5140..3a9146557d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Combat/CombatModule.cs @@ -96,6 +96,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule ScenePresence killingAvatar = null; // string killingAvatarMessage; + // check to see if it is an NPC and just remove it + INPCModule NPCmodule = deadAvatar.Scene.RequestModuleInterface(); + if (NPCmodule != null && NPCmodule.DeleteNPC(deadAvatar.UUID, deadAvatar.Scene)) + { + return; + } + if (killerObjectLocalID == 0) deadAvatarMessage = "You committed suicide!"; else @@ -145,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule catch (InvalidOperationException) { } - deadAvatar.Health = 100; + deadAvatar.setHealthWithUpdate(100.0f); deadAvatar.Scene.TeleportClientHome(deadAvatar.UUID, deadAvatar.ControllingClient); } @@ -154,14 +161,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Combat.CombatModule try { ILandObject obj = avatar.Scene.LandChannel.GetLandObject(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); - - if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0) + if ((obj.LandData.Flags & (uint)ParcelFlags.AllowDamage) != 0 + || avatar.Scene.RegionInfo.RegionSettings.AllowDamage) { avatar.Invulnerable = false; } else { avatar.Invulnerable = true; + if (avatar.Health < 100.0f) + { + avatar.setHealthWithUpdate(100.0f); + } } } catch (Exception) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 91e6e5a452..7e49a5e2cc 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -3312,23 +3312,53 @@ namespace OpenSim.Region.Framework.Scenes } } - if (Invulnerable) + // Gods do not take damage and Invulnerable is set depending on parcel/region flags + if (Invulnerable || GodLevel > 0) return; - + + // The following may be better in the ICombatModule + // probably tweaking of the values for ground and normal prim collisions will be needed float starthealth = Health; uint killerObj = 0; + SceneObjectPart part = null; foreach (uint localid in coldata.Keys) { - SceneObjectPart part = Scene.GetSceneObjectPart(localid); - - if (part != null && part.ParentGroup.Damage != -1.0f) - Health -= part.ParentGroup.Damage; + if (localid == 0) + { + part = null; + } else { - if (coldata[localid].PenetrationDepth >= 0.10f) + part = Scene.GetSceneObjectPart(localid); + } + if (part != null) + { + // Ignore if it has been deleted or volume detect + if (!part.ParentGroup.IsDeleted && !part.ParentGroup.IsVolumeDetect) + { + if (part.ParentGroup.Damage > 0.0f) + { + // Something with damage... + Health -= part.ParentGroup.Damage; + part.ParentGroup.Scene.DeleteSceneObject(part.ParentGroup, false); + } + else + { + // An ordinary prim + if (coldata[localid].PenetrationDepth >= 0.10f) + Health -= coldata[localid].PenetrationDepth * 5.0f; + } + } + } + else + { + // 0 is the ground + // what about collisions with other avatars? + if (localid == 0 && coldata[localid].PenetrationDepth >= 0.10f) Health -= coldata[localid].PenetrationDepth * 5.0f; } + if (Health <= 0.0f) { if (localid != 0) @@ -3344,7 +3374,16 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendHealth(Health); } if (Health <= 0) + { m_scene.EventManager.TriggerAvatarKill(killerObj, this); + } + if (starthealth == Health && Health < 100.0f) + { + Health += 0.03f; + if (Health > 100.0f) + Health = 100.0f; + ControllingClient.SendHealth(Health); + } } }