Monday, August 30, 2021

What is the Strongest Wall in 41.53? (How the Code Calculates Wall Health)


Edit 2021-09-30:  In 41.55 it looks like they fixed the bug associated with walls, and adjusted the strengths as well.  While the code is almost the same as it was before, some of the numbers have changed.  Maybe I should write another post for the 41.55 version of walls.

With level 10 carpentry, I built 9 different walls from strongest to weakest (left to right).  As you can see, wall strength is a little more complicated than just the material used.  For now, I'm calling it "strength" even though you can also call it "hit points" or "health".

Here are the factors that influence wall strength:

  • Wall Type
  • Character Skill Level
  • Skill Level Required to Construct the Wall
  • Handy Trait (only for log walls)
  • If the Wall Has Been Upgraded
  • Sandbox Option: Player-Built Construction Strength

For the purposes of this entire post, let's assume the Sandbox Options are all set to default.

The strongest wall is:

Level 10 Carpentry.  Metal Frame.  Level 1 wooden wall, upgraded to Level 2, and then to Level 3.  Whether or not you are Handy doesn't matter.

And I think this has been the case since Build 40.  There have been a few changes since Build 40, so assume everything else you read from here on only applies to Build 41 until you get to the Build 40 section at the very end.

The walls in the picture are not all of the walls possible, and they were all built with a level 10 in carpentry and metalworking.  They were also built with the Handy trait, but that only matters with the log wall.  They are listed in order of descending strength:

#2 - Wood Frame.  Level 1 wooden wall, upgraded to Level 2, and then to Level 3.
#3 - Level 1 metal wall upgraded to Level 2
#4 - Level 1 metal wall
#5 - Log Wall
#6 - Level 2 metal wall
#7 - Level 2 wooden wall
#8 - (TIE) Level 1 wooden wall and Level 3 wooden wall 

Yes, if built at the same skill level:
A level 2 wooden wall is stronger than a level 3 wooden wall!
A level 1 metal wall is stronger than a level 2 metal wall!

What is the Strongest Wall I Can Build at My Level of Carpentry?

From level 0 - level 3 carpentry, log walls are the strongest.  Just four logs and some rippedsheets/twine/rope.

Between carpentry level 4 and 6, it depends.  
If you are using metal frames, build the L1 wood wall, and then upgrade it (5 planks, 10 nails).
If you aren't using metal frames and have handy, use the log walls (same 4 logs + binder).
If you aren't using metal frames and don't have handy, build wood walls.

At level 7 carpentry and beyond, the strongest wall is a new level 1 wood wall immediately upgraded to level 2, and then immediately upgraded to level 3 (6 planks, 14 nails).  At level 7, even upgrading only to level 2 is better than a log wall.

If your metalworking level is equal to your carpentry level, a fully upgraded metal wall is stronger until you hit level 9 carpentry.  And remember, at level 10 the fully upgraded wood wall is the strongest.

How Wall Health is Determined in the Code

Let's switch to calling it wall "health" instead of "strength", because that's basically what it is called in the code (calling this post "What is the Healthiest Wall?" sounded bad, so I decided to use "strength" in the introduction instead).

The code for wood (and log) walls starts in ISBuildMenu.lua.  Metal walls are handled in ISBlacksmithMenu.lua.  Metal walls are handled similarly to wood walls in lua, and use the same code when we get to the java, so we'll only look at the wood wall code here.

Once we get past determining the skills and materials required to build the wall, the stats for the wall frame gets set in onWoodenWallFrame:

ISBuildMenu.onWoodenWallFrame = function(worldobjects, sprite, player)
-- sprite, northSprite, corner
    local wall = ISWoodenWall:new(sprite.sprite, sprite.northSprite, sprite.corner, ISBuildMenu.isNailsBoxNeededOpening(2));
    wall.canBarricade = false
    wall.name = "WoodenWallFrame";
    -- set up the required material
    wall.modData["xp:Woodwork"] = 5;
    wall.modData["need:Base.Plank"] = "2";
    wall.modData["need:Base.Nails"] = "2";
    wall.health = 50;
    wall.player = player;
    getCell():setDrag(wall, player);
end

So the frame's health is 50.  

Wall frames are built in ISBuildMenu like a lot of constructions (stairs, crates, rain collectors).  But the actual walls are a little different because they can be upgraded.  You expect a level 3 wall to have more hit points than a level 2 wall (though one of my friends seems to be more concerned about the aesthetic).  They are handled in ISBuildMenu:

ISBuildMenu.onMultiStageBuild = function(worldobjects, stage, item, player)

The definitions of these are in the scripts, in multistagebuild.txt.

Here is the definition of a level 1 wall:

    multistagebuild CreateWoodenWall_1
    {
        PreviousStage:WoodenWallFrame;MetalWallFrame,
        Name:WoodenWallLvl1,
        TimeNeeded:250,
        BonusHealth:400,
        SkillRequired:Woodwork=2,
        ItemsRequired:Base.Plank=2;Base.Nails=4,
        ItemsToKeep:Base.Hammer,
        Sprite:walls_exterior_wooden_01_44,
        NorthSprite:walls_exterior_wooden_01_45,
        CraftingSound:Hammering,
        ID:Create Wooden Wall Lvl 1,
        XP:Woodwork=10,
    }

It's pretty clear what most of the items in this definition means.  BonusHealth is what is important for this discussion.

You can look at multistagebuild.txt if you want to see all the values, but here are the health values for the walls and upgrades:

Bonus Health

Level 1 Wall: 400
Level 2 Wall: 500
Level 3 Wall: 600
Level 1 Metal Wall: 650
Level 2 Metal Wall: 750

Upgrade from L1 Wall to L2 Wall: +100
Upgrade from L1 Wall to L3 Wall: +200
Upgrade from L2 Wall to L3 Wall: +100
Upgrade from L1 Metal Wall to L2 Metal Wall: +100

The code that handles setting the stats of these walls isn't in the lua, it is in the java.  It is in the MultiStageBuilding class.  This is used for both wood and metal walls:

        public void doStage(IsoGameCharacter isoGameCharacter, IsoThumpable isoThumpable, boolean bl) {
            int n = isoThumpable.getHealth();
            int n2 = isoThumpable.getMaxHealth();
            String string = this.sprite;
            if (isoThumpable.north) {
                string = this.northSprite;
            }
            IsoThumpable isoThumpable2 = new IsoThumpable(IsoWorld.instance.getCell(), isoThumpable.square, string, isoThumpable.north, isoThumpable.getTable());
            isoThumpable2.setCanBePlastered(this.canBePlastered);
            if ("doorframe".equals(this.wallType)) {
                isoThumpable2.setIsDoorFrame(true);
                isoThumpable2.setCanPassThrough(true);
                isoThumpable2.setIsThumpable(isoThumpable.isThumpable());
            }
            int n3 = this.bonusHealth;
            switch (SandboxOptions.instance.ConstructionBonusPoints.getValue()) {
            // code edited out by Ed for brevity because we are assuming default values
            }
            Iterator<String> iterator = this.perks.keySet().iterator();
            int n4 = 40;
            switch (SandboxOptions.instance.ConstructionBonusPoints.getValue()) {
            // code edited out by Ed for brevity because we are assuming default values
            }
            while (iterator.hasNext()) {
                String string2 = iterator.next();
                n3 += (isoGameCharacter.getPerkLevel(PerkFactory.Perks.FromString(string2)) - this.perks.get(string2)) * n4;
            }
            isoThumpable2.setMaxHealth(n2 + n3);
            isoThumpable2.setHealth(n + n3);

When you build a level 1 wood wall from a wood frame here are the steps for setting the health:

  • Get the health of the wood frame (this includes any damage taken)
  • Get the maximum health of the wood frame (we know this is 50)
  • Get the Bonus Health value of the level 1 wall (we know this is 400)

Then we look at the "perks" which is basically the skills required to build this wall.  In this case, it is carpentry.  We take the character's level, subtract the carpentry level required to build this wall, multiply that by 40, then add that to the Bonus Health value we had before.  And that number gets added to the original (frame's) health and max health to set the values for the new Level 1 wall.

So this part of the calculation is causing a bug.  A level 10 carpenter has stronger level 2 walls than level 3 walls.

Basically, all that code can be summed up in this formula:

Old Wall (Frame) Health + Bonus Health of New Wall + (40 * (Carpentry Level - Required Level))

L2 Wall: 50 + 500 + (40 * (10 - 4)) = 550 + (40 * 6) = 790

L3 Wall: 50 + 600 + (40 * (10 - 7)) = 650 + (40 * 3) = 770

The difference between the base Bonus Health of a L2 and L3 wall is only 100, and the skill difference between them is 3 (7-4)  and (40 * 3 = 120) so L2 walls are 20 health stronger than L3 walls constructed at the same carpentry level.

When you include upgrading level 1 walls to better walls, this becomes even more pronounced, because you are getting the level multiplier over and over again.

Let's take a look at the difference between creating a level 3 wall and upgrading a level 1 wall to become a level 3 wall, if you are at carpentry level 10 for all of the building and upgrades:

L3 Wall: 50 + 600 + (40 * (10 - 7)) = 650 + 120 = 770
L1 Wall: 50 + 400 + (40 * (10 - 2)) = 450 + 320 = 770
L1 Wall Upgraded to L2 Wall: 770 + 100 + (40 * (10 - 4)) = 870 + 240 = 1110
L2 Wall Upgraded to L3 Wall: 1110 + 100 + (40 * (10 - 7)) = 1210 + 120 = 1330

1330 is quite a bit stronger than 770, at a cost of 2 additional planks and 8 additional nails.

I could argue that, because of the additional materials used, a level 1 wall upgraded to a level 2 wall should be stronger than an original level 2 wall (I don't think it is a strong argument).  Additionally, most people build the best wall they can when they can, so when you want to upgrade your level 1 wall, it is because you built that wall when your carpentry skill was lower.  So you could try arguing this only happens in unrealistic circumstances.

But considering that an unupgraded L2 wall is always stronger than an unupgraded L3 wall with the same carpentry level, it seems evident that the system needs some adjusting.

What About Metal Walls and Log Walls?

Although metal walls get their start in the ISBlacksmithMenu.lua code, they also end up in the MultiStageBuilding class so they have the same problem, with different numbers.  Actually, worse, because you can't build a L2 metal wall until L8 metalworking, while you can build a L1 metal wall at L2 metalworking.  This means that while the Bonus Health difference is still 100, the skill bonus difference amounts to 240, giving a net advantage of 140 health to the L1 metal wall.  At level 10, with a metal frame, the L1 metal wall has 1090 health, while the L2 metal wall has only 950 health.

By the way, metal frames have a health of 120 compared to the wood frame health of 50.  And you can build wood walls over metal frames.  So if you want to strongest wall, start with the strongest frame.

Log walls fall under what appears to be the old system of calculating health.  Much of the code for the old system of constructing wood walls is still there, just unreachable because of comments.  When we want to calculate a log wall's health:

-- return the health of the new wall, it's 200 + 100 per carpentry lvl
function ISWoodenWall:getHealth()
    if self.sprite == "carpentry_02_80" then -- log walls are stronger
	    return 400 + buildUtil.getWoodHealth(self);
    else
        return 200 + buildUtil.getWoodHealth(self);
    end
end

The comment there is in the 41.53 file, and is wrong.

-- give the health of the item, depending on you're carpentry level + if you're a construction worker
buildUtil.getWoodHealth = function(ISItem)
	if not ISItem or not ISItem.player then
		return 100;
	end
	local playerObj = getSpecificPlayer(ISItem.player)
	local health = (playerObj:getPerkLevel(Perks.Woodwork) * 50);
	if playerObj:HasTrait("Handy") then
		health = health + 100;
	end
	return health;
end

We can see here that for the log walls, 50 per carpentry level gets added to the health, with an additional 100 if the character is handy.  So a handy character with level 10 carpentry makes 1000 health log walls.  That's a little better than a L2 metal wall, but not quite as good as a L1 metal wall (at Level 10 metalworking).  At every level, a L2 metal wall is better than a log wall.  If you have handy, a log wall is better than a L2 metal wall, but only if you have handy.

Although handy isn't currently being used to calculate wall health, I'd bet that when they fix the wall health calculations they'll add handy back in.

What About Build 40?

I took a quick look at the Build 40 code.  I'm not sure (because it was a *quick* look), but it is basically the same with these notes:

  • Wooden walls have 200 lower health
  • Metal walls have 200 lower health
  • Log walls have the same health
  • Upgrading metal walls from L1 to L2 gives 420 bonus health, not just 100

This makes metal walls upgraded to L2 much stronger.

Fully upgraded L3 wood walls (completely built at level 10 carpentry) still have more health than log walls, but not by as much.  And unupgraded L2 wood walls are still stronger than unupgraded L3 wood walls.

For Build 40, log walls without handy are strongest until carpentry level 7.  Log walls with handy are strongest until level 8.  At level 9 and 10, fully upgraded wood walls are strongest.

New Mod:  How Strong Is That Wall?


After writing the bulk of this post, I decided to create a mod that allows players to see how much health walls have.  Look at the mod through this link!

Takeaways

Until they fix the system:

  • Never build a level 3 wood wall unless you are upgrading
  • Never build a level 2 metal wall unless you are upgrading

And when they fix the system, it is VERY likely it will only affect walls built from that time forward.  I don't think they'll try having the system modify the walls in your existing saved game.  The health of your existing walls should remain what they were before the fix.  I'll make sure to post and update with the details when it happens.


Thanks for reading!  If you see any mistakes I made, or if you have any questions you'd like me to answer by looking at the code, please let me know!

Friday, August 27, 2021

Do Zombies Get Slower and Weaker as Time Progresses?


In the Sandbox settings, under Zombie Lore, there is the "Decomposition" dropdown.  By default, "Slows + Weakens" is selected.

The wiki says "Decomposition: How time will affect the zombie's speed and strength/toughness."

But do zombies actually get slower and weaker as time progresses?

I don't think so.

How do I figure that, based on the code?

The name of that setting is ZombieLore.Decomp (there can be slight variations, just as SandboxOptions.instance.Lore.Decomp), and I don't see that being used to make zombies slower or weaker.

NOT seeing code isn't particularly convincing, so I decided to take a look at "Slows + Weakens".  If decomposition did make zombies slower or weaker, where would that go in the code?  Probably where strength and speed are used, and where they are initially set.

In the IsoZombie class there is a method called "DoZombieStats".  It is called by both the constructor and the load method.

    public void DoZombieStats() {
        if (SandboxOptions.instance.Lore.Cognition.getValue() == 1) {
            this.cognition = 1;
        }
        if (SandboxOptions.instance.Lore.Cognition.getValue() == 4) {
            this.cognition = Rand.Next(0, 2);
        }
        if (this.strength == -1 && SandboxOptions.instance.Lore.Strength.getValue() == 1) {
            this.strength = 5;
        }
        if (this.strength == -1 && SandboxOptions.instance.Lore.Strength.getValue() == 2) {
            this.strength = 3;
        }
        if (this.strength == -1 && SandboxOptions.instance.Lore.Strength.getValue() == 3) {
            this.strength = 1;
        }
        if (this.strength == -1 && SandboxOptions.instance.Lore.Strength.getValue() == 4) {
            this.strength = Rand.Next(1, 5);
        }
        if (this.speedType == -1) {
            this.speedType = SandboxOptions.instance.Lore.Speed.getValue();
            if (this.speedType == 4) {
                this.speedType = Rand.Next(2);
            }
            if (this.inactive) {
                this.speedType = 3;
            }
        }

Both strength and speed are referenced in this code, but there is nothing referencing either "Decomp" or how long the game has been going on.  I've seen "GetNightsSurvived" and "DaysSinceStart" and "getCalender()" and "getWorldAgeDays" used to determine how much time has passed.  Nothing in IsoZombie seems to associate the date or time with zombie strength or speed.  In IsoZombie, strength isn't actually set to a valid value except for in this portion of code.

Somewhere else I looked was when multiple zombies surround you and drag you down.  This comes from the BodyDamage class

        int n7 = this.getParentChar().getSurroundingAttackingZombies();
        n7 = Math.max(n7, 1);
        n4 -= (n7 - 1) * 10;
        n5 -= (n7 - 1) * 30;
        n6 -= (n7 - 1) * 15;
        int n8 = 3;
        if (SandboxOptions.instance.Lore.Strength.getValue() == 1) {
            n8 = 2;
        }
        if (SandboxOptions.instance.Lore.Strength.getValue() == 3) {
            n8 = 6;
        }
        if (this.ParentChar.Traits.ThickSkinned.isSet()) {
            n4 = (int)((double)n4 / 1.3);
        }
        if (this.ParentChar.Traits.ThinSkinned.isSet()) {
            n4 = (int)((double)n4 * 1.3);
        }
        if (!"EndDeath".equals(this.getParentChar().getHitReaction())) {
            if (!this.getParentChar().isGodMod() && n7 >= n8 && SandboxOptions.instance.Lore.ZombiesDragDown.getValue() && !this.getParentChar().isSitOnGround()) {
                n5 = 0;
                n6 = 0;
                n4 = 0;
                this.getParentChar().setHitReaction("EndDeath");
                this.getParentChar().setDeathDragDown(true);

Here, n7 is the number of zombies surrounding the character, and it looks like the value for n8 is the number of zombies required to take down a survivor.  If zombie strength is normal (or, interestingly, random), it takes 3.  If zombie strength is superhuman, it takes 2.  If zombie strength is weak, it takes 6.  No mention of decomposition state or how long the world has been around.

While not conclusive, this appears to be pretty strong evidence that both the Zombie Decomposition sandbox setting and zombie decomposition in general are not used to weaken and slow down the zombies as time passes.

I've heard that zombies used to get weaker and slower as time progressed.  So either this is just a setting they haven't gotten around to taking out yet, or something that they plan on implementing (or re-implementing) in the future.

Additional Notes:

I didn't see zombie strength affecting how much damage a character takes when hit, so zombie strength may only affect how many zombies are needed to drag a character down.  When I do my post on wall strength, I'll check to see if zombie strength affects how much damage zombies do to constructions.


Thanks for reading!  If you notice a mistake or have any questions you'd like me to answer, please let me know!



Wednesday, August 25, 2021

Why 100% Protection Doesn't Protect 100% of the Time

Update 2021-09-16: In Build 41.54 this has been fixed.  Holes are put in clothing AFTER protection is determined.

Every once in a while I'll hear (read) about someone complaining that they had 100% protection on a body part and still got hit by a zombie.

Should 100% protection protect you 100% of the time?  Maybe.  Maybe not.  But it doesn't.  Why?

Sometimes you get a hole in your clothing from an attack shortly before Project Zomboid calculates whether your clothing protects you from that attack.

The Code

The BodyDamage class is where damage (to your body) is determined.

Before we get to this part of the code, Project Zomboid has already randomly determined which body part is being attacked.

Right before the roll to see if you are hit, it checks to see if you will get a hole because of the attack

        bl = false;
        bl = this.getParentChar().addHoleFromZombieAttacks(BloodBodyPartType.FromIndex(n3));
        if (Rand.Next(100) > n4) {

addHoleFromZombieAttacks is in the IsoGameCharacter class and randomly determines if this zombie attack put a hole in a piece of clothing on the body part being attacked.  This is really important, because if there is a new hole, the protection on that part of your body goes down.

After it checks to see if you got a hole, it checks to see if you've been hit.  So it is possible to get a hole in your clothes and not get hit.

After Project Zomboid determines you've been hit, it figures out if it is a scratch or laceration or bite.  Here is code from what happens if you are scratched.  The code for lacerations and bites is almost identical to this part:

                Float f2 = Float.valueOf(this.getParentChar().getBodyPartClothingDefense(n3, false, false));
                if (this.getHealth() > 0.0f) {
                    this.getParentChar().getEmitter().playSound("ZombieScratch");
                }
                if ((float)Rand.Next(100) < f2.floatValue()) {
                    return false;
                }

getBodyPartClothingDefense adds up the clothing protection from the body part being attacked, with a maximum of 100.  Remember, though, that if you acquired a hole right before this, your protection is lower than it was right before the attack.

If a random 0-99 roll is less than defense value of your clothes, the protection holds and nothing else happens.

If the protection doesn't hold, then the code continues and you take the damage (and possibly get the zombie infection).

Some Thoughts

If you are wearing magical longjohns with 100% protection to your upper torso, a single attack can put a hole in it and reduce that protection to 0%.  

If you are wearing layers, a single hole will not reduce your protection by as much, and if your layers gives you more than 100% protection, you may still have 100% protection!

Some items, like the Hard Hat, can't have holes.  Unless a Hard Hat gets knocked off, you will never take damage to the head while wearing it.


Thanks for reading!  If you see a mistake or want me to answer a question about the code, please let me know!


Update:  Project Zomboid developer lemmy101 posted that this is unintentional and will be fixed.  I'll be sure to follow up on this topic when that happens!

Monday, August 23, 2021

How Head Protection Works

Edit 2021-09-18: I misinterpreted this code a little.  Here I say that the code checks to see if a hat/helmet falls off if the attack is on the head or neck.  The correct interpretation is that the code checks to see if any clothing with the ChanceToFall attribute falls whenever there is an attack (with the chance to fall being modified if the attack is on the head or neck).  For more about this, take a look at this newer blog entry.

Head and neck protection is just like protection for other body parts, with one little addition - your hat might fall off.

So how does it work?

When a zombie attacks you, here are the steps:

  • Find hit location (the body part being attacked)
  • Calculate (potential) damage
  • Check if attack puts a hole in the clothing for that body part
  • Check to see if the attack hits
  • Check if a hat falls off
  • Determine severity of the attack (scratch, laceration, bite)
  • Check if the clothing protection repels the attack
  • Actually damage the character (change the health stat, etc)

Every time you see your hat fall off your head, it is because you were HIT on the head or neck, but instead of you taking damage your hat just fell off.  If your hat stays on, it can still protect you from the attack.

Let's look at the code!

Hats Sometimes Fall

Once the code has determined your survivor is hit

        if (Rand.Next(100) > n4) {
            n = 1;
            boolean bl4 = false;
            if (this.getParentChar().helmetFall(n3 == BodyPartType.ToIndex(BodyPartType.Neck) || n3 == BodyPartType.ToIndex(BodyPartType.Head))) {
                return false;
            }

Before anything else actually happens, it checks to see if your "helmet" falls!  I say "helmets" but this applies to all hats!  The baseball cap has a much greater chance of falling off here.  If it does it returns and skips all the code that calculates the damage!  No damage!

Your hat just took the hit for you.

helmetFall actually leads to a bunch of code in IsoGameCharacter, where it determines whether or not your hat fell based on the ChanceToFall attribute in the scripts.  In vanilla PZ the hats are in clothing_hats.txt, and here's an example of the hardhat:

	item Hat_HardHat
	{
		Type = Clothing,
		DisplayName = Hard Hat,
		ClothingItem = Hat_HardHat,
		BodyLocation = Hat,
		IconsForTexture = HardHatYellow;HardHatBlue;HardHatRed;HardHatWhite,
		CanHaveHoles = false,
		BloodLocation = Head,
		BiteDefense = 100,
		ScratchDefense = 100,
		ChanceToFall = 20,
		Insulation = 0.15,
		WindResistance = 0.25,
		WaterResistance = 0.5,
	}

Hard Hats have a base 20% chance to fall.  If you look at the other hats, you can see Baseball Caps have an 80% chance to fall and Football Helmets have a 3% chance to fall.

One thing I find interesting is that even if the hat doesn't normally protect your neck, a neck attack can still trigger your hat to fall and avoid causing damage to you.

Hats Also Protect Like Other Clothing

Once you are hit, the severity of the hit is calculated and then it checks to see if your clothing protected you, also in BodyDamage:

                Float f2 = Float.valueOf(this.getParentChar().getBodyPartClothingDefense(n3, false, false));
                if (this.getHealth() > 0.0f) {
                    this.getParentChar().getEmitter().playSound("ZombieScratch");
                }
                if ((float)Rand.Next(100) < f2.floatValue()) {
                    return false;
                }

getBodyPartClothingDefense goes through your clothes and determines which clothing covers the body part that was hit and then adds up the defense values (ScratchDefense for scratches and lacerations, BiteDefense for bites).

Once the defense number (up to 100) is calculated, it plays the awful zombie scratch sound.  

Then, it randomly rolls to check if your defense protected you from the attack.  If it did protect you, you skip all the damage!

So this is why sometimes you heard the zombie crunch sound but when you check your health status you have taken no damage.  Your armor protected you.

There Might Be a Bug

On 2021-08-13 I filed a bug stating that the ChanceToFall was being used incorrectly, opposite to how it should be used.  This would mean that a Hard Hat with a 20% chance to fall is actually falling 80% of the time.

Whether or not I am right about the bug or if the bug has been fixed by the time you read this, falling hats protect you from attacks.

Conclusion

Always wear a hat!  Even if it doesn't protect you much, a fallen hat means you were completely protected from an attack that otherwise would have caused head or neck damage.  And when the hat doesn't fall off, it still protects you like other pieces of clothing protect other parts of your body.


Thanks for reading!  If you see a mistake here or if you have any questions you'd like me to answer, let me know!


Do Gloves Protect You From Broken Glass?

Yes, gloves protect you from handling broken glass - any pair of gloves.  But gloves are not needed when removing broken glass from a smashe...