diff --git a/CHANGELOG.md b/CHANGELOG.md
index 43c3498d68..734b6c53a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Gave the axe a third attack
 - A new secondary charged melee attack for the hammer
 - Added Dutch translations
+- Buff system
 
 ### Changed
 
diff --git a/assets/common/items/food/apple_stick.ron b/assets/common/items/food/apple_stick.ron
index 5bf9454978..7d5071e5f7 100644
--- a/assets/common/items/food/apple_stick.ron
+++ b/assets/common/items/food/apple_stick.ron
@@ -1,6 +1,6 @@
 ItemDef(
     name: "Apple Stick",
-    description: "Restores 20 Health",
+    description: "Restores 25 Health",
     kind: Consumable(
         kind: "AppleStick",
         effect: Health((
diff --git a/assets/common/items/npc_armor/back/backpack_0.ron b/assets/common/items/npc_armor/back/backpack_0.ron
new file mode 100644
index 0000000000..00a64c0d47
--- /dev/null
+++ b/assets/common/items/npc_armor/back/backpack_0.ron
@@ -0,0 +1,12 @@
+ItemDef(
+    name: "Rugged Backpack",
+    description: "Keeps all your stuff together.",
+    kind: Armor(
+        (
+            kind: Back("Backpack0"),
+            stats: (
+                protection: Normal(0.0)),            
+        )
+    ),
+    quality: Moderate,
+)
diff --git a/assets/common/items/npc_armor/back/backpack_blue_0.ron b/assets/common/items/npc_armor/back/backpack_blue_0.ron
new file mode 100644
index 0000000000..66446c93f2
--- /dev/null
+++ b/assets/common/items/npc_armor/back/backpack_blue_0.ron
@@ -0,0 +1,12 @@
+ItemDef(
+    name: "Rugged Backpack",
+    description: "Keeps all your stuff together.",
+    kind: Armor(
+        (
+            kind: Back("BackpackBlue0"),
+            stats: (
+                protection: Normal(0.0)),            
+        )
+    ),
+    quality: Moderate,
+)
diff --git a/assets/voxygen/element/animation/buff_frame/1.png b/assets/voxygen/element/animation/buff_frame/1.png
new file mode 100644
index 0000000000..e05166cd46
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/1.png differ
diff --git a/assets/voxygen/element/animation/buff_frame/2.png b/assets/voxygen/element/animation/buff_frame/2.png
new file mode 100644
index 0000000000..54c5183ec1
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/2.png differ
diff --git a/assets/voxygen/element/animation/buff_frame/3.png b/assets/voxygen/element/animation/buff_frame/3.png
new file mode 100644
index 0000000000..b0a196aeac
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/3.png differ
diff --git a/assets/voxygen/element/animation/buff_frame/4.png b/assets/voxygen/element/animation/buff_frame/4.png
new file mode 100644
index 0000000000..beceaf397b
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/4.png differ
diff --git a/assets/voxygen/element/animation/buff_frame/5.png b/assets/voxygen/element/animation/buff_frame/5.png
new file mode 100644
index 0000000000..4cb8dc04c1
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/5.png differ
diff --git a/assets/voxygen/element/animation/buff_frame/6.png b/assets/voxygen/element/animation/buff_frame/6.png
new file mode 100644
index 0000000000..4bc7af2a36
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/6.png differ
diff --git a/assets/voxygen/element/animation/buff_frame/7.png b/assets/voxygen/element/animation/buff_frame/7.png
new file mode 100644
index 0000000000..80dcb85b44
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/7.png differ
diff --git a/assets/voxygen/element/animation/buff_frame/8.png b/assets/voxygen/element/animation/buff_frame/8.png
new file mode 100644
index 0000000000..e158dfbb97
Binary files /dev/null and b/assets/voxygen/element/animation/buff_frame/8.png differ
diff --git a/assets/voxygen/element/icons/de_buffs/buff_plus_0.png b/assets/voxygen/element/icons/de_buffs/buff_plus_0.png
new file mode 100644
index 0000000000..7ad6751359
Binary files /dev/null and b/assets/voxygen/element/icons/de_buffs/buff_plus_0.png differ
diff --git a/assets/voxygen/element/icons/de_buffs/debuff_bleed_0.png b/assets/voxygen/element/icons/de_buffs/debuff_bleed_0.png
new file mode 100644
index 0000000000..4638eeb618
Binary files /dev/null and b/assets/voxygen/element/icons/de_buffs/debuff_bleed_0.png differ
diff --git a/assets/voxygen/element/icons/de_buffs/debuff_skull_0.png b/assets/voxygen/element/icons/de_buffs/debuff_skull_0.png
new file mode 100644
index 0000000000..1e16dcf7ce
Binary files /dev/null and b/assets/voxygen/element/icons/de_buffs/debuff_skull_0.png differ
diff --git a/assets/voxygen/element/icons/m1.png b/assets/voxygen/element/icons/m1.png
index 774ae38bc5..1b5f113651 100644
Binary files a/assets/voxygen/element/icons/m1.png and b/assets/voxygen/element/icons/m1.png differ
diff --git a/assets/voxygen/element/icons/m2.png b/assets/voxygen/element/icons/m2.png
index aeb57b3d46..0e346644b9 100644
Binary files a/assets/voxygen/element/icons/m2.png and b/assets/voxygen/element/icons/m2.png differ
diff --git a/assets/voxygen/element/skillbar/bar_content.png b/assets/voxygen/element/skillbar/bar_content.png
index 61d1f93094..5f27678238 100644
Binary files a/assets/voxygen/element/skillbar/bar_content.png and b/assets/voxygen/element/skillbar/bar_content.png differ
diff --git a/assets/voxygen/element/skillbar/bg.png b/assets/voxygen/element/skillbar/bg.png
new file mode 100644
index 0000000000..eda76288f4
Binary files /dev/null and b/assets/voxygen/element/skillbar/bg.png differ
diff --git a/assets/voxygen/element/skillbar/energybar_bg.png b/assets/voxygen/element/skillbar/energybar_bg.png
deleted file mode 100644
index c05ee0e667..0000000000
Binary files a/assets/voxygen/element/skillbar/energybar_bg.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/frame.png b/assets/voxygen/element/skillbar/frame.png
new file mode 100644
index 0000000000..8af8fe295e
Binary files /dev/null and b/assets/voxygen/element/skillbar/frame.png differ
diff --git a/assets/voxygen/element/skillbar/healthbar_bg.png b/assets/voxygen/element/skillbar/healthbar_bg.png
deleted file mode 100644
index 3696ab4fd3..0000000000
Binary files a/assets/voxygen/element/skillbar/healthbar_bg.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/skillbar_slot.png b/assets/voxygen/element/skillbar/skillbar_slot.png
deleted file mode 100644
index 9a132d9882..0000000000
Binary files a/assets/voxygen/element/skillbar/skillbar_slot.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/skillbar_slot_active.png b/assets/voxygen/element/skillbar/skillbar_slot_active.png
deleted file mode 100644
index 1cbfb65d5c..0000000000
Binary files a/assets/voxygen/element/skillbar/skillbar_slot_active.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/skillbar_slot_big.png b/assets/voxygen/element/skillbar/skillbar_slot_big.png
deleted file mode 100644
index c7f27c4897..0000000000
Binary files a/assets/voxygen/element/skillbar/skillbar_slot_big.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/skillbar_slot_l.png b/assets/voxygen/element/skillbar/skillbar_slot_l.png
deleted file mode 100644
index 5e786baebf..0000000000
Binary files a/assets/voxygen/element/skillbar/skillbar_slot_l.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/skillbar_slot_l_active.png b/assets/voxygen/element/skillbar/skillbar_slot_l_active.png
deleted file mode 100644
index d146f3d20f..0000000000
Binary files a/assets/voxygen/element/skillbar/skillbar_slot_l_active.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/skillbar_slot_r.png b/assets/voxygen/element/skillbar/skillbar_slot_r.png
deleted file mode 100644
index d6d6030958..0000000000
Binary files a/assets/voxygen/element/skillbar/skillbar_slot_r.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/skillbar_slot_r_active.png b/assets/voxygen/element/skillbar/skillbar_slot_r_active.png
deleted file mode 100644
index dd4eef2233..0000000000
Binary files a/assets/voxygen/element/skillbar/skillbar_slot_r_active.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/xp_bar_content.png b/assets/voxygen/element/skillbar/xp_bar_content.png
deleted file mode 100644
index f44d2432d7..0000000000
Binary files a/assets/voxygen/element/skillbar/xp_bar_content.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/xp_bar_left.png b/assets/voxygen/element/skillbar/xp_bar_left.png
deleted file mode 100644
index 4693d465bb..0000000000
Binary files a/assets/voxygen/element/skillbar/xp_bar_left.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/xp_bar_mid.png b/assets/voxygen/element/skillbar/xp_bar_mid.png
deleted file mode 100644
index 6558458ce2..0000000000
Binary files a/assets/voxygen/element/skillbar/xp_bar_mid.png and /dev/null differ
diff --git a/assets/voxygen/element/skillbar/xp_bar_right.png b/assets/voxygen/element/skillbar/xp_bar_right.png
deleted file mode 100644
index c45a6ba988..0000000000
Binary files a/assets/voxygen/element/skillbar/xp_bar_right.png and /dev/null differ
diff --git a/assets/voxygen/i18n/en.ron b/assets/voxygen/i18n/en.ron
index 04a12e119f..5239007e82 100644
--- a/assets/voxygen/i18n/en.ron
+++ b/assets/voxygen/i18n/en.ron
@@ -183,7 +183,8 @@ https://account.veloren.net."#,
         "hud.chat.pvp_melee_kill_msg": "[{attacker}] defeated [{victim}]",
         "hud.chat.pvp_ranged_kill_msg": "[{attacker}] shot [{victim}]",
         "hud.chat.pvp_explosion_kill_msg": "[{attacker}] blew up [{victim}]",
-        "hud.chat.pvp_energy_kill_msg": "[{attacker}] used magic to kill [{victim}]",
+        "hud.chat.pvp_energy_kill_msg": "[{attacker}] killed [{victim}] with magic",
+        "hud.chat.pvp_buff_kill_msg": "[{attacker}] killed [{victim}]",
 
         "hud.chat.npc_melee_kill_msg": "{attacker} killed [{victim}]",
         "hud.chat.npc_ranged_kill_msg": "{attacker} shot [{victim}]",
@@ -290,6 +291,8 @@ magically infused items?"#,
         "hud.settings.transparency": "Transparency",
         "hud.settings.hotbar": "Hotbar",
         "hud.settings.toggle_shortcuts": "Toggle Shortcuts",
+        "hud.settings.buffs_skillbar": "Buffs at Skillbar",
+        "hud.settings.buffs_mmap": "Buffs at Minimap",
         "hud.settings.toggle_bar_experience": "Toggle Experience Bar",
         "hud.settings.scrolling_combat_text": "Scrolling Combat Text",
         "hud.settings.single_damage_number": "Single Damage Numbers",
@@ -342,9 +345,9 @@ magically infused items?"#,
         "hud.settings.refresh_rate": "Refresh Rate",
         "hud.settings.save_window_size": "Save window size",
         "hud.settings.lighting_rendering_mode": "Lighting Rendering Mode",
-        "hud.settings.lighting_rendering_mode.ashikhmin": "Type A",
-        "hud.settings.lighting_rendering_mode.blinnphong": "Type B",
-        "hud.settings.lighting_rendering_mode.lambertian": "Type L",
+        "hud.settings.lighting_rendering_mode.ashikhmin": "Type A - High    ",
+        "hud.settings.lighting_rendering_mode.blinnphong": "Type B - Medium",
+        "hud.settings.lighting_rendering_mode.lambertian": "Type L - Cheap",
         "hud.settings.shadow_rendering_mode": "Shadow Rendering Mode",
         "hud.settings.shadow_rendering_mode.none": "None",
         "hud.settings.shadow_rendering_mode.cheap": "Cheap",
@@ -508,6 +511,16 @@ Protection
         "esc_menu.quit_game": "Quit Game",
         /// End Escape Menu Section
 
+        /// Buffs and Debuffs
+        "buff.remove": "Click to remove",
+        "buff.title.missing": "Missing Title", 
+        "buff.desc.missing": "Missing Description", 
+        // Buffs
+        "buff.title.heal_test": "Heal Test", 
+        "buff.desc.heal_test": "This is a test buff to test healing.",   
+        // Debuffs   
+        "debuff.title.bleed_test": "Bleed Test", 
+        "debuff.desc.bleed_test": "This is a test debuff to test bleeding.",
     },
 
 
diff --git a/assets/voxygen/i18n/es_la.ron b/assets/voxygen/i18n/es_la.ron
index 866257d619..8b13d7e628 100644
--- a/assets/voxygen/i18n/es_la.ron
+++ b/assets/voxygen/i18n/es_la.ron
@@ -65,6 +65,7 @@ VoxygenLocalization(
         "common.create": "Crear",
         "common.okay": "Ok",
         "common.accept": "Aceptar",
+        "common.decline": "Rechazar",
         "common.disclaimer": "Cuidado",
         "common.cancel": "Cancelar",
         "common.none": "Ninguno",
@@ -73,6 +74,13 @@ VoxygenLocalization(
         "common.you": "Tu",
         "common.automatic": "Automatico",
         "common.random": "Aleatorio",
+        // Settings Window title
+        "common.interface_settings": "Ajustes de Interfaz",
+        "common.gameplay_settings": "Ajustes de Jugabilidad",
+        "common.controls_settings": "Ajustes de Controles",
+        "common.video_settings": "Ajustes de Graficos",
+        "common.sound_settings": "Ajustes de Sonido",
+        "common.language_settings": "Ajustes de Idiomas",
 
         // Message when connection to the server is lost
         "common.connection_lost": r#"Conexión perdida!
@@ -89,9 +97,11 @@ El cliente está actualizado?"#,
 
         "common.weapons.axe": "Hacha",
         "common.weapons.sword": "Espada",
-        "common.weapons.staff": "Báculo",
+        "common.weapons.staff": "Vara Mágica",
         "common.weapons.bow": "Arco",
         "common.weapons.hammer": "Martillo",
+        "common.weapons.sceptre": "Cetro curativo",
+        "common.rand_appearance": "Nombre y Apariencia Aleatoria",
         /// End Common section
 
 
@@ -141,6 +151,9 @@ https://account.veloren.net."#,
         "main.login.invalid_character": "El personaje seleccionado no es válido",
         "main.login.client_crashed": "El cliente crasheó",
         "main.login.not_on_whitelist": "No estas en la lista. Contacta al Dueño del Servidor si quieres unirte.",
+        "main.login.banned": "Usted ha sido baneado por la siguiente razón",
+        "main.login.kicked": "Te han echado por la siguiente razón",
+
 
         /// End Main screen section
 
@@ -153,6 +166,7 @@ https://account.veloren.net."#,
         "hud.waypoint_saved": "Marcador Guardado",
 
         "hud.press_key_to_show_keybindings_fmt": "Presiona {key} para mostrar los controles del teclado",
+        "hud.press_key_to_toggle_lantern_fmt": "[{key}] Encender Linterna",
         "hud.press_key_to_show_debug_info_fmt": "Presiona {key} para mostrar información de depuración",
         "hud.press_key_to_toggle_keybindings_fmt": "Presiona {key} para alternar los controles del teclado",
         "hud.press_key_to_toggle_debug_info_fmt": "Presiona {key} para alternar la información de depuración",
@@ -160,6 +174,21 @@ https://account.veloren.net."#,
         // Chat outputs
         "hud.chat.online_msg": "[{name}] se ha conectado.",
         "hud.chat.offline_msg": "[{name}] se ha desconectado.",
+        
+        "hud.chat.default_death_msg": "[{name}] Murió",
+        "hud.chat.environmental_kill_msg": "[{name}] Murió en {environment}",
+        "hud.chat.fall_kill_msg": "[{name}] Murió por el daño de la caída",
+        "hud.chat.suicide_msg": "[{name}] Murió por heridas autoinfligidas",
+
+        "hud.chat.pvp_melee_kill_msg": "[{attacker}] Derroto a [{victim}]",
+        "hud.chat.pvp_ranged_kill_msg": "[{attacker}] Le Disparo a [{victim}]",
+        "hud.chat.pvp_explosion_kill_msg": "[{attacker}] Hizo explotar a [{victim}]",
+        "hud.chat.pvp_energy_kill_msg": "[{attacker}] usó magia para matar [{victim}]",
+
+        "hud.chat.npc_melee_kill_msg": "{attacker} Mató a [{victim}]",
+        "hud.chat.npc_ranged_kill_msg": "{attacker} Le Disparo a [{victim}]",
+        "hud.chat.npc_explosion_kill_msg": "{attacker} Hizo explotar a [{victim}]",
+        
         "hud.chat.loot_msg": "Recogiste [{item}]",
         "hud.chat.loot_fail": "Tu inventario está lleno!",
         "hud.chat.goodbye": "Adiós!",
@@ -197,7 +226,7 @@ Deshazte de ellos haciendo click en ellos y luego arrastralos fuera de la bolsa.
 
 Las noches pueden volverse bastante oscuras en Veloren.
 
-Enciende tu farol escribiendo /lantern en el chat o presionando la G.
+Enciende tu Linterna escribiendo /lantern en el chat o presionando la G.
 
 
 Quieres liberar tu cursor para cerrar esta ventana? Presiona TAB!
@@ -232,6 +261,7 @@ objetos infundidos con magia?"#,
         "hud.bag.chest": "Torso",
         "hud.bag.hands": "Manos",
         "hud.bag.lantern": "Linterna",
+        "hud.bag.glider": "Planeador",
         "hud.bag.belt": "Cinturón",
         "hud.bag.ring": "Anillo",
         "hud.bag.back": "Espalda",
@@ -282,8 +312,8 @@ objetos infundidos con magia?"#,
         "hud.settings.invert_scroll_zoom": "Invertir Desplazamiento de Zoom",
         "hud.settings.invert_mouse_y_axis": "Invertir eje Y del Ratón",
         "hud.settings.enable_mouse_smoothing": "Suavizado de la Cámara",
-        "hud.settings.free_look_behavior": "Comportamiento de vista libre",
-        "hud.settings.auto_walk_behavior": "Comportamiento al caminar automaticamente",
+        "hud.settings.free_look_behavior": "Modo de vista libre",
+        "hud.settings.auto_walk_behavior": "Modo de caminata automática",
         "hud.settings.stop_auto_walk_on_input": "Frenar caminata automática",
 
         "hud.settings.view_distance": "Distancia de Visión",
@@ -292,22 +322,43 @@ objetos infundidos con magia?"#,
         "hud.settings.maximum_fps": "FPS Máximos",
         "hud.settings.fov": "Campo de Visión (grados)",
         "hud.settings.gamma": "Gama",
+        "hud.settings.ambiance": "Brillo del Ambiente",
         "hud.settings.antialiasing_mode": "Modo Anti-Aliasing",
         "hud.settings.cloud_rendering_mode": "Modo de Renderizado de Nubes",
-        "hud.settings.fluid_rendering_mode": "Modo de Renderizado de Fluidos",
-        "hud.settings.fluid_rendering_mode.cheap": "Barato",
-        "hud.settings.fluid_rendering_mode.shiny": "Brillante",
-        "hud.settings.cloud_rendering_mode.regular": "Regular",
+        "hud.settings.fluid_rendering_mode": "Modo de Renderizado del Agua",
+        "hud.settings.fluid_rendering_mode.cheap": "Bajo",
+        "hud.settings.fluid_rendering_mode.shiny": "Alto",
+        "hud.settings.cloud_rendering_mode.regular": "Normal",
         "hud.settings.fullscreen": "Pantalla Completa",
-        "hud.settings.save_window_size": "Guardar tamaño de la ventana",
-
+        "hud.settings.fullscreen_mode": "Modo de Pantalla Completa",
+        "hud.settings.fullscreen_mode.exclusive": "Completo",
+        "hud.settings.fullscreen_mode.borderless": "Con Bordes",
+        "hud.settings.particles": "Particulas",
+        "hud.settings.resolution": "Resolución",
+        "hud.settings.bit_depth": "Profundidad de Bits",
+        "hud.settings.refresh_rate": "Taza de Refresco",
+        "hud.settings.save_window_size": "  Guardar tamaño de ventana",
+        "hud.settings.shadow_rendering_mode": "Renderizado de Sombras",
+        "hud.settings.shadow_rendering_mode.none": "Ninguno",
+        "hud.settings.shadow_rendering_mode.cheap": "Bajo",
+        "hud.settings.shadow_rendering_mode.map": "Alto",
+        "hud.settings.lighting_rendering_mode": "Renderizado de la luz de la Linterna",
+        "hud.settings.lighting_rendering_mode.ashikhmin": "Tipo A",
+        "hud.settings.lighting_rendering_mode.blinnphong": "Tipo B",
+        "hud.settings.lighting_rendering_mode.lambertian": "Tipo L",
+        "hud.settings.shadow_rendering_mode": "Renderizado de Sombras",
+        "hud.settings.shadow_rendering_mode.none": "Ninguno",
+        "hud.settings.shadow_rendering_mode.cheap": "Bajo",
+        "hud.settings.shadow_rendering_mode.map": "Alto",
+        "hud.settings.shadow_rendering_mode.map.resolution": "Resolución",
+        "hud.settings.lod_detail": "Detalle de LoD",
         "hud.settings.music_volume": "Volumen de Musica",
         "hud.settings.sound_effect_volume": "Volumen de Efectos de Sonido",
         "hud.settings.audio_device": "Dispositivo de Audio",
 
         "hud.settings.awaitingkey": "Presiona una tecla...",
         "hud.settings.unbound": "Ninguno",
-        "hud.settings.reset_keybinds": "Reestablecer a los valores predeterminados",
+        "hud.settings.reset_keybinds": "Reestablecer Controles",
 
         "hud.social": "Lista de jugadores",
         "hud.social.online": "En Línea",
@@ -315,12 +366,29 @@ objetos infundidos con magia?"#,
         "hud.social.not_yet_available": "Aún no esta disponible",
         "hud.social.faction": "Facción",
         "hud.social.play_online_fmt": "{nb_player} jugador(es) en línea",
+        "hud.social.name": "Nombre",
+        "hud.social.level": "Nivel",
+        "hud.social.zone": "Zona",
+        "hud.social.account": "Cuenta",
 
         "hud.crafting": "Crafteo",
         "hud.crafting.recipes": "Recetas",
         "hud.crafting.ingredients": "Ingredientes:",
         "hud.crafting.craft": "Fabricar",
         "hud.crafting.tool_cata": "Requisitos:",
+        
+        "hud.group": "Grupo",
+        "hud.group.invite_to_join": "{name} Te invito a su Grupo!",
+        "hud.group.invite": "Invitar",
+        "hud.group.kick": "Echar",
+        "hud.group.assign_leader": "Asignar Lider",
+        "hud.group.leave": "Salir del Grupo",
+        "hud.group.dead" : "Muerto",
+        "hud.group.out_of_range": "Fuera de Alcance",
+        "hud.group.add_friend": "Agregar a Amigos",
+        "hud.group.link_group": "Conectar Grupos",
+        "hud.group.in_menu": "Eligiendo Personaje",
+        "hud.group.members": "Miembros del Grupo",
 
         "hud.spell": "Hechizos",        
 
@@ -381,6 +449,9 @@ objetos infundidos con magia?"#,
         "gameinput.freelook": "Vista Libre",
         "gameinput.autowalk": "Caminata Automática",
         "gameinput.dance": "Bailar",
+        "gameinput.select": "Seleccione la Entidad",
+        "gameinput.acceptgroupinvite": "Aceptar invitación al grupo",
+        "gameinput.declinegroupinvite": "Rechazar invitación al grupo",
         "gameinput.crafting": "Craftear",
         "gameinput.sneak": "Agacharse",
         "gameinput.swimdown": "Sumergirse",
@@ -423,7 +494,7 @@ objetos infundidos con magia?"#,
 
 Estado Físico
 
-Fuerza de Voluntad
+Valentía
 
 Protección
 "#,
diff --git a/assets/voxygen/item_image_manifest.ron b/assets/voxygen/item_image_manifest.ron
index fb4b51f230..06677412cc 100644
--- a/assets/voxygen/item_image_manifest.ron
+++ b/assets/voxygen/item_image_manifest.ron
@@ -1099,6 +1099,14 @@
         "voxel.armor.back.short-2",
         (0.0, -2.0, 0.0), (-90.0, 180.0, 0.0), 1.0,
     ),
+    Armor(Back("Backpack0")): VoxTrans(
+        "voxel.armor.back.backpack-0",
+        (0.0, 0.0, 0.0), (-90.0, 0.0, 0.0), 1.0,
+    ),
+    Armor(Back("BackpackBlue0")): VoxTrans(
+        "voxel.armor.back.backpack-0",
+        (0.0, 0.0, 0.0), (-90.0, 0.0, 0.0), 1.0,
+    ),
     // Rings
     Armor(Ring("Ring0")): Png(
         "element.icons.ring-0",
diff --git a/assets/voxygen/voxel/armor/back/backpack-0.vox b/assets/voxygen/voxel/armor/back/backpack-0.vox
new file mode 100644
index 0000000000..32e778562d
Binary files /dev/null and b/assets/voxygen/voxel/armor/back/backpack-0.vox differ
diff --git a/assets/voxygen/voxel/armor/back/backpack-grey.vox b/assets/voxygen/voxel/armor/back/backpack-grey.vox
new file mode 100644
index 0000000000..60e4568aba
Binary files /dev/null and b/assets/voxygen/voxel/armor/back/backpack-grey.vox differ
diff --git a/assets/voxygen/voxel/humanoid_armor_back_manifest.ron b/assets/voxygen/voxel/humanoid_armor_back_manifest.ron
index 8ab7638b62..baea9952be 100644
--- a/assets/voxygen/voxel/humanoid_armor_back_manifest.ron
+++ b/assets/voxygen/voxel/humanoid_armor_back_manifest.ron
@@ -23,6 +23,14 @@
       "Short2": (
           vox_spec: ("armor.back.short-2", (-5.0, -1.0, -11.0)),
           color: None
+      ),
+      "Backpack0": (
+          vox_spec: ("armor.back.backpack-0", (-7.0, -5.0, -10.0)),
+          color: None
+      ),   
+      "BackpackBlue0": (
+          vox_spec: ("armor.back.backpack-grey", (-7.0, -5.0, -10.0)),
+          color: Some((76, 72, 178))
       ),   
     },
 ))
diff --git a/client/src/lib.rs b/client/src/lib.rs
index 9824086919..85c77c3e6b 100644
--- a/client/src/lib.rs
+++ b/client/src/lib.rs
@@ -37,6 +37,7 @@ use common::{
     terrain::{block::Block, neighbors, TerrainChunk, TerrainChunkSize},
     vol::RectVolSize,
 };
+use comp::BuffKind;
 use futures_executor::block_on;
 use futures_timer::Delay;
 use futures_util::{select, FutureExt};
@@ -644,6 +645,12 @@ impl Client {
         self.send_msg(ClientGeneral::ControlEvent(ControlEvent::DisableLantern));
     }
 
+    pub fn remove_buff(&mut self, buff_id: BuffKind) {
+        self.send_msg(ClientGeneral::ControlEvent(ControlEvent::RemoveBuff(
+            buff_id,
+        )));
+    }
+
     pub fn max_group_size(&self) -> u32 { self.max_group_size }
 
     pub fn group_invite(&self) -> Option<(Uid, std::time::Instant, std::time::Duration)> {
@@ -977,6 +984,11 @@ impl Client {
 
         // 4) Tick the client's LocalState
         self.state.tick(dt, add_foreign_systems, true);
+        // TODO: avoid emitting these in the first place
+        self.state
+            .ecs()
+            .fetch::<EventBus<common::event::ServerEvent>>()
+            .recv_all();
 
         // 5) Terrain
         let pos = self
@@ -1728,6 +1740,11 @@ impl Client {
                             alias_of_uid(attacker_uid),
                             alias_of_uid(victim)
                         ),
+                        KillSource::Player(attacker_uid, KillType::Buff) => format!(
+                            "[{}] killed [{}]",
+                            alias_of_uid(attacker_uid),
+                            alias_of_uid(victim)
+                        ),
                         KillSource::NonPlayer(attacker_name, KillType::Melee) => {
                             format!("{} killed [{}]", attacker_name, alias_of_uid(victim))
                         },
@@ -1742,6 +1759,9 @@ impl Client {
                             attacker_name,
                             alias_of_uid(victim)
                         ),
+                        KillSource::NonPlayer(attacker_name, KillType::Buff) => {
+                            format!("{} killed [{}]", attacker_name, alias_of_uid(victim))
+                        },
                         KillSource::Environment(environment) => {
                             format!("[{}] died in {}", alias_of_uid(victim), environment)
                         },
@@ -1767,6 +1787,9 @@ impl Client {
                         KillSource::Player(attacker_uid, KillType::Energy) => message
                             .replace("{attacker}", &alias_of_uid(attacker_uid))
                             .replace("{victim}", &alias_of_uid(victim)),
+                        KillSource::Player(attacker_uid, KillType::Buff) => message
+                            .replace("{attacker}", &alias_of_uid(attacker_uid))
+                            .replace("{victim}", &alias_of_uid(victim)),
                         KillSource::NonPlayer(attacker_name, KillType::Melee) => message
                             .replace("{attacker}", attacker_name)
                             .replace("{victim}", &alias_of_uid(victim)),
@@ -1779,6 +1802,9 @@ impl Client {
                         KillSource::NonPlayer(attacker_name, KillType::Energy) => message
                             .replace("{attacker}", attacker_name)
                             .replace("{victim}", &alias_of_uid(victim)),
+                        KillSource::NonPlayer(attacker_name, KillType::Buff) => message
+                            .replace("{attacker}", attacker_name)
+                            .replace("{victim}", &alias_of_uid(victim)),
                         KillSource::Environment(environment) => message
                             .replace("{name}", &alias_of_uid(victim))
                             .replace("{environment}", environment),
diff --git a/common/src/comp/buff.rs b/common/src/comp/buff.rs
new file mode 100644
index 0000000000..08a489baf3
--- /dev/null
+++ b/common/src/comp/buff.rs
@@ -0,0 +1,286 @@
+use crate::sync::Uid;
+use serde::{Deserialize, Serialize};
+use specs::{Component, FlaggedStorage};
+use specs_idvs::IdvStorage;
+use std::{cmp::Ordering, collections::HashMap, time::Duration};
+
+/// De/buff Kind.
+/// This is used to determine what effects a buff will have
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
+pub enum BuffKind {
+    /// Restores health/time for some period
+    Regeneration,
+    /// Lowers health over time for some duration
+    Bleeding,
+    /// Lower a creature's max health
+    /// Currently placeholder buff to show other stuff is possible
+    Cursed,
+}
+
+impl BuffKind {
+    // Checks if buff is buff or debuff
+    pub fn is_buff(self) -> bool {
+        match self {
+            BuffKind::Regeneration { .. } => true,
+            BuffKind::Bleeding { .. } => false,
+            BuffKind::Cursed { .. } => false,
+        }
+    }
+}
+
+// Struct used to store data relevant to a buff
+#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
+pub struct BuffData {
+    pub strength: f32,
+    pub duration: Option<Duration>,
+}
+
+/// De/buff category ID.
+/// Similar to `BuffKind`, but to mark a category (for more generic usage, like
+/// positive/negative buffs).
+#[derive(Clone, Copy, Eq, PartialEq, Debug, Serialize, Deserialize)]
+pub enum BuffCategory {
+    Natural,
+    Physical,
+    Magical,
+    Divine,
+    PersistOnDeath,
+}
+
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum ModifierKind {
+    Additive,
+    Multiplicative,
+}
+
+/// Data indicating and configuring behaviour of a de/buff.
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub enum BuffEffect {
+    /// Periodically damages or heals entity
+    HealthChangeOverTime { rate: f32, accumulated: f32 },
+    /// Changes maximum health by a certain amount
+    MaxHealthModifier { value: f32, kind: ModifierKind },
+}
+
+/// Actual de/buff.
+/// Buff can timeout after some time if `time` is Some. If `time` is None,
+/// Buff will last indefinitely, until removed manually (by some action, like
+/// uncursing).
+///
+/// Buff has a kind, which is used to determine the effects in a builder
+/// function.
+///
+/// To provide more classification info when needed,
+/// buff can be in one or more buff category.
+#[derive(Clone, Debug, Serialize, Deserialize)]
+pub struct Buff {
+    pub kind: BuffKind,
+    pub data: BuffData,
+    pub cat_ids: Vec<BuffCategory>,
+    pub time: Option<Duration>,
+    pub effects: Vec<BuffEffect>,
+    pub source: BuffSource,
+}
+
+/// Information about whether buff addition or removal was requested.
+/// This to implement "on_add" and "on_remove" hooks for constant buffs.
+#[derive(Clone, Debug)]
+pub enum BuffChange {
+    /// Adds this buff.
+    Add(Buff),
+    /// Removes all buffs with this ID.
+    RemoveByKind(BuffKind),
+    /// Removes all buffs with this ID, but not debuffs.
+    RemoveFromController(BuffKind),
+    /// Removes buffs of these indices (first vec is for active buffs, second is
+    /// for inactive buffs), should only be called when buffs expire
+    RemoveById(Vec<BuffId>),
+    /// Removes buffs of these categories (first vec is of categories of which
+    /// all are required, second vec is of categories of which at least one is
+    /// required, third vec is of categories that will not be removed)  
+    RemoveByCategory {
+        all_required: Vec<BuffCategory>,
+        any_required: Vec<BuffCategory>,
+        none_required: Vec<BuffCategory>,
+    },
+}
+
+impl Buff {
+    /// Builder function for buffs
+    pub fn new(
+        kind: BuffKind,
+        data: BuffData,
+        cat_ids: Vec<BuffCategory>,
+        source: BuffSource,
+    ) -> Self {
+        let (effects, time) = match kind {
+            BuffKind::Bleeding => (
+                vec![BuffEffect::HealthChangeOverTime {
+                    rate: -data.strength,
+                    accumulated: 0.0,
+                }],
+                data.duration,
+            ),
+            BuffKind::Regeneration => (
+                vec![BuffEffect::HealthChangeOverTime {
+                    rate: data.strength,
+                    accumulated: 0.0,
+                }],
+                data.duration,
+            ),
+            BuffKind::Cursed => (
+                vec![BuffEffect::MaxHealthModifier {
+                    value: -100. * data.strength,
+                    kind: ModifierKind::Additive,
+                }],
+                data.duration,
+            ),
+        };
+        Buff {
+            kind,
+            data,
+            cat_ids,
+            time,
+            effects,
+            source,
+        }
+    }
+}
+
+impl PartialOrd for Buff {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        if self == other {
+            Some(Ordering::Equal)
+        } else if self.data.strength > other.data.strength {
+            Some(Ordering::Greater)
+        } else if self.data.strength < other.data.strength {
+            Some(Ordering::Less)
+        } else if compare_duration(self.time, other.time) {
+            Some(Ordering::Greater)
+        } else if compare_duration(other.time, self.time) {
+            Some(Ordering::Less)
+        } else {
+            None
+        }
+    }
+}
+
+fn compare_duration(a: Option<Duration>, b: Option<Duration>) -> bool {
+    a.map_or(true, |dur_a| b.map_or(false, |dur_b| dur_a > dur_b))
+}
+
+impl PartialEq for Buff {
+    fn eq(&self, other: &Self) -> bool {
+        self.data.strength == other.data.strength && self.time == other.time
+    }
+}
+
+/// Source of the de/buff
+#[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)]
+pub enum BuffSource {
+    /// Applied by a character
+    Character { by: Uid },
+    /// Applied by world, like a poisonous fumes from a swamp
+    World,
+    /// Applied by command
+    Command,
+    /// Applied by an item
+    Item,
+    /// Applied by another buff (like an after-effect)
+    Buff,
+    /// Some other source
+    Unknown,
+}
+
+/// Component holding all de/buffs that gets resolved each tick.
+/// On each tick, remaining time of buffs get lowered and
+/// buff effect of each buff is applied or not, depending on the `BuffEffect`
+/// (specs system will decide based on `BuffEffect`, to simplify
+/// implementation). TODO: Something like `once` flag for `Buff` to remove the
+/// dependence on `BuffEffect` enum?
+///
+/// In case of one-time buffs, buff effects will be applied on addition
+/// and undone on removal of the buff (by the specs system).
+/// Example could be decreasing max health, which, if repeated each tick,
+/// would be probably an undesired effect).
+#[derive(Clone, Debug, Serialize, Deserialize, Default)]
+pub struct Buffs {
+    /// Uid used for synchronization
+    id_counter: u64,
+    /// Maps Kinds of buff to Id's of currently applied buffs of that kind
+    pub kinds: HashMap<BuffKind, Vec<BuffId>>,
+    // All currently applied buffs stored by Id
+    pub buffs: HashMap<BuffId, Buff>,
+}
+
+impl Buffs {
+    fn sort_kind(&mut self, kind: BuffKind) {
+        if let Some(buff_order) = self.kinds.get_mut(&kind) {
+            if buff_order.is_empty() {
+                self.kinds.remove(&kind);
+            } else {
+                let buffs = &self.buffs;
+                // Intentionally sorted in reverse so that the strongest buffs are earlier in
+                // the vector
+                buff_order.sort_by(|a, b| buffs[&b].partial_cmp(&buffs[&a]).unwrap());
+            }
+        }
+    }
+
+    pub fn remove_kind(&mut self, kind: BuffKind) {
+        if let Some(buff_ids) = self.kinds.get_mut(&kind) {
+            for id in buff_ids {
+                self.buffs.remove(id);
+            }
+            self.kinds.remove(&kind);
+        }
+    }
+
+    pub fn force_insert(&mut self, id: BuffId, buff: Buff) -> BuffId {
+        let kind = buff.kind;
+        self.kinds.entry(kind).or_default().push(id);
+        self.buffs.insert(id, buff);
+        self.sort_kind(kind);
+        id
+    }
+
+    pub fn insert(&mut self, buff: Buff) -> BuffId {
+        self.id_counter += 1;
+        self.force_insert(self.id_counter, buff)
+    }
+
+    // Iterate through buffs of a given kind in effect order (most powerful first)
+    pub fn iter_kind(&self, kind: BuffKind) -> impl Iterator<Item = (BuffId, &Buff)> + '_ {
+        self.kinds
+            .get(&kind)
+            .map(|ids| ids.iter())
+            .unwrap_or_else(|| (&[]).iter())
+            .map(move |id| (*id, &self.buffs[id]))
+    }
+
+    // Iterates through all active buffs (the most powerful buff of each kind)
+    pub fn iter_active(&self) -> impl Iterator<Item = &Buff> + '_ {
+        self.kinds
+            .values()
+            .map(move |ids| self.buffs.get(&ids[0]))
+            .filter(|buff| buff.is_some())
+            .map(|buff| buff.unwrap())
+    }
+
+    // Gets most powerful buff of a given kind
+    // pub fn get_active_kind(&self, kind: BuffKind) -> Buff
+
+    pub fn remove(&mut self, buff_id: BuffId) {
+        let kind = self.buffs.remove(&buff_id).unwrap().kind;
+        self.kinds
+            .get_mut(&kind)
+            .map(|ids| ids.retain(|id| *id != buff_id));
+        self.sort_kind(kind);
+    }
+}
+
+pub type BuffId = u64;
+
+impl Component for Buffs {
+    type Storage = FlaggedStorage<Self, IdvStorage<Self>>;
+}
diff --git a/common/src/comp/chat.rs b/common/src/comp/chat.rs
index 4774b18683..0b748db9d4 100644
--- a/common/src/comp/chat.rs
+++ b/common/src/comp/chat.rs
@@ -51,6 +51,7 @@ pub enum KillType {
     Projectile,
     Explosion,
     Energy,
+    Buff,
     // Projectile(String), TODO: add projectile name when available
 }
 
diff --git a/common/src/comp/controller.rs b/common/src/comp/controller.rs
index b9c7e1cb4c..5c7f3558c8 100644
--- a/common/src/comp/controller.rs
+++ b/common/src/comp/controller.rs
@@ -1,4 +1,8 @@
-use crate::{comp::inventory::slot::Slot, sync::Uid, util::Dir};
+use crate::{
+    comp::{inventory::slot::Slot, BuffKind},
+    sync::Uid,
+    util::Dir,
+};
 use serde::{Deserialize, Serialize};
 use specs::{Component, FlaggedStorage};
 use specs_idvs::IdvStorage;
@@ -37,6 +41,7 @@ pub enum ControlEvent {
     Unmount,
     InventoryManip(InventoryManip),
     GroupManip(GroupManip),
+    RemoveBuff(BuffKind),
     Respawn,
 }
 
diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs
index c8204c6eed..329546a54e 100644
--- a/common/src/comp/mod.rs
+++ b/common/src/comp/mod.rs
@@ -3,6 +3,7 @@ mod admin;
 pub mod agent;
 pub mod beam;
 pub mod body;
+pub mod buff;
 mod character_state;
 pub mod chat;
 mod controller;
@@ -31,6 +32,10 @@ pub use body::{
     biped_large, bird_medium, bird_small, dragon, fish_medium, fish_small, golem, humanoid, object,
     quadruped_low, quadruped_medium, quadruped_small, theropod, AllBodies, Body, BodyData,
 };
+pub use buff::{
+    Buff, BuffCategory, BuffChange, BuffData, BuffEffect, BuffId, BuffKind, BuffSource, Buffs,
+    ModifierKind,
+};
 pub use character_state::{Attacking, CharacterState, StateUpdate};
 pub use chat::{
     ChatMode, ChatMsg, ChatType, Faction, SpeechBubble, SpeechBubbleType, UnresolvedChatMsg,
diff --git a/common/src/comp/stats.rs b/common/src/comp/stats.rs
index e1e129b6b3..7289bfbdf7 100644
--- a/common/src/comp/stats.rs
+++ b/common/src/comp/stats.rs
@@ -8,6 +8,7 @@ use specs::{Component, FlaggedStorage};
 use specs_idvs::IdvStorage;
 use std::{error::Error, fmt};
 
+/// Specifies what and how much changed current health
 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize)]
 pub struct HealthChange {
     pub amount: i32,
@@ -20,6 +21,7 @@ pub enum HealthSource {
     Projectile { owner: Option<Uid> },
     Explosion { owner: Option<Uid> },
     Energy { owner: Option<Uid> },
+    Buff { owner: Option<Uid> },
     Suicide,
     World,
     Revive,
@@ -32,6 +34,7 @@ pub enum HealthSource {
 
 #[derive(Clone, Copy, Debug, Serialize, Deserialize)]
 pub struct Health {
+    base_max: u32,
     current: u32,
     maximum: u32,
     pub last_change: (f64, HealthChange),
@@ -67,11 +70,21 @@ impl Health {
         self.last_change = (0.0, change);
     }
 
-    // This is private because max hp is based on the level
-    fn set_maximum(&mut self, amount: u32) {
+    // This function changes the modified max health value, not the base health
+    // value. The modified health value takes into account buffs and other temporary
+    // changes to max health.
+    pub fn set_maximum(&mut self, amount: u32) {
         self.maximum = amount;
         self.current = self.current.min(self.maximum);
     }
+
+    // This is private because max hp is based on the level
+    fn set_base_max(&mut self, amount: u32) {
+        self.base_max = amount;
+        self.current = self.current.min(self.maximum);
+    }
+
+    pub fn reset_max(&mut self) { self.maximum = self.base_max; }
 }
 #[derive(Debug)]
 pub enum StatChangeError {
@@ -148,6 +161,8 @@ impl Stats {
 
     // TODO: Delete this once stat points will be a thing
     pub fn update_max_hp(&mut self, body: Body) {
+        self.health
+            .set_base_max(body.base_health() + body.base_health_increase() * self.level.amount);
         self.health
             .set_maximum(body.base_health() + body.base_health_increase() * self.level.amount);
     }
@@ -179,6 +194,7 @@ impl Stats {
             health: Health {
                 current: 0,
                 maximum: 0,
+                base_max: 0,
                 last_change: (0.0, HealthChange {
                     amount: 0,
                     cause: HealthSource::Revive,
@@ -198,6 +214,7 @@ impl Stats {
         };
 
         stats.update_max_hp(body);
+
         stats
             .health
             .set_to(stats.health.maximum(), HealthSource::Revive);
@@ -213,6 +230,7 @@ impl Stats {
             health: Health {
                 current: 0,
                 maximum: 0,
+                base_max: 0,
                 last_change: (0.0, HealthChange {
                     amount: 0,
                     cause: HealthSource::Revive,
diff --git a/common/src/event.rs b/common/src/event.rs
index 542650d8a4..a51620c961 100644
--- a/common/src/event.rs
+++ b/common/src/event.rs
@@ -106,6 +106,10 @@ pub enum ServerEvent {
     ChatCmd(EcsEntity, String),
     /// Send a chat message to the player from an npc or other player
     Chat(comp::UnresolvedChatMsg),
+    Buff {
+        entity: EcsEntity,
+        buff_change: comp::BuffChange,
+    },
 }
 
 pub struct EventBus<E> {
diff --git a/common/src/msg/ecs_packet.rs b/common/src/msg/ecs_packet.rs
index ce9852720f..41ab1bda71 100644
--- a/common/src/msg/ecs_packet.rs
+++ b/common/src/msg/ecs_packet.rs
@@ -13,6 +13,7 @@ sum_type! {
         Player(comp::Player),
         CanBuild(comp::CanBuild),
         Stats(comp::Stats),
+        Buffs(comp::Buffs),
         Energy(comp::Energy),
         LightEmitter(comp::LightEmitter),
         Item(comp::Item),
@@ -42,6 +43,7 @@ sum_type! {
         Player(PhantomData<comp::Player>),
         CanBuild(PhantomData<comp::CanBuild>),
         Stats(PhantomData<comp::Stats>),
+        Buffs(PhantomData<comp::Buffs>),
         Energy(PhantomData<comp::Energy>),
         LightEmitter(PhantomData<comp::LightEmitter>),
         Item(PhantomData<comp::Item>),
@@ -71,6 +73,7 @@ impl sync::CompPacket for EcsCompPacket {
             EcsCompPacket::Player(comp) => sync::handle_insert(comp, entity, world),
             EcsCompPacket::CanBuild(comp) => sync::handle_insert(comp, entity, world),
             EcsCompPacket::Stats(comp) => sync::handle_insert(comp, entity, world),
+            EcsCompPacket::Buffs(comp) => sync::handle_insert(comp, entity, world),
             EcsCompPacket::Energy(comp) => sync::handle_insert(comp, entity, world),
             EcsCompPacket::LightEmitter(comp) => sync::handle_insert(comp, entity, world),
             EcsCompPacket::Item(comp) => sync::handle_insert(comp, entity, world),
@@ -98,6 +101,7 @@ impl sync::CompPacket for EcsCompPacket {
             EcsCompPacket::Player(comp) => sync::handle_modify(comp, entity, world),
             EcsCompPacket::CanBuild(comp) => sync::handle_modify(comp, entity, world),
             EcsCompPacket::Stats(comp) => sync::handle_modify(comp, entity, world),
+            EcsCompPacket::Buffs(comp) => sync::handle_modify(comp, entity, world),
             EcsCompPacket::Energy(comp) => sync::handle_modify(comp, entity, world),
             EcsCompPacket::LightEmitter(comp) => sync::handle_modify(comp, entity, world),
             EcsCompPacket::Item(comp) => sync::handle_modify(comp, entity, world),
@@ -125,6 +129,7 @@ impl sync::CompPacket for EcsCompPacket {
             EcsCompPhantom::Player(_) => sync::handle_remove::<comp::Player>(entity, world),
             EcsCompPhantom::CanBuild(_) => sync::handle_remove::<comp::CanBuild>(entity, world),
             EcsCompPhantom::Stats(_) => sync::handle_remove::<comp::Stats>(entity, world),
+            EcsCompPhantom::Buffs(_) => sync::handle_remove::<comp::Buffs>(entity, world),
             EcsCompPhantom::Energy(_) => sync::handle_remove::<comp::Energy>(entity, world),
             EcsCompPhantom::LightEmitter(_) => {
                 sync::handle_remove::<comp::LightEmitter>(entity, world)
diff --git a/common/src/state.rs b/common/src/state.rs
index d54a5d9433..cbf00daaf2 100644
--- a/common/src/state.rs
+++ b/common/src/state.rs
@@ -112,6 +112,7 @@ impl State {
         ecs.register::<comp::Body>();
         ecs.register::<comp::Player>();
         ecs.register::<comp::Stats>();
+        ecs.register::<comp::Buffs>();
         ecs.register::<comp::Energy>();
         ecs.register::<comp::CanBuild>();
         ecs.register::<comp::LightEmitter>();
diff --git a/common/src/sys/agent.rs b/common/src/sys/agent.rs
index a86e6ec529..06d39cb1c8 100644
--- a/common/src/sys/agent.rs
+++ b/common/src/sys/agent.rs
@@ -601,6 +601,7 @@ impl<'a> System<'a> for Sys {
                     if let comp::HealthSource::Attack { by }
                     | comp::HealthSource::Projectile { owner: Some(by) }
                     | comp::HealthSource::Energy { owner: Some(by) }
+                    | comp::HealthSource::Buff { owner: Some(by) }
                     | comp::HealthSource::Explosion { owner: Some(by) } =
                         my_stats.health.last_change.1.cause
                     {
diff --git a/common/src/sys/buff.rs b/common/src/sys/buff.rs
new file mode 100644
index 0000000000..3cff89f8fc
--- /dev/null
+++ b/common/src/sys/buff.rs
@@ -0,0 +1,146 @@
+use crate::{
+    comp::{
+        BuffCategory, BuffChange, BuffEffect, BuffId, BuffSource, Buffs, HealthChange,
+        HealthSource, Loadout, ModifierKind, Stats,
+    },
+    event::{EventBus, ServerEvent},
+    state::DeltaTime,
+    sync::Uid,
+};
+use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
+use std::time::Duration;
+
+pub struct Sys;
+impl<'a> System<'a> for Sys {
+    #[allow(clippy::type_complexity)]
+    type SystemData = (
+        Entities<'a>,
+        Read<'a, DeltaTime>,
+        Read<'a, EventBus<ServerEvent>>,
+        ReadStorage<'a, Uid>,
+        ReadStorage<'a, Loadout>,
+        WriteStorage<'a, Stats>,
+        WriteStorage<'a, Buffs>,
+    );
+
+    fn run(
+        &mut self,
+        (entities, dt, server_bus, uids, loadouts, mut stats, mut buffs): Self::SystemData,
+    ) {
+        let mut server_emitter = server_bus.emitter();
+        // Set to false to avoid spamming server
+        buffs.set_event_emission(false);
+        stats.set_event_emission(false);
+        for (entity, buff_comp, uid, stat) in (&entities, &mut buffs, &uids, &mut stats).join() {
+            let mut expired_buffs = Vec::<BuffId>::new();
+            for (id, buff) in buff_comp.buffs.iter_mut() {
+                // Tick the buff and subtract delta from it
+                if let Some(remaining_time) = &mut buff.time {
+                    if let Some(new_duration) =
+                        remaining_time.checked_sub(Duration::from_secs_f32(dt.0))
+                    {
+                        // The buff still continues.
+                        *remaining_time = new_duration;
+                    } else {
+                        // checked_sub returns None when remaining time
+                        // went below 0, so set to 0
+                        *remaining_time = Duration::default();
+                        // The buff has expired.
+                        // Remove it.
+                        expired_buffs.push(*id);
+                    }
+                }
+            }
+
+            if let Some(loadout) = loadouts.get(entity) {
+                let damage_reduction = loadout.get_damage_reduction();
+                if (damage_reduction - 1.0).abs() < f32::EPSILON {
+                    for (id, buff) in buff_comp.buffs.iter() {
+                        if !buff.kind.is_buff() {
+                            expired_buffs.push(*id);
+                        }
+                    }
+                }
+            }
+
+            // Call to reset stats to base values
+            stat.health.reset_max();
+
+            // Iterator over the lists of buffs by kind
+            for buff_ids in buff_comp.kinds.values() {
+                // Get the strongest of this buff kind
+                if let Some(buff) = buff_comp.buffs.get_mut(&buff_ids[0]) {
+                    // Get buff owner?
+                    let buff_owner = if let BuffSource::Character { by: owner } = buff.source {
+                        Some(owner)
+                    } else {
+                        None
+                    };
+
+                    // Now, execute the buff, based on it's delta
+                    for effect in &mut buff.effects {
+                        match effect {
+                            BuffEffect::HealthChangeOverTime { rate, accumulated } => {
+                                *accumulated += *rate * dt.0;
+                                // Apply damage only once a second (with a minimum of 1 damage), or
+                                // when a buff is removed
+                                if accumulated.abs() > rate.abs().max(10.0)
+                                    || buff.time.map_or(false, |dur| dur == Duration::default())
+                                {
+                                    let cause = if *accumulated > 0.0 {
+                                        HealthSource::Healing { by: buff_owner }
+                                    } else {
+                                        HealthSource::Buff { owner: buff_owner }
+                                    };
+                                    server_emitter.emit(ServerEvent::Damage {
+                                        uid: *uid,
+                                        change: HealthChange {
+                                            amount: *accumulated as i32,
+                                            cause,
+                                        },
+                                    });
+                                    *accumulated = 0.0;
+                                };
+                            },
+                            BuffEffect::MaxHealthModifier { value, kind } => match kind {
+                                ModifierKind::Multiplicative => {
+                                    stat.health.set_maximum(
+                                        (stat.health.maximum() as f32 * *value) as u32,
+                                    );
+                                },
+                                ModifierKind::Additive => {
+                                    stat.health.set_maximum(
+                                        (stat.health.maximum() as f32 + *value) as u32,
+                                    );
+                                },
+                            },
+                        };
+                    }
+                }
+            }
+
+            // Remove buffs that expire
+            if !expired_buffs.is_empty() {
+                server_emitter.emit(ServerEvent::Buff {
+                    entity,
+                    buff_change: BuffChange::RemoveById(expired_buffs),
+                });
+            }
+
+            // Remove stats that don't persist on death
+            if stat.is_dead {
+                server_emitter.emit(ServerEvent::Buff {
+                    entity,
+                    buff_change: BuffChange::RemoveByCategory {
+                        all_required: vec![],
+                        any_required: vec![],
+                        none_required: vec![BuffCategory::PersistOnDeath],
+                    },
+                });
+            }
+        }
+        // Turned back to true
+        buffs.set_event_emission(true);
+        stats.set_event_emission(true);
+    }
+}
diff --git a/common/src/sys/combat.rs b/common/src/sys/combat.rs
index a9327b96ef..cfa469a910 100644
--- a/common/src/sys/combat.rs
+++ b/common/src/sys/combat.rs
@@ -1,7 +1,7 @@
 use crate::{
     comp::{
-        group, Attacking, Body, CharacterState, Damage, DamageSource, HealthChange, HealthSource,
-        Loadout, Ori, Pos, Scale, Stats,
+        buff, group, Attacking, Body, CharacterState, Damage, DamageSource, HealthChange,
+        HealthSource, Loadout, Ori, Pos, Scale, Stats,
     },
     event::{EventBus, LocalEvent, ServerEvent},
     metrics::SysMetrics,
@@ -9,7 +9,9 @@ use crate::{
     sync::Uid,
     util::Dir,
 };
+use rand::{thread_rng, Rng};
 use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, WriteStorage};
+use std::time::Duration;
 use vek::*;
 
 pub const BLOCK_EFFICIENCY: f32 = 0.9;
@@ -150,6 +152,24 @@ impl<'a> System<'a> for Sys {
                                 cause,
                             },
                         });
+
+                        // Apply bleeding buff on melee hits with 10% chance
+                        // TODO: Don't have buff uniformly applied on all melee attacks
+                        if thread_rng().gen::<f32>() < 0.1 {
+                            use buff::*;
+                            server_emitter.emit(ServerEvent::Buff {
+                                entity: b,
+                                buff_change: BuffChange::Add(Buff::new(
+                                    BuffKind::Bleeding,
+                                    BuffData {
+                                        strength: attack.base_damage as f32 / 10.0,
+                                        duration: Some(Duration::from_secs(10)),
+                                    },
+                                    vec![BuffCategory::Physical],
+                                    BuffSource::Character { by: *uid },
+                                )),
+                            });
+                        }
                         attack.hit_count += 1;
                     }
                     if attack.knockback != 0.0 && damage.healthchange != 0.0 {
diff --git a/common/src/sys/controller.rs b/common/src/sys/controller.rs
index 380b176adf..3fe6b8bedb 100644
--- a/common/src/sys/controller.rs
+++ b/common/src/sys/controller.rs
@@ -1,7 +1,7 @@
 use crate::{
     comp::{
         slot::{EquipSlot, Slot},
-        CharacterState, ControlEvent, Controller, InventoryManip,
+        BuffChange, CharacterState, ControlEvent, Controller, InventoryManip,
     },
     event::{EventBus, LocalEvent, ServerEvent},
     metrics::SysMetrics,
@@ -83,6 +83,12 @@ impl<'a> System<'a> for Sys {
                             server_emitter.emit(ServerEvent::Mount(entity, mountee_entity));
                         }
                     },
+                    ControlEvent::RemoveBuff(buff_id) => {
+                        server_emitter.emit(ServerEvent::Buff {
+                            entity,
+                            buff_change: BuffChange::RemoveFromController(buff_id),
+                        });
+                    },
                     ControlEvent::Unmount => server_emitter.emit(ServerEvent::Unmount(entity)),
                     ControlEvent::EnableLantern => {
                         server_emitter.emit(ServerEvent::EnableLantern(entity))
diff --git a/common/src/sys/mod.rs b/common/src/sys/mod.rs
index 99b2e56047..98c70fd145 100644
--- a/common/src/sys/mod.rs
+++ b/common/src/sys/mod.rs
@@ -1,5 +1,6 @@
 pub mod agent;
 mod beam;
+mod buff;
 pub mod character_behavior;
 pub mod combat;
 pub mod controller;
@@ -23,6 +24,7 @@ pub const PHYS_SYS: &str = "phys_sys";
 pub const PROJECTILE_SYS: &str = "projectile_sys";
 pub const SHOCKWAVE_SYS: &str = "shockwave_sys";
 pub const STATS_SYS: &str = "stats_sys";
+pub const BUFFS_SYS: &str = "buffs_sys";
 
 pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
     dispatch_builder.add(agent::Sys, AGENT_SYS, &[]);
@@ -32,6 +34,7 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
         CONTROLLER_SYS,
     ]);
     dispatch_builder.add(stats::Sys, STATS_SYS, &[]);
+    dispatch_builder.add(buff::Sys, BUFFS_SYS, &[]);
     dispatch_builder.add(phys::Sys, PHYS_SYS, &[CONTROLLER_SYS, MOUNT_SYS, STATS_SYS]);
     dispatch_builder.add(projectile::Sys, PROJECTILE_SYS, &[PHYS_SYS]);
     dispatch_builder.add(shockwave::Sys, SHOCKWAVE_SYS, &[PHYS_SYS]);
diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs
index d4daa1b3bc..e32e7318b7 100644
--- a/server/src/events/entity_manipulation.rs
+++ b/server/src/events/entity_manipulation.rs
@@ -6,7 +6,7 @@ use crate::{
 use common::{
     assets::Asset,
     comp::{
-        self,
+        self, buff,
         chat::{KillSource, KillType},
         object, Alignment, Body, Damage, DamageSource, Group, HealthChange, HealthSource, Item,
         Player, Pos, Stats,
@@ -165,11 +165,34 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
                         KillSource::NonPlayer("<?>".to_string(), KillType::Energy)
                     }
                 },
+                HealthSource::Buff { owner: Some(by) } => {
+                    // Get energy owner entity
+                    if let Some(char_entity) = state.ecs().entity_from_uid(by.into()) {
+                        // Check if attacker is another player or entity with stats (npc)
+                        if state
+                            .ecs()
+                            .read_storage::<Player>()
+                            .get(char_entity)
+                            .is_some()
+                        {
+                            KillSource::Player(by, KillType::Buff)
+                        } else if let Some(stats) =
+                            state.ecs().read_storage::<Stats>().get(char_entity)
+                        {
+                            KillSource::NonPlayer(stats.name.clone(), KillType::Buff)
+                        } else {
+                            KillSource::NonPlayer("<?>".to_string(), KillType::Buff)
+                        }
+                    } else {
+                        KillSource::NonPlayer("<?>".to_string(), KillType::Buff)
+                    }
+                },
                 HealthSource::World => KillSource::FallDamage,
                 HealthSource::Suicide => KillSource::Suicide,
                 HealthSource::Projectile { owner: None }
                 | HealthSource::Explosion { owner: None }
                 | HealthSource::Energy { owner: None }
+                | HealthSource::Buff { owner: None }
                 | HealthSource::Revive
                 | HealthSource::Command
                 | HealthSource::LevelUp
@@ -189,6 +212,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
         let by = if let HealthSource::Attack { by }
         | HealthSource::Projectile { owner: Some(by) }
         | HealthSource::Energy { owner: Some(by) }
+        | HealthSource::Buff { owner: Some(by) }
         | HealthSource::Explosion { owner: Some(by) } = cause
         {
             by
@@ -674,3 +698,65 @@ pub fn handle_level_up(server: &mut Server, entity: EcsEntity, new_level: u32) {
             PlayerListUpdate::LevelChange(*uid, new_level),
         ));
 }
+
+pub fn handle_buff(server: &mut Server, entity: EcsEntity, buff_change: buff::BuffChange) {
+    let ecs = &server.state.ecs();
+    let mut buffs_all = ecs.write_storage::<comp::Buffs>();
+    if let Some(buffs) = buffs_all.get_mut(entity) {
+        use buff::BuffChange;
+        match buff_change {
+            BuffChange::Add(new_buff) => {
+                buffs.insert(new_buff);
+            },
+            BuffChange::RemoveById(ids) => {
+                for id in ids {
+                    buffs.remove(id);
+                }
+            },
+            BuffChange::RemoveByKind(kind) => {
+                buffs.remove_kind(kind);
+            },
+            BuffChange::RemoveFromController(kind) => {
+                if kind.is_buff() {
+                    buffs.remove_kind(kind);
+                }
+            },
+            BuffChange::RemoveByCategory {
+                all_required,
+                any_required,
+                none_required,
+            } => {
+                let mut ids_to_remove = Vec::new();
+                for (id, buff) in buffs.buffs.iter() {
+                    let mut required_met = true;
+                    for required in &all_required {
+                        if !buff.cat_ids.iter().any(|cat| cat == required) {
+                            required_met = false;
+                            break;
+                        }
+                    }
+                    let mut any_met = any_required.is_empty();
+                    for any in &any_required {
+                        if buff.cat_ids.iter().any(|cat| cat == any) {
+                            any_met = true;
+                            break;
+                        }
+                    }
+                    let mut none_met = true;
+                    for none in &none_required {
+                        if buff.cat_ids.iter().any(|cat| cat == none) {
+                            none_met = false;
+                            break;
+                        }
+                    }
+                    if required_met && any_met && none_met {
+                        ids_to_remove.push(*id);
+                    }
+                }
+                for id in ids_to_remove {
+                    buffs.remove(id);
+                }
+            },
+        }
+    }
+}
diff --git a/server/src/events/mod.rs b/server/src/events/mod.rs
index 9d64de3202..651b49a350 100644
--- a/server/src/events/mod.rs
+++ b/server/src/events/mod.rs
@@ -8,8 +8,8 @@ use entity_creation::{
     handle_loaded_character_data, handle_shockwave, handle_shoot,
 };
 use entity_manipulation::{
-    handle_damage, handle_destroy, handle_explosion, handle_knockback, handle_land_on_ground,
-    handle_level_up, handle_respawn,
+    handle_buff, handle_damage, handle_destroy, handle_explosion, handle_knockback,
+    handle_land_on_ground, handle_level_up, handle_respawn,
 };
 use group_manip::handle_group;
 use interaction::{handle_lantern, handle_mount, handle_possess, handle_unmount};
@@ -133,6 +133,10 @@ impl Server {
                 ServerEvent::Chat(msg) => {
                     chat_messages.push(msg);
                 },
+                ServerEvent::Buff {
+                    entity,
+                    buff_change,
+                } => handle_buff(self, entity, buff_change),
             }
         }
 
diff --git a/server/src/state_ext.rs b/server/src/state_ext.rs
index a4208f0934..06d7c523e3 100644
--- a/server/src/state_ext.rs
+++ b/server/src/state_ext.rs
@@ -111,6 +111,7 @@ impl StateExt for State {
             .with(comp::Gravity(1.0))
             .with(comp::CharacterState::default())
             .with(loadout)
+            .with(comp::Buffs::default())
     }
 
     fn create_object(&mut self, pos: comp::Pos, object: comp::object::Body) -> EcsEntityBuilder {
@@ -202,6 +203,7 @@ impl StateExt for State {
             entity,
             comp::Alignment::Owned(self.read_component_copied(entity).unwrap()),
         );
+        self.write_component(entity, comp::Buffs::default());
 
         // Make sure physics components are updated
         self.write_component(entity, comp::ForceUpdate);
diff --git a/server/src/sys/sentinel.rs b/server/src/sys/sentinel.rs
index fcecccb288..68d568b66c 100644
--- a/server/src/sys/sentinel.rs
+++ b/server/src/sys/sentinel.rs
@@ -1,7 +1,7 @@
 use super::SysTimer;
 use common::{
     comp::{
-        BeamSegment, Body, CanBuild, CharacterState, Collider, Energy, Gravity, Group, Item,
+        BeamSegment, Body, Buffs, CanBuild, CharacterState, Collider, Energy, Gravity, Group, Item,
         LightEmitter, Loadout, Mass, MountState, Mounting, Ori, Player, Pos, Scale, Shockwave,
         Stats, Sticky, Vel,
     },
@@ -44,6 +44,7 @@ pub struct TrackedComps<'a> {
     pub body: ReadStorage<'a, Body>,
     pub player: ReadStorage<'a, Player>,
     pub stats: ReadStorage<'a, Stats>,
+    pub buffs: ReadStorage<'a, Buffs>,
     pub energy: ReadStorage<'a, Energy>,
     pub can_build: ReadStorage<'a, CanBuild>,
     pub light_emitter: ReadStorage<'a, LightEmitter>,
@@ -85,6 +86,10 @@ impl<'a> TrackedComps<'a> {
             .get(entity)
             .cloned()
             .map(|c| comps.push(c.into()));
+        self.buffs
+            .get(entity)
+            .cloned()
+            .map(|c| comps.push(c.into()));
         self.energy
             .get(entity)
             .cloned()
@@ -157,6 +162,7 @@ pub struct ReadTrackers<'a> {
     pub body: ReadExpect<'a, UpdateTracker<Body>>,
     pub player: ReadExpect<'a, UpdateTracker<Player>>,
     pub stats: ReadExpect<'a, UpdateTracker<Stats>>,
+    pub buffs: ReadExpect<'a, UpdateTracker<Buffs>>,
     pub energy: ReadExpect<'a, UpdateTracker<Energy>>,
     pub can_build: ReadExpect<'a, UpdateTracker<CanBuild>>,
     pub light_emitter: ReadExpect<'a, UpdateTracker<LightEmitter>>,
@@ -187,6 +193,7 @@ impl<'a> ReadTrackers<'a> {
             .with_component(&comps.uid, &*self.body, &comps.body, filter)
             .with_component(&comps.uid, &*self.player, &comps.player, filter)
             .with_component(&comps.uid, &*self.stats, &comps.stats, filter)
+            .with_component(&comps.uid, &*self.buffs, &comps.buffs, filter)
             .with_component(&comps.uid, &*self.energy, &comps.energy, filter)
             .with_component(&comps.uid, &*self.can_build, &comps.can_build, filter)
             .with_component(
@@ -224,6 +231,7 @@ pub struct WriteTrackers<'a> {
     body: WriteExpect<'a, UpdateTracker<Body>>,
     player: WriteExpect<'a, UpdateTracker<Player>>,
     stats: WriteExpect<'a, UpdateTracker<Stats>>,
+    buffs: WriteExpect<'a, UpdateTracker<Buffs>>,
     energy: WriteExpect<'a, UpdateTracker<Energy>>,
     can_build: WriteExpect<'a, UpdateTracker<CanBuild>>,
     light_emitter: WriteExpect<'a, UpdateTracker<LightEmitter>>,
@@ -248,6 +256,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
     trackers.body.record_changes(&comps.body);
     trackers.player.record_changes(&comps.player);
     trackers.stats.record_changes(&comps.stats);
+    trackers.buffs.record_changes(&comps.buffs);
     trackers.energy.record_changes(&comps.energy);
     trackers.can_build.record_changes(&comps.can_build);
     trackers.light_emitter.record_changes(&comps.light_emitter);
@@ -283,6 +292,7 @@ fn record_changes(comps: &TrackedComps, trackers: &mut WriteTrackers) {
     };
     log_counts!(uid, "Uids");
     log_counts!(body, "Bodies");
+    log_counts!(buffs, "Buffs");
     log_counts!(player, "Players");
     log_counts!(stats, "Stats");
     log_counts!(energy, "Energies");
@@ -307,6 +317,7 @@ pub fn register_trackers(world: &mut World) {
     world.register_tracker::<Body>();
     world.register_tracker::<Player>();
     world.register_tracker::<Stats>();
+    world.register_tracker::<Buffs>();
     world.register_tracker::<Energy>();
     world.register_tracker::<CanBuild>();
     world.register_tracker::<LightEmitter>();
diff --git a/voxygen/src/ecs/sys/floater.rs b/voxygen/src/ecs/sys/floater.rs
index 6964010d9f..ad9c8c1de7 100644
--- a/voxygen/src/ecs/sys/floater.rs
+++ b/voxygen/src/ecs/sys/floater.rs
@@ -76,6 +76,7 @@ impl<'a> System<'a> for Sys {
                     | HealthSource::Projectile { owner: Some(by) }
                     | HealthSource::Energy { owner: Some(by) }
                     | HealthSource::Explosion { owner: Some(by) }
+                    | HealthSource::Buff { owner: Some(by) }
                     | HealthSource::Healing { by: Some(by) } => {
                         let by_me = my_uid.map_or(false, |&uid| by == uid);
                         // If the attack was by me also reset this timer
diff --git a/voxygen/src/hud/buffs.rs b/voxygen/src/hud/buffs.rs
new file mode 100644
index 0000000000..1bd91eabc3
--- /dev/null
+++ b/voxygen/src/hud/buffs.rs
@@ -0,0 +1,474 @@
+use super::{
+    img_ids::{Imgs, ImgsRot},
+    BUFF_COLOR, DEBUFF_COLOR, TEXT_COLOR,
+};
+use crate::{
+    hud::{get_buff_info, BuffPosition},
+    i18n::VoxygenLocalization,
+    ui::{fonts::ConrodVoxygenFonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
+    GlobalState,
+};
+
+use common::comp::{BuffKind, Buffs};
+use conrod_core::{
+    color,
+    widget::{self, Button, Image, Rectangle, Text},
+    widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
+};
+
+widget_ids! {
+    struct Ids {
+        align,
+        buffs_align,
+        debuffs_align,
+        buff_test,
+        debuff_test,
+        buffs[],
+        buff_timers[],
+        debuffs[],
+        debuff_timers[],
+        buff_txts[],
+    }
+}
+
+#[derive(WidgetCommon)]
+pub struct BuffsBar<'a> {
+    imgs: &'a Imgs,
+    fonts: &'a ConrodVoxygenFonts,
+    #[conrod(common_builder)]
+    common: widget::CommonBuilder,
+    rot_imgs: &'a ImgsRot,
+    tooltip_manager: &'a mut TooltipManager,
+    localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
+    buffs: &'a Buffs,
+    pulse: f32,
+    global_state: &'a GlobalState,
+}
+
+impl<'a> BuffsBar<'a> {
+    #[allow(clippy::too_many_arguments)] // TODO: Pending review in #587
+    pub fn new(
+        imgs: &'a Imgs,
+        fonts: &'a ConrodVoxygenFonts,
+        rot_imgs: &'a ImgsRot,
+        tooltip_manager: &'a mut TooltipManager,
+        localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
+        buffs: &'a Buffs,
+        pulse: f32,
+        global_state: &'a GlobalState,
+    ) -> Self {
+        Self {
+            imgs,
+            fonts,
+            common: widget::CommonBuilder::default(),
+            rot_imgs,
+            tooltip_manager,
+            localized_strings,
+            buffs,
+            pulse,
+            global_state,
+        }
+    }
+}
+
+pub struct State {
+    ids: Ids,
+}
+
+pub enum Event {
+    RemoveBuff(BuffKind),
+}
+
+impl<'a> Widget for BuffsBar<'a> {
+    type Event = Vec<Event>;
+    type State = State;
+    type Style = ();
+
+    fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
+        State {
+            ids: Ids::new(id_gen),
+        }
+    }
+
+    fn style(&self) -> Self::Style {}
+
+    fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
+        let widget::UpdateArgs { state, ui, .. } = args;
+        let mut event = Vec::new();
+        let localized_strings = self.localized_strings;
+        let buffs = self.buffs;
+        let buff_ani = ((self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8) + 0.5; //Animation timer
+        let pulsating_col = Color::Rgba(1.0, 1.0, 1.0, buff_ani);
+        let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0);
+        let buff_position = self.global_state.settings.gameplay.buff_position;
+        let buffs_tooltip = Tooltip::new({
+            // Edge images [t, b, r, l]
+            // Corner images [tr, tl, br, bl]
+            let edge = &self.rot_imgs.tt_side;
+            let corner = &self.rot_imgs.tt_corner;
+            ImageFrame::new(
+                [edge.cw180, edge.none, edge.cw270, edge.cw90],
+                [corner.none, corner.cw270, corner.cw90, corner.cw180],
+                Color::Rgba(0.08, 0.07, 0.04, 1.0),
+                5.0,
+            )
+        })
+        .title_font_size(self.fonts.cyri.scale(15))
+        .parent(ui.window)
+        .desc_font_size(self.fonts.cyri.scale(12))
+        .font_id(self.fonts.cyri.conrod_id)
+        .desc_text_color(TEXT_COLOR);
+        if let BuffPosition::Bar = buff_position {
+            // Alignment
+            Rectangle::fill_with([484.0, 100.0], color::TRANSPARENT)
+                .mid_bottom_with_margin_on(ui.window, 92.0)
+                .set(state.ids.align, ui);
+            Rectangle::fill_with([484.0 / 2.0, 90.0], color::TRANSPARENT)
+                .bottom_left_with_margins_on(state.ids.align, 0.0, 0.0)
+                .set(state.ids.debuffs_align, ui);
+            Rectangle::fill_with([484.0 / 2.0, 90.0], color::TRANSPARENT)
+                .bottom_right_with_margins_on(state.ids.align, 0.0, 0.0)
+                .set(state.ids.buffs_align, ui);
+
+            // Buffs and Debuffs
+            let (buff_count, debuff_count) = buffs.iter_active().map(get_buff_info).fold(
+                (0, 0),
+                |(buff_count, debuff_count), info| {
+                    if info.is_buff {
+                        (buff_count + 1, debuff_count)
+                    } else {
+                        (buff_count, debuff_count + 1)
+                    }
+                },
+            );
+            // Limit displayed buffs
+            let buff_count = buff_count.min(22);
+            let debuff_count = debuff_count.min(22);
+
+            let gen = &mut ui.widget_id_generator();
+            if state.ids.buffs.len() < buff_count {
+                state.update(|state| state.ids.buffs.resize(buff_count, gen));
+            };
+            if state.ids.debuffs.len() < debuff_count {
+                state.update(|state| state.ids.debuffs.resize(debuff_count, gen));
+            };
+            if state.ids.buff_timers.len() < buff_count {
+                state.update(|state| state.ids.buff_timers.resize(buff_count, gen));
+            };
+            if state.ids.debuff_timers.len() < debuff_count {
+                state.update(|state| state.ids.debuff_timers.resize(debuff_count, gen));
+            };
+
+            // Create Buff Widgets
+            state
+                .ids
+                .buffs
+                .iter()
+                .copied()
+                .zip(state.ids.buff_timers.iter().copied())
+                .zip(
+                    buffs
+                        .iter_active()
+                        .map(get_buff_info)
+                        .filter(|info| info.is_buff),
+                )
+                .enumerate()
+                .for_each(|(i, ((id, timer_id), buff))| {
+                    let max_duration = buff.data.duration;
+                    let current_duration = buff.dur;
+                    let duration_percentage = current_duration.map_or(1000.0, |cur| {
+                        max_duration
+                            .map_or(1000.0, |max| cur.as_secs_f32() / max.as_secs_f32() * 1000.0)
+                    }) as u32; // Percentage to determine which frame of the timer overlay is displayed
+                    let buff_img = match buff.kind {
+                        BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
+                        _ => self.imgs.missing_icon,
+                    };
+                    let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
+                    // Sort buffs into rows of 11 slots
+                    let x = i % 11;
+                    let y = i / 11;
+                    let buff_widget = buff_widget.bottom_left_with_margins_on(
+                        state.ids.buffs_align,
+                        0.0 + y as f64 * (21.0),
+                        0.0 + x as f64 * (21.0),
+                    );
+                    buff_widget
+                        .color(
+                            if current_duration.map_or(false, |cur| cur.as_secs_f32() < 10.0) {
+                                Some(pulsating_col)
+                            } else {
+                                Some(norm_col)
+                            },
+                        )
+                        .set(id, ui);
+                    // Create Buff tooltip
+                    let title = match buff.kind {
+                        BuffKind::Regeneration { .. } => {
+                            localized_strings.get("buff.title.heal_test")
+                        },
+                        _ => localized_strings.get("buff.title.missing"),
+                    };
+                    let remaining_time = if current_duration.is_none() {
+                        "Permanent".to_string()
+                    } else {
+                        format!("Remaining: {:.0}s", current_duration.unwrap().as_secs_f32())
+                    };
+                    let click_to_remove = format!("<{}>", &localized_strings.get("buff.remove"));
+                    let desc_txt = match buff.kind {
+                        BuffKind::Regeneration { .. } => {
+                            localized_strings.get("buff.desc.heal_test")
+                        },
+                        _ => localized_strings.get("buff.desc.missing"),
+                    };
+                    let desc = format!("{}\n\n{}\n\n{}", desc_txt, remaining_time, click_to_remove);
+                    // Timer overlay
+                    if Button::image(match duration_percentage as u64 {
+                        875..=1000 => self.imgs.nothing, // 8/8
+                        750..=874 => self.imgs.buff_0,   // 7/8
+                        625..=749 => self.imgs.buff_1,   // 6/8
+                        500..=624 => self.imgs.buff_2,   // 5/8
+                        375..=499 => self.imgs.buff_3,   // 4/8
+                        250..=374 => self.imgs.buff_4,   //3/8
+                        125..=249 => self.imgs.buff_5,   // 2/8
+                        0..=124 => self.imgs.buff_6,     // 1/8
+                        _ => self.imgs.nothing,
+                    })
+                    .w_h(20.0, 20.0)
+                    .middle_of(id)
+                    .with_tooltip(
+                        self.tooltip_manager,
+                        title,
+                        &desc,
+                        &buffs_tooltip,
+                        BUFF_COLOR,
+                    )
+                    .set(timer_id, ui)
+                    .was_clicked()
+                    {
+                        event.push(Event::RemoveBuff(buff.kind));
+                    };
+                });
+            // Create Debuff Widgets
+            state
+                .ids
+                .debuffs
+                .iter()
+                .copied()
+                .zip(state.ids.debuff_timers.iter().copied())
+                .zip(
+                    buffs
+                        .iter_active()
+                        .map(get_buff_info)
+                        .filter(|info| !info.is_buff),
+                )
+                .enumerate()
+                .for_each(|(i, ((id, timer_id), debuff))| {
+                    let max_duration = debuff.data.duration;
+                    let current_duration = debuff.dur;
+                    let duration_percentage = current_duration.map_or(1000.0, |cur| {
+                        max_duration
+                            .map_or(1000.0, |max| cur.as_secs_f32() / max.as_secs_f32() * 1000.0)
+                    }) as u32; // Percentage to determine which frame of the timer overlay is displayed
+                    let debuff_img = match debuff.kind {
+                        BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
+                        BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
+                        _ => self.imgs.missing_icon,
+                    };
+                    let debuff_widget = Image::new(debuff_img).w_h(20.0, 20.0);
+                    // Sort buffs into rows of 11 slots
+                    let x = i % 11;
+                    let y = i / 11;
+                    let debuff_widget = debuff_widget.bottom_right_with_margins_on(
+                        state.ids.debuffs_align,
+                        0.0 + y as f64 * (21.0),
+                        0.0 + x as f64 * (21.0),
+                    );
+
+                    debuff_widget
+                        .color(
+                            if current_duration.map_or(false, |cur| cur.as_secs_f32() < 10.0) {
+                                Some(pulsating_col)
+                            } else {
+                                Some(norm_col)
+                            },
+                        )
+                        .set(id, ui);
+                    // Create Debuff tooltip
+                    let title = match debuff.kind {
+                        BuffKind::Bleeding { .. } => {
+                            localized_strings.get("debuff.title.bleed_test")
+                        },
+                        _ => localized_strings.get("buff.title.missing"),
+                    };
+                    let remaining_time = if current_duration.is_none() {
+                        "Permanent".to_string()
+                    } else {
+                        format!("Remaining: {:.0}s", current_duration.unwrap().as_secs_f32())
+                    };
+                    let desc_txt = match debuff.kind {
+                        BuffKind::Bleeding { .. } => {
+                            localized_strings.get("debuff.desc.bleed_test")
+                        },
+                        _ => localized_strings.get("debuff.desc.missing"),
+                    };
+                    let desc = format!("{}\n\n{}", desc_txt, remaining_time);
+                    Image::new(match duration_percentage as u64 {
+                        875..=1000 => self.imgs.nothing, // 8/8
+                        750..=874 => self.imgs.buff_0,   // 7/8
+                        625..=749 => self.imgs.buff_1,   // 6/8
+                        500..=624 => self.imgs.buff_2,   // 5/8
+                        375..=499 => self.imgs.buff_3,   // 4/8
+                        250..=374 => self.imgs.buff_4,   //3/8
+                        125..=249 => self.imgs.buff_5,   // 2/8
+                        0..=124 => self.imgs.buff_6,     // 1/8
+                        _ => self.imgs.nothing,
+                    })
+                    .w_h(20.0, 20.0)
+                    .middle_of(id)
+                    .with_tooltip(
+                        self.tooltip_manager,
+                        title,
+                        &desc,
+                        &buffs_tooltip,
+                        DEBUFF_COLOR,
+                    )
+                    .set(timer_id, ui);
+                });
+        }
+
+        if let BuffPosition::Map = buff_position {
+            // Alignment
+            Rectangle::fill_with([210.0, 210.0], color::TRANSPARENT)
+                .top_right_with_margins_on(ui.window, 5.0, 270.0)
+                .set(state.ids.align, ui);
+
+            // Buffs and Debuffs
+            let buff_count = buffs.kinds.len().min(11);
+            // Limit displayed buffs
+            let buff_count = buff_count.min(20);
+
+            let gen = &mut ui.widget_id_generator();
+            if state.ids.buffs.len() < buff_count {
+                state.update(|state| state.ids.buffs.resize(buff_count, gen));
+            };
+            if state.ids.buff_timers.len() < buff_count {
+                state.update(|state| state.ids.buff_timers.resize(buff_count, gen));
+            };
+            if state.ids.buff_txts.len() < buff_count {
+                state.update(|state| state.ids.buff_txts.resize(buff_count, gen));
+            };
+
+            // Create Buff Widgets
+            state
+                .ids
+                .buffs
+                .iter()
+                .copied()
+                .zip(state.ids.buff_timers.iter().copied())
+                .zip(state.ids.buff_txts.iter().copied())
+                .zip(buffs.iter_active().map(get_buff_info))
+                .enumerate()
+                .for_each(|(i, (((id, timer_id), txt_id), buff))| {
+                    let max_duration = buff.data.duration;
+                    let current_duration = buff.dur;
+                    // Percentage to determine which frame of the timer overlay is displayed
+                    let duration_percentage = current_duration.map_or(1000.0, |cur| {
+                        max_duration
+                            .map_or(1000.0, |max| cur.as_secs_f32() / max.as_secs_f32() * 1000.0)
+                    }) as u32;
+                    let buff_img = match buff.kind {
+                        BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
+                        BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
+                        BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
+                    };
+                    let buff_widget = Image::new(buff_img).w_h(40.0, 40.0);
+                    // Sort buffs into rows of 6 slots
+                    let x = i % 6;
+                    let y = i / 6;
+                    let buff_widget = buff_widget.top_right_with_margins_on(
+                        state.ids.align,
+                        0.0 + y as f64 * (54.0),
+                        0.0 + x as f64 * (42.0),
+                    );
+                    buff_widget
+                        .color(
+                            if current_duration.map_or(false, |cur| cur.as_secs_f32() < 10.0) {
+                                Some(pulsating_col)
+                            } else {
+                                Some(norm_col)
+                            },
+                        )
+                        .set(id, ui);
+                    // Create Buff tooltip
+                    let title = match buff.kind {
+                        BuffKind::Regeneration { .. } => {
+                            localized_strings.get("buff.title.heal_test")
+                        },
+                        BuffKind::Bleeding { .. } => {
+                            localized_strings.get("debuff.title.bleed_test")
+                        },
+                        _ => localized_strings.get("buff.title.missing"),
+                    };
+                    let remaining_time = if current_duration.is_none() {
+                        "".to_string()
+                    } else {
+                        format!("{:.0}s", current_duration.unwrap().as_secs_f32())
+                    };
+                    let click_to_remove = format!("<{}>", &localized_strings.get("buff.remove"));
+                    let desc_txt = match buff.kind {
+                        BuffKind::Regeneration { .. } => {
+                            localized_strings.get("buff.desc.heal_test")
+                        },
+                        BuffKind::Bleeding { .. } => {
+                            localized_strings.get("debuff.desc.bleed_test")
+                        },
+                        _ => localized_strings.get("buff.desc.missing"),
+                    };
+                    let desc = if buff.is_buff {
+                        format!("{}\n\n{}", desc_txt, click_to_remove)
+                    } else {
+                        desc_txt.to_string()
+                    };
+                    // Timer overlay
+                    if Button::image(match duration_percentage as u64 {
+                        875..=1000 => self.imgs.nothing, // 8/8
+                        750..=874 => self.imgs.buff_0,   // 7/8
+                        625..=749 => self.imgs.buff_1,   // 6/8
+                        500..=624 => self.imgs.buff_2,   // 5/8
+                        375..=499 => self.imgs.buff_3,   // 4/8
+                        250..=374 => self.imgs.buff_4,   // 3/8
+                        125..=249 => self.imgs.buff_5,   // 2/8
+                        0..=124 => self.imgs.buff_6,     // 1/8
+                        _ => self.imgs.nothing,
+                    })
+                    .w_h(40.0, 40.0)
+                    .middle_of(id)
+                    .with_tooltip(
+                        self.tooltip_manager,
+                        title,
+                        &desc,
+                        &buffs_tooltip,
+                        if buff.is_buff {
+                            BUFF_COLOR
+                        } else {
+                            DEBUFF_COLOR
+                        },
+                    )
+                    .set(timer_id, ui)
+                    .was_clicked()
+                    {
+                        event.push(Event::RemoveBuff(buff.kind));
+                    }
+                    Text::new(&remaining_time)
+                        .down_from(timer_id, 1.0)
+                        .font_size(self.fonts.cyri.scale(10))
+                        .font_id(self.fonts.cyri.conrod_id)
+                        .graphics_for(timer_id)
+                        .color(TEXT_COLOR)
+                        .set(txt_id, ui);
+                });
+        }
+        event
+    }
+}
diff --git a/voxygen/src/hud/chat.rs b/voxygen/src/hud/chat.rs
index 8194ddf445..b9424d366a 100644
--- a/voxygen/src/hud/chat.rs
+++ b/voxygen/src/hud/chat.rs
@@ -373,6 +373,10 @@ impl<'a> Widget for Chat<'a> {
                             .localized_strings
                             .get("hud.chat.pvp_energy_kill_msg")
                             .to_string(),
+                        KillSource::Player(_, KillType::Buff) => self
+                            .localized_strings
+                            .get("hud.chat.pvp_buff_kill_msg")
+                            .to_string(),
                         KillSource::NonPlayer(_, KillType::Melee) => self
                             .localized_strings
                             .get("hud.chat.npc_melee_kill_msg")
@@ -389,6 +393,10 @@ impl<'a> Widget for Chat<'a> {
                             .localized_strings
                             .get("hud.chat.npc_energy_kill_msg")
                             .to_string(),
+                        KillSource::NonPlayer(_, KillType::Buff) => self
+                            .localized_strings
+                            .get("hud.chat.npc_buff_kill_msg")
+                            .to_string(),
                         KillSource::Environment(_) => self
                             .localized_strings
                             .get("hud.chat.environmental_kill_msg")
diff --git a/voxygen/src/hud/group.rs b/voxygen/src/hud/group.rs
index 26060b3084..1bfeaa1cb2 100644
--- a/voxygen/src/hud/group.rs
+++ b/voxygen/src/hud/group.rs
@@ -1,15 +1,20 @@
 use super::{
-    img_ids::Imgs, Show, BLACK, ERROR_COLOR, GROUP_COLOR, HP_COLOR, KILL_COLOR, LOW_HP_COLOR,
-    MANA_COLOR, TEXT_COLOR, TEXT_COLOR_GREY, UI_HIGHLIGHT_0, UI_MAIN,
+    img_ids::{Imgs, ImgsRot},
+    Show, BLACK, BUFF_COLOR, DEBUFF_COLOR, ERROR_COLOR, GROUP_COLOR, HP_COLOR, KILL_COLOR,
+    LOW_HP_COLOR, STAMINA_COLOR, TEXT_COLOR, TEXT_COLOR_GREY, UI_HIGHLIGHT_0, UI_MAIN,
 };
 
 use crate::{
-    i18n::VoxygenLocalization, settings::Settings, ui::fonts::ConrodVoxygenFonts,
-    window::GameInput, GlobalState,
+    hud::get_buff_info,
+    i18n::VoxygenLocalization,
+    settings::Settings,
+    ui::{fonts::ConrodVoxygenFonts, ImageFrame, Tooltip, TooltipManager, Tooltipable},
+    window::GameInput,
+    GlobalState,
 };
 use client::{self, Client};
 use common::{
-    comp::{group::Role, Stats},
+    comp::{group::Role, BuffKind, Stats},
     sync::{Uid, WorldSyncExt},
 };
 use conrod_core::{
@@ -19,7 +24,6 @@ use conrod_core::{
     widget_ids, Color, Colorable, Labelable, Positionable, Sizeable, Widget, WidgetCommon,
 };
 use specs::{saveload::MarkerAllocator, WorldExt};
-
 widget_ids! {
     pub struct Ids {
         group_button,
@@ -44,6 +48,8 @@ widget_ids! {
         member_panels_txt[],
         member_health[],
         member_stam[],
+        buffs[],
+        buff_timers[],
         dead_txt[],
         health_txt[],
         timeout_bg,
@@ -63,10 +69,12 @@ pub struct Group<'a> {
     client: &'a Client,
     settings: &'a Settings,
     imgs: &'a Imgs,
+    rot_imgs: &'a ImgsRot,
     fonts: &'a ConrodVoxygenFonts,
     localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
     pulse: f32,
     global_state: &'a GlobalState,
+    tooltip_manager: &'a mut TooltipManager,
 
     #[conrod(common_builder)]
     common: widget::CommonBuilder,
@@ -79,20 +87,24 @@ impl<'a> Group<'a> {
         client: &'a Client,
         settings: &'a Settings,
         imgs: &'a Imgs,
+        rot_imgs: &'a ImgsRot,
         fonts: &'a ConrodVoxygenFonts,
         localized_strings: &'a std::sync::Arc<VoxygenLocalization>,
         pulse: f32,
         global_state: &'a GlobalState,
+        tooltip_manager: &'a mut TooltipManager,
     ) -> Self {
         Self {
             show,
             client,
             settings,
             imgs,
+            rot_imgs,
             fonts,
             localized_strings,
             pulse,
             global_state,
+            tooltip_manager,
             common: widget::CommonBuilder::default(),
         }
     }
@@ -127,8 +139,26 @@ impl<'a> Widget for Group<'a> {
     #[allow(clippy::blocks_in_if_conditions)] // TODO: Pending review in #587
     fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
         let widget::UpdateArgs { state, ui, .. } = args;
-
         let mut events = Vec::new();
+        let localized_strings = self.localized_strings;
+        let buff_ani = ((self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8) + 0.5; //Animation timer
+        let buffs_tooltip = Tooltip::new({
+            // Edge images [t, b, r, l]
+            // Corner images [tr, tl, br, bl]
+            let edge = &self.rot_imgs.tt_side;
+            let corner = &self.rot_imgs.tt_corner;
+            ImageFrame::new(
+                [edge.cw180, edge.none, edge.cw270, edge.cw90],
+                [corner.none, corner.cw270, corner.cw90, corner.cw180],
+                Color::Rgba(0.08, 0.07, 0.04, 1.0),
+                5.0,
+            )
+        })
+        .title_font_size(self.fonts.cyri.scale(15))
+        .parent(ui.window)
+        .desc_font_size(self.fonts.cyri.scale(12))
+        .font_id(self.fonts.cyri.conrod_id)
+        .desc_text_color(TEXT_COLOR);
 
         // Don't show pets
         let group_members = self
@@ -293,31 +323,35 @@ impl<'a> Widget for Group<'a> {
             let client_state = self.client.state();
             let stats = client_state.ecs().read_storage::<common::comp::Stats>();
             let energy = client_state.ecs().read_storage::<common::comp::Energy>();
+            let buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
             let uid_allocator = client_state
                 .ecs()
                 .read_resource::<common::sync::UidAllocator>();
-
+            let offset = if self.global_state.settings.gameplay.toggle_debug {
+                320.0
+            } else {
+                110.0
+            };
+            // Keep track of the total number of widget ids we are using for buffs
+            let mut total_buff_count = 0;
             for (i, &uid) in group_members.iter().copied().enumerate() {
                 self.show.group = true;
                 let entity = uid_allocator.retrieve_entity_internal(uid.into());
                 let stats = entity.and_then(|entity| stats.get(entity));
                 let energy = entity.and_then(|entity| energy.get(entity));
+                let buffs = entity.and_then(|entity| buffs.get(entity));
+
                 if let Some(stats) = stats {
                     let char_name = stats.name.to_string();
                     let health_perc = stats.health.current() as f64 / stats.health.maximum() as f64;
 
                     // change panel positions when debug info is shown
-                    let offset = if self.global_state.settings.gameplay.toggle_debug {
-                        290.0
-                    } else {
-                        110.0
-                    };
                     let back = if i == 0 {
                         Image::new(self.imgs.member_bg)
                             .top_left_with_margins_on(ui.window, offset, 20.0)
                     } else {
                         Image::new(self.imgs.member_bg)
-                            .down_from(state.ids.member_panels_bg[i - 1], 40.0)
+                            .down_from(state.ids.member_panels_bg[i - 1], 45.0)
                     };
                     let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
                     let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
@@ -386,66 +420,174 @@ impl<'a> Widget for Group<'a> {
                         .set(state.ids.member_panels_frame[i], ui);
                     // Panel Text
                     Text::new(&char_name)
-                        .top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 0.0)
-                        .font_size(20)
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(BLACK)
-                        .w(300.0) // limit name length display
-                        .set(state.ids.member_panels_txt_bg[i], ui);
+                            .top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 0.0)
+                            .font_size(20)
+                            .font_id(self.fonts.cyri.conrod_id)
+                            .color(BLACK)
+                            .w(300.0) // limit name length display
+                            .set(state.ids.member_panels_txt_bg[i], ui);
                     Text::new(&char_name)
-                        .bottom_left_with_margins_on(state.ids.member_panels_txt_bg[i], 2.0, 2.0)
-                        .font_size(20)
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(if is_leader { ERROR_COLOR } else { GROUP_COLOR })
-                        .w(300.0) // limit name length display
-                        .set(state.ids.member_panels_txt[i], ui);
+                            .bottom_left_with_margins_on(state.ids.member_panels_txt_bg[i], 2.0, 2.0)
+                            .font_size(20)
+                            .font_id(self.fonts.cyri.conrod_id)
+                            .color(if is_leader { ERROR_COLOR } else { GROUP_COLOR })
+                            .w(300.0) // limit name length display
+                            .set(state.ids.member_panels_txt[i], ui);
                     if let Some(energy) = energy {
                         let stam_perc = energy.current() as f64 / energy.maximum() as f64;
                         // Stamina
                         Image::new(self.imgs.bar_content)
                             .w_h(100.0 * stam_perc, 8.0)
-                            .color(Some(MANA_COLOR))
+                            .color(Some(STAMINA_COLOR))
                             .top_left_with_margins_on(state.ids.member_panels_bg[i], 26.0, 2.0)
                             .set(state.ids.member_stam[i], ui);
                     }
-                } else {
-                    // Values N.A.
-                    if let Some(stats) = stats {
+                    if let Some(buffs) = buffs {
+                        // Limit displayed buffs to 11
+                        let buff_count = buffs.kinds.len().min(11);
+                        total_buff_count += buff_count;
+                        let gen = &mut ui.widget_id_generator();
+                        if state.ids.buffs.len() < total_buff_count {
+                            state.update(|state| state.ids.buffs.resize(total_buff_count, gen));
+                        }
+                        if state.ids.buff_timers.len() < total_buff_count {
+                            state.update(|state| {
+                                state.ids.buff_timers.resize(total_buff_count, gen)
+                            });
+                        }
+                        // Create Buff Widgets
+                        let mut prev_id = None;
+                        state
+                            .ids
+                            .buffs
+                            .iter()
+                            .copied()
+                            .zip(state.ids.buff_timers.iter().copied())
+                            .skip(total_buff_count - buff_count)
+                            .zip(buffs.iter_active().map(get_buff_info))
+                            .for_each(|((id, timer_id), buff)| {
+                                let max_duration = buff.data.duration;
+                                let pulsating_col = Color::Rgba(1.0, 1.0, 1.0, buff_ani);
+                                let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0);
+                                let current_duration = buff.dur;
+                                let duration_percentage = current_duration.map_or(1000.0, |cur| {
+                                    max_duration.map_or(1000.0, |max| {
+                                        cur.as_secs_f32() / max.as_secs_f32() * 1000.0
+                                    })
+                                }) as u32; // Percentage to determine which frame of the timer overlay is displayed
+                                let buff_img = match buff.kind {
+                                    BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
+                                    BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
+                                    BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
+                                };
+                                let buff_widget = Image::new(buff_img).w_h(15.0, 15.0);
+                                let buff_widget = if let Some(id) = prev_id {
+                                    buff_widget.right_from(id, 1.0)
+                                } else {
+                                    buff_widget.bottom_left_with_margins_on(
+                                        state.ids.member_panels_frame[i],
+                                        -16.0,
+                                        1.0,
+                                    )
+                                };
+                                prev_id = Some(id);
+                                buff_widget
+                                    .color(
+                                        if current_duration
+                                            .map_or(false, |cur| cur.as_secs_f32() < 10.0)
+                                        {
+                                            Some(pulsating_col)
+                                        } else {
+                                            Some(norm_col)
+                                        },
+                                    )
+                                    .set(id, ui);
+                                // Create Buff tooltip
+                                let title = match buff.kind {
+                                    BuffKind::Regeneration { .. } => {
+                                        localized_strings.get("buff.title.heal_test")
+                                    },
+                                    BuffKind::Bleeding { .. } => {
+                                        localized_strings.get("debuff.title.bleed_test")
+                                    },
+                                    _ => localized_strings.get("buff.title.missing"),
+                                };
+                                let remaining_time = if current_duration.is_none() {
+                                    "Permanent".to_string()
+                                } else {
+                                    format!(
+                                        "Remaining: {:.0}s",
+                                        current_duration.unwrap().as_secs_f32()
+                                    )
+                                };
+                                let desc_txt = match buff.kind {
+                                    BuffKind::Regeneration { .. } => {
+                                        localized_strings.get("buff.desc.heal_test")
+                                    },
+                                    BuffKind::Bleeding { .. } => {
+                                        localized_strings.get("debuff.desc.bleed_test")
+                                    },
+                                    _ => localized_strings.get("buff.desc.missing"),
+                                };
+                                let desc = format!("{}\n\n{}", desc_txt, remaining_time);
+                                Image::new(match duration_percentage as u64 {
+                                    875..=1000 => self.imgs.nothing, // 8/8
+                                    750..=874 => self.imgs.buff_0,   // 7/8
+                                    625..=749 => self.imgs.buff_1,   // 6/8
+                                    500..=624 => self.imgs.buff_2,   // 5/8
+                                    375..=499 => self.imgs.buff_3,   // 4/8
+                                    250..=374 => self.imgs.buff_4,   // 3/8
+                                    125..=249 => self.imgs.buff_5,   // 2/8
+                                    0..=124 => self.imgs.buff_6,     // 1/8
+                                    _ => self.imgs.nothing,
+                                })
+                                .w_h(15.0, 15.0)
+                                .middle_of(id)
+                                .with_tooltip(
+                                    self.tooltip_manager,
+                                    title,
+                                    &desc,
+                                    &buffs_tooltip,
+                                    if buff.is_buff {
+                                        BUFF_COLOR
+                                    } else {
+                                        DEBUFF_COLOR
+                                    },
+                                )
+                                .set(timer_id, ui);
+                            });
+                    } else {
+                        // Values N.A.
                         Text::new(&stats.name.to_string())
                             .top_left_with_margins_on(state.ids.member_panels_frame[i], -22.0, 0.0)
                             .font_size(20)
                             .font_id(self.fonts.cyri.conrod_id)
                             .color(GROUP_COLOR)
                             .set(state.ids.member_panels_txt[i], ui);
-                    };
-                    let offset = if self.global_state.settings.gameplay.toggle_debug {
-                        210.0
-                    } else {
-                        110.0
-                    };
-                    let back = if i == 0 {
-                        Image::new(self.imgs.member_bg)
-                            .top_left_with_margins_on(ui.window, offset, 20.0)
-                    } else {
-                        Image::new(self.imgs.member_bg)
-                            .down_from(state.ids.member_panels_bg[i - 1], 40.0)
-                    };
-                    back.w_h(152.0, 36.0)
-                        .color(Some(TEXT_COLOR))
-                        .set(state.ids.member_panels_bg[i], ui);
-                    // Panel Frame
-                    Image::new(self.imgs.member_frame)
-                        .w_h(152.0, 36.0)
-                        .middle_of(state.ids.member_panels_bg[i])
-                        .color(Some(UI_HIGHLIGHT_0))
-                        .set(state.ids.member_panels_frame[i], ui);
-                    // Panel Text
-                    Text::new(&self.localized_strings.get("hud.group.out_of_range"))
-                        .mid_top_with_margin_on(state.ids.member_panels_bg[i], 3.0)
-                        .font_size(16)
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(TEXT_COLOR)
-                        .set(state.ids.dead_txt[i], ui);
+                        let back = if i == 0 {
+                            Image::new(self.imgs.member_bg)
+                                .top_left_with_margins_on(ui.window, offset, 20.0)
+                        } else {
+                            Image::new(self.imgs.member_bg)
+                                .down_from(state.ids.member_panels_bg[i - 1], 40.0)
+                        };
+                        back.w_h(152.0, 36.0)
+                            .color(Some(TEXT_COLOR))
+                            .set(state.ids.member_panels_bg[i], ui);
+                        // Panel Frame
+                        Image::new(self.imgs.member_frame)
+                            .w_h(152.0, 36.0)
+                            .middle_of(state.ids.member_panels_bg[i])
+                            .color(Some(UI_HIGHLIGHT_0))
+                            .set(state.ids.member_panels_frame[i], ui);
+                        // Panel Text
+                        Text::new(&self.localized_strings.get("hud.group.out_of_range"))
+                            .mid_top_with_margin_on(state.ids.member_panels_bg[i], 3.0)
+                            .font_size(16)
+                            .font_id(self.fonts.cyri.conrod_id)
+                            .color(TEXT_COLOR)
+                            .set(state.ids.dead_txt[i], ui);
+                    }
                 }
             }
 
diff --git a/voxygen/src/hud/img_ids.rs b/voxygen/src/hud/img_ids.rs
index eecd9d18da..fbb48033c0 100644
--- a/voxygen/src/hud/img_ids.rs
+++ b/voxygen/src/hud/img_ids.rs
@@ -147,22 +147,12 @@ image_ids! {
 
         // Skillbar
         level_up: "voxygen.element.misc_bg.level_up",
-        level_down: "voxygen.element.misc_bg.level_down",
-        xp_bar_mid: "voxygen.element.skillbar.xp_bar_mid",
-        xp_bar_left: "voxygen.element.skillbar.xp_bar_left",
-        xp_bar_right: "voxygen.element.skillbar.xp_bar_right",
-        healthbar_bg: "voxygen.element.skillbar.healthbar_bg",
-        energybar_bg: "voxygen.element.skillbar.energybar_bg",
+        level_down:"voxygen.element.misc_bg.level_down",
         bar_content: "voxygen.element.skillbar.bar_content",
-        skillbar_slot_big: "voxygen.element.skillbar.skillbar_slot_big",
-        skillbar_slot_big_bg: "voxygen.element.skillbar.skillbar_slot_big",
-        skillbar_slot_big_act: "voxygen.element.skillbar.skillbar_slot_big",
-        skillbar_slot: "voxygen.element.skillbar.skillbar_slot",
-        skillbar_slot_act: "voxygen.element.skillbar.skillbar_slot_active",
-        skillbar_slot_l: "voxygen.element.skillbar.skillbar_slot_l",
-        skillbar_slot_r: "voxygen.element.skillbar.skillbar_slot_r",
-        skillbar_slot_l_act: "voxygen.element.skillbar.skillbar_slot_l_active",
-        skillbar_slot_r_act: "voxygen.element.skillbar.skillbar_slot_r_active",
+        skillbar_bg: "voxygen.element.skillbar.bg",
+        skillbar_frame: "voxygen.element.skillbar.frame",
+        m1_ico: "voxygen.element.icons.m1",
+        m2_ico: "voxygen.element.icons.m2",
 
         // Other Icons/Art
         skull: "voxygen.element.icons.skull",
@@ -282,6 +272,7 @@ image_ids! {
         hammerleap: "voxygen.element.icons.skill_hammerleap",
         skill_axe_leap_slash: "voxygen.element.icons.skill_axe_leap_slash",
         skill_bow_jump_burst: "voxygen.element.icons.skill_bow_jump_burst",
+        missing_icon: "voxygen.element.icons.missing_icon_grey",
 
         // Buttons
         button: "voxygen.element.buttons.button",
@@ -359,6 +350,24 @@ image_ids! {
         chat_tell: "voxygen.element.icons.chat.tell",
         chat_world: "voxygen.element.icons.chat.world",
 
+        // Buffs
+        buff_plus_0: "voxygen.element.icons.de_buffs.buff_plus_0",
+
+        // Debuffs
+        debuff_skull_0: "voxygen.element.icons.de_buffs.debuff_skull_0",
+        debuff_bleed_0: "voxygen.element.icons.de_buffs.debuff_bleed_0",
+
+        // Animation Frames
+        // Buff Frame
+        buff_0: "voxygen.element.animation.buff_frame.1",
+        buff_1: "voxygen.element.animation.buff_frame.2",
+        buff_2: "voxygen.element.animation.buff_frame.3",
+        buff_3: "voxygen.element.animation.buff_frame.4",
+        buff_4: "voxygen.element.animation.buff_frame.5",
+        buff_5: "voxygen.element.animation.buff_frame.6",
+        buff_6: "voxygen.element.animation.buff_frame.7",
+        buff_7: "voxygen.element.animation.buff_frame.8",
+
         <BlankGraphic>
         nothing: (),
     }
diff --git a/voxygen/src/hud/minimap.rs b/voxygen/src/hud/minimap.rs
index 1bdeef1395..ca993285cb 100644
--- a/voxygen/src/hud/minimap.rs
+++ b/voxygen/src/hud/minimap.rs
@@ -105,7 +105,7 @@ impl<'a> Widget for MiniMap<'a> {
     fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
         let widget::UpdateArgs { state, ui, .. } = args;
         let zoom = state.zoom;
-        const SCALE: f64 = 1.5;
+        const SCALE: f64 = 1.5; // TODO Make this a setting
         if self.show.mini_map {
             Image::new(self.imgs.mmap_frame)
                 .w_h(174.0 * SCALE, 190.0 * SCALE)
diff --git a/voxygen/src/hud/mod.rs b/voxygen/src/hud/mod.rs
index 0350b89dd1..907a04857f 100644
--- a/voxygen/src/hud/mod.rs
+++ b/voxygen/src/hud/mod.rs
@@ -1,4 +1,5 @@
 mod bag;
+mod buffs;
 mod buttons;
 mod chat;
 mod crafting;
@@ -24,6 +25,7 @@ pub use hotbar::{SlotContents as HotbarSlotContents, State as HotbarState};
 pub use settings_window::ScaleChange;
 
 use bag::Bag;
+use buffs::BuffsBar;
 use buttons::Buttons;
 use chat::Chat;
 use chrono::NaiveTime;
@@ -58,7 +60,10 @@ use client::Client;
 use common::{
     assets::Asset,
     comp,
-    comp::item::{ItemDesc, Quality},
+    comp::{
+        item::{ItemDesc, Quality},
+        BuffKind,
+    },
     span,
     sync::Uid,
     terrain::TerrainChunk,
@@ -91,10 +96,12 @@ const BLACK: Color = Color::Rgba(0.0, 0.0, 0.0, 1.0);
 const HP_COLOR: Color = Color::Rgba(0.33, 0.63, 0.0, 1.0);
 const LOW_HP_COLOR: Color = Color::Rgba(0.93, 0.59, 0.03, 1.0);
 const CRITICAL_HP_COLOR: Color = Color::Rgba(0.79, 0.19, 0.17, 1.0);
-const MANA_COLOR: Color = Color::Rgba(0.29, 0.62, 0.75, 0.9);
+const STAMINA_COLOR: Color = Color::Rgba(0.29, 0.62, 0.75, 0.9);
 //const TRANSPARENT: Color = Color::Rgba(0.0, 0.0, 0.0, 0.0);
 //const FOCUS_COLOR: Color = Color::Rgba(1.0, 0.56, 0.04, 1.0);
 //const RAGE_COLOR: Color = Color::Rgba(0.5, 0.04, 0.13, 1.0);
+const BUFF_COLOR: Color = Color::Rgba(0.06, 0.69, 0.12, 1.0);
+const DEBUFF_COLOR: Color = Color::Rgba(0.79, 0.19, 0.17, 1.0);
 
 // Item Quality Colors
 const QUALITY_LOW: Color = Color::Rgba(0.41, 0.41, 0.41, 1.0); // Grey - Trash, can be sold to vendors
@@ -239,6 +246,7 @@ widget_ids! {
         spell,
         skillbar,
         buttons,
+        buffs,
         esc_menu,
         small_window,
         social_window,
@@ -264,6 +272,14 @@ widget_ids! {
     }
 }
 
+#[derive(Clone, Copy)]
+pub struct BuffInfo {
+    kind: comp::BuffKind,
+    data: comp::BuffData,
+    is_buff: bool,
+    dur: Option<Duration>,
+}
+
 pub struct DebugInfo {
     pub tps: f64,
     pub frame_time: Duration,
@@ -315,6 +331,7 @@ pub enum Event {
     ChatTransp(f32),
     ChatCharName(bool),
     CrosshairType(CrosshairType),
+    BuffPosition(BuffPosition),
     ToggleXpBar(XpBar),
     Intro(Intro),
     ToggleBarNumbers(BarNumbers),
@@ -348,6 +365,7 @@ pub enum Event {
     KickMember(common::sync::Uid),
     LeaveGroup,
     AssignLeader(common::sync::Uid),
+    RemoveBuff(BuffKind),
 }
 
 // TODO: Are these the possible layouts we want?
@@ -388,6 +406,13 @@ pub enum ShortcutNumbers {
     On,
     Off,
 }
+
+#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
+pub enum BuffPosition {
+    Bar,
+    Map,
+}
+
 #[derive(Clone, Copy, Debug, Serialize, Deserialize)]
 pub enum PressBehavior {
     Toggle = 0,
@@ -722,6 +747,7 @@ impl Hud {
             let ecs = client.state().ecs();
             let pos = ecs.read_storage::<comp::Pos>();
             let stats = ecs.read_storage::<comp::Stats>();
+            let buffs = ecs.read_storage::<comp::Buffs>();
             let energy = ecs.read_storage::<comp::Energy>();
             let hp_floater_lists = ecs.read_storage::<vcomp::HpFloaterList>();
             let uids = ecs.read_storage::<common::sync::Uid>();
@@ -1120,11 +1146,12 @@ impl Hud {
             let speech_bubbles = &self.speech_bubbles;
 
             // Render overhead name tags and health bars
-            for (pos, info, bubble, stats, height_offset, hpfl, in_group) in (
+            for (pos, info, bubble, stats, _, height_offset, hpfl, in_group) in (
                 &entities,
                 &pos,
                 interpolated.maybe(),
                 &stats,
+                &buffs,
                 energy.maybe(),
                 scales.maybe(),
                 &bodies,
@@ -1138,7 +1165,7 @@ impl Hud {
                     entity != me && !stats.is_dead
                 })
                 .filter_map(
-                    |(entity, pos, interpolated, stats, energy, scale, body, hpfl, uid)| {
+                    |(entity, pos, interpolated, stats, buffs, energy, scale, body, hpfl, uid)| {
                         // Use interpolated position if available
                         let pos = interpolated.map_or(pos.0, |i| i.pos);
                         let in_group = client.group_members().contains_key(uid);
@@ -1168,6 +1195,7 @@ impl Hud {
                         let info = display_overhead_info.then(|| overhead::Info {
                             name: &stats.name,
                             stats,
+                            buffs,
                             energy,
                         });
                         let bubble = if dist_sqr < SPEECH_BUBBLE_RANGE.powi(2) {
@@ -1182,6 +1210,7 @@ impl Hud {
                                 info,
                                 bubble,
                                 stats,
+                                buffs,
                                 body.height() * scale.map_or(1.0, |s| s.0) + 0.5,
                                 hpfl,
                                 in_group,
@@ -1730,6 +1759,7 @@ impl Hud {
         // Bag button and nearby icons
         let ecs = client.state().ecs();
         let stats = ecs.read_storage::<comp::Stats>();
+        let buffs = ecs.read_storage::<comp::Buffs>();
         if let Some(player_stats) = stats.get(client.entity()) {
             match Buttons::new(
                 client,
@@ -1754,6 +1784,48 @@ impl Hud {
             }
         }
 
+        // Buffs and Debuffs
+        if let Some(player_buffs) = buffs.get(client.entity()) {
+            for event in BuffsBar::new(
+                &self.imgs,
+                &self.fonts,
+                &self.rot_imgs,
+                tooltip_manager,
+                &self.voxygen_i18n,
+                &player_buffs,
+                self.pulse,
+                &global_state,
+            )
+            .set(self.ids.buffs, ui_widgets)
+            {
+                match event {
+                    buffs::Event::RemoveBuff(buff_id) => events.push(Event::RemoveBuff(buff_id)),
+                }
+            }
+        }
+        // Group Window
+        for event in Group::new(
+            &mut self.show,
+            client,
+            &global_state.settings,
+            &self.imgs,
+            &self.rot_imgs,
+            &self.fonts,
+            &self.voxygen_i18n,
+            self.pulse,
+            &global_state,
+            tooltip_manager,
+        )
+        .set(self.ids.group_window, ui_widgets)
+        {
+            match event {
+                group::Event::Accept => events.push(Event::AcceptInvite),
+                group::Event::Decline => events.push(Event::DeclineInvite),
+                group::Event::Kick(uid) => events.push(Event::KickMember(uid)),
+                group::Event::LeaveGroup => events.push(Event::LeaveGroup),
+                group::Event::AssignLeader(uid) => events.push(Event::AssignLeader(uid)),
+            }
+        }
         // Popup (waypoint saved and similar notifications)
         Popup::new(
             &self.voxygen_i18n,
@@ -1828,8 +1900,8 @@ impl Hud {
             Some(stats),
             Some(loadout),
             Some(energy),
-            Some(character_state),
-            Some(controller),
+            Some(_character_state),
+            Some(_controller),
             Some(inventory),
         ) = (
             stats.get(entity),
@@ -1848,9 +1920,9 @@ impl Hud {
                 &stats,
                 &loadout,
                 &energy,
-                &character_state,
+                //&character_state,
                 self.pulse,
-                &controller,
+                //&controller,
                 &inventory,
                 &self.hotbar,
                 tooltip_manager,
@@ -1996,6 +2068,9 @@ impl Hud {
                     settings_window::Event::ToggleZoomInvert(zoom_inverted) => {
                         events.push(Event::ToggleZoomInvert(zoom_inverted));
                     },
+                    settings_window::Event::BuffPosition(buff_position) => {
+                        events.push(Event::BuffPosition(buff_position));
+                    },
                     settings_window::Event::ToggleMouseYInvert(mouse_y_inverted) => {
                         events.push(Event::ToggleMouseYInvert(mouse_y_inverted));
                     },
@@ -2032,9 +2107,6 @@ impl Hud {
                     settings_window::Event::CrosshairType(crosshair_type) => {
                         events.push(Event::CrosshairType(crosshair_type));
                     },
-                    settings_window::Event::ToggleXpBar(xp_bar) => {
-                        events.push(Event::ToggleXpBar(xp_bar));
-                    },
                     settings_window::Event::ToggleBarNumbers(bar_numbers) => {
                         events.push(Event::ToggleBarNumbers(bar_numbers));
                     },
@@ -2123,27 +2195,6 @@ impl Hud {
                 }
             }
         }
-        // Group Window
-        for event in Group::new(
-            &mut self.show,
-            client,
-            &global_state.settings,
-            &self.imgs,
-            &self.fonts,
-            &self.voxygen_i18n,
-            self.pulse,
-            &global_state,
-        )
-        .set(self.ids.group_window, ui_widgets)
-        {
-            match event {
-                group::Event::Accept => events.push(Event::AcceptInvite),
-                group::Event::Decline => events.push(Event::DeclineInvite),
-                group::Event::Kick(uid) => events.push(Event::KickMember(uid)),
-                group::Event::LeaveGroup => events.push(Event::LeaveGroup),
-                group::Event::AssignLeader(uid) => events.push(Event::AssignLeader(uid)),
-            }
-        }
 
         // Spellbook
         if self.show.spell {
@@ -2675,3 +2726,12 @@ pub fn get_quality_col<I: ItemDesc>(item: &I) -> Color {
         Quality::Debug => QUALITY_DEBUG,
     }
 }
+// Get info about applied buffs
+fn get_buff_info(buff: &comp::Buff) -> BuffInfo {
+    BuffInfo {
+        kind: buff.kind,
+        data: buff.data,
+        is_buff: buff.kind.is_buff(),
+        dur: buff.time,
+    }
+}
diff --git a/voxygen/src/hud/overhead.rs b/voxygen/src/hud/overhead.rs
index a69bccbea6..7ebfb29cfc 100644
--- a/voxygen/src/hud/overhead.rs
+++ b/voxygen/src/hud/overhead.rs
@@ -1,14 +1,16 @@
 use super::{
     img_ids::Imgs, DEFAULT_NPC, FACTION_COLOR, GROUP_COLOR, GROUP_MEMBER, HP_COLOR, LOW_HP_COLOR,
-    MANA_COLOR, REGION_COLOR, SAY_COLOR, TELL_COLOR, TEXT_BG, TEXT_COLOR,
+    REGION_COLOR, SAY_COLOR, STAMINA_COLOR, TELL_COLOR, TEXT_BG, TEXT_COLOR,
 };
 use crate::{
+    hud::get_buff_info,
     i18n::VoxygenLocalization,
     settings::GameplaySettings,
     ui::{fonts::ConrodVoxygenFonts, Ingameable},
 };
-use common::comp::{Energy, SpeechBubble, SpeechBubbleType, Stats};
+use common::comp::{BuffKind, Buffs, Energy, SpeechBubble, SpeechBubbleType, Stats};
 use conrod_core::{
+    color,
     position::Align,
     widget::{self, Image, Rectangle, Text},
     widget_ids, Color, Colorable, Positionable, Sizeable, Widget, WidgetCommon,
@@ -44,6 +46,11 @@ widget_ids! {
         health_txt,
         mana_bar,
         health_bar_fg,
+
+        // Buffs
+        buffs_align,
+        buffs[],
+        buff_timers[],
     }
 }
 
@@ -51,6 +58,7 @@ widget_ids! {
 pub struct Info<'a> {
     pub name: &'a str,
     pub stats: &'a Stats,
+    pub buffs: &'a Buffs,
     pub energy: Option<&'a Energy>,
 }
 
@@ -119,17 +127,25 @@ impl<'a> Ingameable for Overhead<'a> {
         // - 1 for HP text
         // - If there's mana
         //   - 1 Rect::new for mana
-        //
+        // If there are Buffs
+        // - 1 Alignment Rectangle
+        // - 10 + 10 Buffs and Timer Overlays (only if there is no speech bubble)
         // If there's a speech bubble
         // - 2 Text::new for speech bubble
         // - 1 Image::new for icon
         // - 10 Image::new for speech bubble (9-slice + tail)
         self.info.map_or(0, |info| {
-            2 + if show_healthbar(info.stats) {
-                5 + if info.energy.is_some() { 1 } else { 0 }
-            } else {
-                0
-            }
+            2 + 1
+                + if self.bubble.is_none() {
+                    info.buffs.kinds.len().min(10) * 2
+                } else {
+                    0
+                }
+                + if show_healthbar(info.stats) {
+                    5 + if info.energy.is_some() { 1 } else { 0 }
+                } else {
+                    0
+                }
         }) + if self.bubble.is_some() { 13 } else { 0 }
     }
 }
@@ -155,6 +171,7 @@ impl<'a> Widget for Overhead<'a> {
         if let Some(Info {
             name,
             stats,
+            buffs,
             energy,
         }) = self.info
         {
@@ -185,6 +202,84 @@ impl<'a> Widget for Overhead<'a> {
                 1000..=999999 => format!("{:.0}K", (health_max / 1000.0).max(1.0)),
                 _ => format!("{:.0}M", (health_max as f64 / 1.0e6).max(1.0)),
             };
+            // Buffs
+            // Alignment
+            let buff_count = buffs.kinds.len().min(11);
+            Rectangle::fill_with([168.0, 100.0], color::TRANSPARENT)
+                .x_y(-1.0, name_y + 60.0)
+                .parent(id)
+                .set(state.ids.buffs_align, ui);
+
+            let gen = &mut ui.widget_id_generator();
+            if state.ids.buffs.len() < buff_count {
+                state.update(|state| state.ids.buffs.resize(buff_count, gen));
+            };
+            if state.ids.buff_timers.len() < buff_count {
+                state.update(|state| state.ids.buff_timers.resize(buff_count, gen));
+            };
+
+            let buff_ani = ((self.pulse * 4.0).cos() * 0.5 + 0.8) + 0.5; //Animation timer
+            let pulsating_col = Color::Rgba(1.0, 1.0, 1.0, buff_ani);
+            let norm_col = Color::Rgba(1.0, 1.0, 1.0, 1.0);
+            // Create Buff Widgets
+            if self.bubble.is_none() {
+                state
+                    .ids
+                    .buffs
+                    .iter()
+                    .copied()
+                    .zip(state.ids.buff_timers.iter().copied())
+                    .zip(buffs.iter_active().map(get_buff_info))
+                    .enumerate()
+                    .for_each(|(i, ((id, timer_id), buff))| {
+                        // Limit displayed buffs
+                        let max_duration = buff.data.duration;
+                        let current_duration = buff.dur;
+                        let duration_percentage = current_duration.map_or(1000.0, |cur| {
+                            max_duration.map_or(1000.0, |max| {
+                                cur.as_secs_f32() / max.as_secs_f32() * 1000.0
+                            })
+                        }) as u32; // Percentage to determine which frame of the timer overlay is displayed
+                        let buff_img = match buff.kind {
+                            BuffKind::Regeneration { .. } => self.imgs.buff_plus_0,
+                            BuffKind::Bleeding { .. } => self.imgs.debuff_bleed_0,
+                            BuffKind::Cursed { .. } => self.imgs.debuff_skull_0,
+                        };
+                        let buff_widget = Image::new(buff_img).w_h(20.0, 20.0);
+                        // Sort buffs into rows of 5 slots
+                        let x = i % 5;
+                        let y = i / 5;
+                        let buff_widget = buff_widget.bottom_left_with_margins_on(
+                            state.ids.buffs_align,
+                            0.0 + y as f64 * (21.0),
+                            0.0 + x as f64 * (21.0),
+                        );
+                        buff_widget
+                            .color(
+                                if current_duration.map_or(false, |cur| cur.as_secs_f32() < 10.0) {
+                                    Some(pulsating_col)
+                                } else {
+                                    Some(norm_col)
+                                },
+                            )
+                            .set(id, ui);
+
+                        Image::new(match duration_percentage as u64 {
+                            875..=1000 => self.imgs.nothing, // 8/8
+                            750..=874 => self.imgs.buff_0,   // 7/8
+                            625..=749 => self.imgs.buff_1,   // 6/8
+                            500..=624 => self.imgs.buff_2,   // 5/8
+                            375..=499 => self.imgs.buff_3,   // 4/8
+                            250..=374 => self.imgs.buff_4,   // 3/8
+                            125..=249 => self.imgs.buff_5,   // 2/8
+                            0..=124 => self.imgs.buff_6,     // 1/8
+                            _ => self.imgs.nothing,
+                        })
+                        .w_h(20.0, 20.0)
+                        .middle_of(id)
+                        .set(timer_id, ui);
+                    });
+            }
             // Name
             Text::new(name)
                 .font_id(self.fonts.cyri.conrod_id)
@@ -254,7 +349,7 @@ impl<'a> Widget for Overhead<'a> {
 
                     Rectangle::fill_with(
                         [72.0 * energy_factor * BARSIZE, MANA_BAR_HEIGHT],
-                        MANA_COLOR,
+                        STAMINA_COLOR,
                     )
                     .x_y(
                         ((3.5 + (energy_factor * 36.5)) - 36.45) * BARSIZE,
diff --git a/voxygen/src/hud/settings_window.rs b/voxygen/src/hud/settings_window.rs
index 6fb2473742..59f5a6f14b 100644
--- a/voxygen/src/hud/settings_window.rs
+++ b/voxygen/src/hud/settings_window.rs
@@ -1,9 +1,10 @@
 use super::{
-    img_ids::Imgs, BarNumbers, CrosshairType, PressBehavior, ShortcutNumbers, Show, XpBar,
-    CRITICAL_HP_COLOR, ERROR_COLOR, HP_COLOR, LOW_HP_COLOR, MANA_COLOR, MENU_BG,
+    img_ids::Imgs, BarNumbers, CrosshairType, PressBehavior, ShortcutNumbers, Show,
+    CRITICAL_HP_COLOR, ERROR_COLOR, HP_COLOR, LOW_HP_COLOR, MENU_BG, STAMINA_COLOR,
     TEXT_BIND_CONFLICT_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN,
 };
 use crate::{
+    hud::BuffPosition,
     i18n::{list_localizations, LanguageMetadata, VoxygenLocalization},
     render::{AaMode, CloudMode, FluidMode, LightingMode, RenderMode, ShadowMapMode, ShadowMode},
     ui::{fonts::ConrodVoxygenFonts, ImageSlider, ScaleMode, ToggleButton},
@@ -19,7 +20,6 @@ use conrod_core::{
 };
 use core::convert::TryFrom;
 
-use inline_tweak::*;
 use itertools::Itertools;
 use std::iter::once;
 use winit::monitor::VideoMode;
@@ -159,6 +159,7 @@ widget_ids! {
         sfx_volume_text,
         audio_device_list,
         audio_device_text,
+        //
         hotbar_title,
         bar_numbers_title,
         show_bar_numbers_none_button,
@@ -167,18 +168,20 @@ widget_ids! {
         show_bar_numbers_values_text,
         show_bar_numbers_percentage_button,
         show_bar_numbers_percentage_text,
+        //
         show_shortcuts_button,
         show_shortcuts_text,
-        show_xpbar_button,
-        show_xpbar_text,
-        show_bars_button,
-        show_bars_text,
-        placeholder,
+        buff_pos_bar_button,
+        buff_pos_bar_text,
+        buff_pos_map_button,
+        buff_pos_map_text,
+        //
         chat_transp_title,
         chat_transp_text,
         chat_transp_slider,
         chat_char_name_text,
         chat_char_name_button,
+        //
         sct_title,
         sct_show_text,
         sct_show_radio,
@@ -195,6 +198,7 @@ widget_ids! {
         sct_num_dur_text,
         sct_num_dur_slider,
         sct_num_dur_value,
+        //
         speech_bubble_text,
         speech_bubble_dark_mode_text,
         speech_bubble_dark_mode_button,
@@ -259,9 +263,9 @@ pub enum Event {
     ToggleHelp,
     ToggleDebug,
     ToggleTips(bool),
-    ToggleXpBar(XpBar),
     ToggleBarNumbers(BarNumbers),
     ToggleShortcutNumbers(ShortcutNumbers),
+    BuffPosition(BuffPosition),
     ChangeTab(SettingsTab),
     Close,
     AdjustMousePan(u32),
@@ -796,40 +800,6 @@ impl<'a> Widget for SettingsWindow<'a> {
                 .font_id(self.fonts.cyri.conrod_id)
                 .color(TEXT_COLOR)
                 .set(state.ids.hotbar_title, ui);
-            // Show xp bar
-            if Button::image(match self.global_state.settings.gameplay.xp_bar {
-                XpBar::Always => self.imgs.checkbox_checked,
-                XpBar::OnGain => self.imgs.checkbox,
-            })
-            .w_h(18.0, 18.0)
-            .hover_image(match self.global_state.settings.gameplay.xp_bar {
-                XpBar::Always => self.imgs.checkbox_checked_mo,
-                XpBar::OnGain => self.imgs.checkbox_mo,
-            })
-            .press_image(match self.global_state.settings.gameplay.xp_bar {
-                XpBar::Always => self.imgs.checkbox_checked,
-                XpBar::OnGain => self.imgs.checkbox_press,
-            })
-            .down_from(state.ids.hotbar_title, 8.0)
-            .set(state.ids.show_xpbar_button, ui)
-            .was_clicked()
-            {
-                match self.global_state.settings.gameplay.xp_bar {
-                    XpBar::Always => events.push(Event::ToggleXpBar(XpBar::OnGain)),
-                    XpBar::OnGain => events.push(Event::ToggleXpBar(XpBar::Always)),
-                }
-            }
-            Text::new(
-                &self
-                    .localized_strings
-                    .get("hud.settings.toggle_bar_experience"),
-            )
-            .right_from(state.ids.show_xpbar_button, 10.0)
-            .font_size(self.fonts.cyri.scale(14))
-            .font_id(self.fonts.cyri.conrod_id)
-            .graphics_for(state.ids.show_xpbar_button)
-            .color(TEXT_COLOR)
-            .set(state.ids.show_xpbar_text, ui);
             // Show Shortcut Numbers
             if Button::image(match self.global_state.settings.gameplay.shortcut_numbers {
                 ShortcutNumbers::On => self.imgs.checkbox_checked,
@@ -844,7 +814,7 @@ impl<'a> Widget for SettingsWindow<'a> {
                 ShortcutNumbers::On => self.imgs.checkbox_checked,
                 ShortcutNumbers::Off => self.imgs.checkbox_press,
             })
-            .down_from(state.ids.show_xpbar_button, 8.0)
+            .down_from(state.ids.hotbar_title, 8.0)
             .set(state.ids.show_shortcuts_button, ui)
             .was_clicked()
             {
@@ -864,11 +834,61 @@ impl<'a> Widget for SettingsWindow<'a> {
                 .graphics_for(state.ids.show_shortcuts_button)
                 .color(TEXT_COLOR)
                 .set(state.ids.show_shortcuts_text, ui);
-
-            Rectangle::fill_with([60.0 * 4.0, 1.0 * 4.0], color::TRANSPARENT)
-                .down_from(state.ids.show_shortcuts_text, 30.0)
-                .set(state.ids.placeholder, ui);
-
+            // Buff Position
+            // Buffs above skills
+            if Button::image(match self.global_state.settings.gameplay.buff_position {
+                BuffPosition::Bar => self.imgs.checkbox_checked,
+                BuffPosition::Map => self.imgs.checkbox,
+            })
+            .w_h(18.0, 18.0)
+            .hover_image(match self.global_state.settings.gameplay.buff_position {
+                BuffPosition::Bar => self.imgs.checkbox_checked_mo,
+                BuffPosition::Map => self.imgs.checkbox_mo,
+            })
+            .press_image(match self.global_state.settings.gameplay.buff_position {
+                BuffPosition::Bar => self.imgs.checkbox_checked,
+                BuffPosition::Map => self.imgs.checkbox_press,
+            })
+            .down_from(state.ids.show_shortcuts_button, 8.0)
+            .set(state.ids.buff_pos_bar_button, ui)
+            .was_clicked()
+            {
+                events.push(Event::BuffPosition(BuffPosition::Bar))
+            }
+            Text::new(&self.localized_strings.get("hud.settings.buffs_skillbar"))
+                .right_from(state.ids.buff_pos_bar_button, 10.0)
+                .font_size(self.fonts.cyri.scale(14))
+                .font_id(self.fonts.cyri.conrod_id)
+                .graphics_for(state.ids.show_shortcuts_button)
+                .color(TEXT_COLOR)
+                .set(state.ids.buff_pos_bar_text, ui);
+            // Buffs left from minimap
+            if Button::image(match self.global_state.settings.gameplay.buff_position {
+                BuffPosition::Map => self.imgs.checkbox_checked,
+                BuffPosition::Bar => self.imgs.checkbox,
+            })
+            .w_h(18.0, 18.0)
+            .hover_image(match self.global_state.settings.gameplay.buff_position {
+                BuffPosition::Map => self.imgs.checkbox_checked_mo,
+                BuffPosition::Bar => self.imgs.checkbox_mo,
+            })
+            .press_image(match self.global_state.settings.gameplay.buff_position {
+                BuffPosition::Map => self.imgs.checkbox_checked,
+                BuffPosition::Bar => self.imgs.checkbox_press,
+            })
+            .down_from(state.ids.buff_pos_bar_button, 8.0)
+            .set(state.ids.buff_pos_map_button, ui)
+            .was_clicked()
+            {
+                events.push(Event::BuffPosition(BuffPosition::Map))
+            }
+            Text::new(&self.localized_strings.get("hud.settings.buffs_mmap"))
+                .right_from(state.ids.buff_pos_map_button, 10.0)
+                .font_size(self.fonts.cyri.scale(14))
+                .font_id(self.fonts.cyri.conrod_id)
+                .graphics_for(state.ids.show_shortcuts_button)
+                .color(TEXT_COLOR)
+                .set(state.ids.buff_pos_map_text, ui);
             // Content Right Side
 
             /*Scrolling Combat text
@@ -1692,7 +1712,7 @@ impl<'a> Widget for SettingsWindow<'a> {
                 0..=14 => CRITICAL_HP_COLOR,
                 15..=29 => LOW_HP_COLOR,
                 30..=50 => HP_COLOR,
-                _ => MANA_COLOR,
+                _ => STAMINA_COLOR,
             };
             Text::new(&format!("FPS: {:.0}", self.fps))
                 .color(fps_col)
@@ -2688,8 +2708,8 @@ impl<'a> Widget for SettingsWindow<'a> {
                 });
             };
             for (i, language) in language_list.iter().enumerate() {
-                let button_w = tweak!(400.0);
-                let button_h = tweak!(50.0);
+                let button_w = 400.0;
+                let button_h = 50.0;
                 let button = Button::image(if selected_language == &language.language_identifier {
                     self.imgs.selection
                 } else {
@@ -2706,7 +2726,7 @@ impl<'a> Widget for SettingsWindow<'a> {
                     .hover_image(self.imgs.selection_hover)
                     .press_image(self.imgs.selection_press)
                     .label_color(TEXT_COLOR)
-                    .label_font_size(self.fonts.cyri.scale(tweak!(22)))
+                    .label_font_size(self.fonts.cyri.scale(22))
                     .label_font_id(self.fonts.cyri.conrod_id)
                     .label_y(conrod_core::position::Relative::Scalar(2.0))
                     .set(state.ids.language_list[i], ui)
diff --git a/voxygen/src/hud/skillbar.rs b/voxygen/src/hud/skillbar.rs
index 21e1aa2bd4..172671622e 100644
--- a/voxygen/src/hud/skillbar.rs
+++ b/voxygen/src/hud/skillbar.rs
@@ -2,8 +2,8 @@ use super::{
     hotbar,
     img_ids::{Imgs, ImgsRot},
     item_imgs::ItemImgs,
-    slots, BarNumbers, ShortcutNumbers, Show, XpBar, BLACK, CRITICAL_HP_COLOR, HP_COLOR,
-    LOW_HP_COLOR, MANA_COLOR, TEXT_COLOR, XP_COLOR,
+    slots, BarNumbers, ShortcutNumbers, Show, BLACK, CRITICAL_HP_COLOR, HP_COLOR, LOW_HP_COLOR,
+    STAMINA_COLOR, TEXT_COLOR, UI_HIGHLIGHT_0, UI_MAIN, XP_COLOR,
 };
 use crate::{
     i18n::VoxygenLocalization,
@@ -20,7 +20,7 @@ use common::comp::{
         tool::{Tool, ToolKind},
         Hands, ItemKind,
     },
-    CharacterState, ControllerInputs, Energy, Inventory, Loadout, Stats,
+    Energy, Inventory, Loadout, Stats,
 };
 use conrod_core::{
     color,
@@ -32,22 +32,45 @@ use vek::*;
 
 widget_ids! {
     struct Ids {
+        // Death message
         death_message_1,
         death_message_2,
         death_message_1_bg,
         death_message_2_bg,
-        level_text,
-        next_level_text,
-        xp_bar_mid,
-        xp_bar_mid_top,
-        xp_bar_left,
-        xp_bar_left_top,
-        xp_bar_right,
-        xp_bar_right_top,
-        xp_bar_filling,
-        xp_bar_filling_top,
-        hotbar_align,
-        xp_bar_subdivision,
+        death_bg,
+        // Level up message
+        level_up,
+        level_down,
+        level_align,
+        level_message,
+        level_message_bg,
+        // Hurt BG
+        hurt_bg,
+        // Skillbar
+        alignment,
+        bg,
+        frame,
+        m1_ico,
+        m2_ico,
+        // Level
+        level_bg,
+        level,
+        // Exp-Bar
+        exp_alignment,
+        exp_filling,
+        // HP-Bar
+        hp_alignment,
+        hp_filling,
+        hp_txt_alignment,
+        hp_txt_bg,
+        hp_txt,
+        // Stamina-Bar
+        stamina_alignment,
+        stamina_filling,
+        stamina_txt_alignment,
+        stamina_txt_bg,
+        stamina_txt,
+        // Slots
         m1_slot,
         m1_slot_bg,
         m1_text,
@@ -63,7 +86,6 @@ widget_ids! {
         slot1,
         slot1_text,
         slot1_text_bg,
-        //slot1_act,
         slot2,
         slot2_text,
         slot2_text_bg,
@@ -91,29 +113,9 @@ widget_ids! {
         slot10,
         slot10_text,
         slot10_text_bg,
-        healthbar_bg,
-        healthbar_filling,
-        health_text,
-        health_text_bg,
-        energybar_bg,
-        energybar_filling,
-        energy_text,
-        energy_text_bg,
-        level_up,
-        level_down,
-        level_align,
-        level_message,
-        level_message_bg,
-        death_bg,
-        hurt_bg,
     }
 }
 
-pub enum ResourceType {
-    Mana,
-    /*Rage,
-     *Focus, */
-}
 #[derive(WidgetCommon)]
 pub struct Skillbar<'a> {
     global_state: &'a GlobalState,
@@ -124,8 +126,8 @@ pub struct Skillbar<'a> {
     stats: &'a Stats,
     loadout: &'a Loadout,
     energy: &'a Energy,
-    character_state: &'a CharacterState,
-    controller: &'a ControllerInputs,
+    // character_state: &'a CharacterState,
+    // controller: &'a ControllerInputs,
     inventory: &'a Inventory,
     hotbar: &'a hotbar::State,
     tooltip_manager: &'a mut TooltipManager,
@@ -134,7 +136,6 @@ pub struct Skillbar<'a> {
     pulse: f32,
     #[conrod(common_builder)]
     common: widget::CommonBuilder,
-    current_resource: ResourceType,
     show: &'a Show,
 }
 
@@ -149,9 +150,9 @@ impl<'a> Skillbar<'a> {
         stats: &'a Stats,
         loadout: &'a Loadout,
         energy: &'a Energy,
-        character_state: &'a CharacterState,
+        // character_state: &'a CharacterState,
         pulse: f32,
-        controller: &'a ControllerInputs,
+        // controller: &'a ControllerInputs,
         inventory: &'a Inventory,
         hotbar: &'a hotbar::State,
         tooltip_manager: &'a mut TooltipManager,
@@ -168,11 +169,10 @@ impl<'a> Skillbar<'a> {
             stats,
             loadout,
             energy,
-            current_resource: ResourceType::Mana,
             common: widget::CommonBuilder::default(),
-            character_state,
+            // character_state,
             pulse,
-            controller,
+            // controller,
             inventory,
             hotbar,
             tooltip_manager,
@@ -185,10 +185,7 @@ impl<'a> Skillbar<'a> {
 
 pub struct State {
     ids: Ids,
-
-    last_xp_value: u32,
     last_level: u32,
-    last_update_xp: Instant,
     last_update_level: Instant,
 }
 
@@ -200,10 +197,7 @@ impl<'a> Widget for Skillbar<'a> {
     fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
         State {
             ids: Ids::new(id_gen),
-
-            last_xp_value: 0,
             last_level: 1,
-            last_update_xp: Instant::now(),
             last_update_level: Instant::now(),
         }
     }
@@ -214,8 +208,11 @@ impl<'a> Widget for Skillbar<'a> {
     fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
         let widget::UpdateArgs { state, ui, .. } = args;
 
-        let level = (self.stats.level.level()).to_string();
-        let next_level = (self.stats.level.level() + 1).to_string();
+        let level = if self.stats.level.level() > 999 {
+            "A".to_string()
+        } else {
+            (self.stats.level.level()).to_string()
+        };
 
         let exp_percentage = (self.stats.exp.current() as f64) / (self.stats.exp.maximum() as f64);
 
@@ -227,12 +224,10 @@ impl<'a> Widget for Skillbar<'a> {
             hp_percentage = 0.0;
             energy_percentage = 0.0;
         };
-        let scale = 2.0;
 
         let bar_values = self.global_state.settings.gameplay.bar_numbers;
         let shortcuts = self.global_state.settings.gameplay.shortcut_numbers;
 
-        const BG_COLOR_2: Color = Color::Rgba(0.0, 0.0, 0.0, 0.99);
         let hp_ani = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.8; //Animation timer
         let crit_hp_color: Color = Color::Rgba(0.79, 0.19, 0.17, hp_ani);
 
@@ -339,410 +334,147 @@ impl<'a> Widget for Skillbar<'a> {
                 .set(state.ids.death_message_2, ui);
             }
         }
-        // Experience-Bar
-        match self.global_state.settings.gameplay.xp_bar {
-            XpBar::Always => {
-                // Constant Display of the Exp Bar at the bottom of the screen
-                Image::new(self.imgs.xp_bar_mid)
-                    .w_h(80.0 * scale, 10.0 * scale)
-                    .mid_bottom_with_margin_on(ui.window, 2.0)
-                    .set(state.ids.xp_bar_mid, ui);
-                Image::new(self.imgs.xp_bar_right)
-                    .w_h(100.0 * scale, 10.0 * scale)
-                    .right_from(state.ids.xp_bar_mid, 0.0)
-                    .set(state.ids.xp_bar_right, ui);
-                Image::new(self.imgs.xp_bar_left)
-                    .w_h(100.0 * scale, 10.0 * scale)
-                    .left_from(state.ids.xp_bar_mid, 0.0)
-                    .set(state.ids.xp_bar_left, ui);
-                Image::new(self.imgs.bar_content)
-                    .w_h(260.0 * scale * exp_percentage, 5.0 * scale)
-                    .color(Some(XP_COLOR))
-                    .top_left_with_margins_on(state.ids.xp_bar_left, 2.0 * scale, 10.0 * scale)
-                    .set(state.ids.xp_bar_filling, ui);
-                // Level Display
-                if self.stats.level.level() < 10 {
-                    Text::new(&level)
-                        .bottom_left_with_margins_on(
-                            state.ids.xp_bar_left,
-                            3.5 * scale,
-                            4.0 * scale,
-                        )
-                        .font_size(self.fonts.cyri.scale(10))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
-                        .set(state.ids.level_text, ui);
-                    Text::new(&next_level)
-                        .bottom_right_with_margins_on(
-                            state.ids.xp_bar_right,
-                            3.5 * scale,
-                            4.0 * scale,
-                        )
-                        .font_size(self.fonts.cyri.scale(10))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
-                        .set(state.ids.next_level_text, ui);
-                } else if self.stats.level.level() < 100 {
-                    // Change offset and fontsize for levels > 9
-                    Text::new(&level)
-                        .bottom_left_with_margins_on(
-                            state.ids.xp_bar_left,
-                            3.5 * scale,
-                            3.0 * scale,
-                        )
-                        .font_size(self.fonts.cyri.scale(9))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
-                        .set(state.ids.level_text, ui);
-                    Text::new(&next_level)
-                        .bottom_right_with_margins_on(
-                            state.ids.xp_bar_right,
-                            3.5 * scale,
-                            3.0 * scale,
-                        )
-                        .font_size(self.fonts.cyri.scale(9))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
-                        .set(state.ids.next_level_text, ui);
-                } else {
-                    // Change offset and fontsize for levels > 9
-                    Text::new(&level)
-                        .bottom_left_with_margins_on(
-                            state.ids.xp_bar_left,
-                            3.5 * scale,
-                            2.5 * scale,
-                        )
-                        .font_size(self.fonts.cyri.scale(8))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
-                        .set(state.ids.level_text, ui);
-                    Text::new(&next_level)
-                        .bottom_right_with_margins_on(
-                            state.ids.xp_bar_right,
-                            3.5 * scale,
-                            2.5 * scale,
-                        )
-                        .font_size(self.fonts.cyri.scale(8))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, 1.0))
-                        .set(state.ids.next_level_text, ui);
-                }
-                // M1 Slot
-                Image::new(self.imgs.skillbar_slot_big)
-                    .w_h(40.0 * scale, 40.0 * scale)
-                    .top_left_with_margins_on(state.ids.xp_bar_mid, -40.0 * scale, 0.0)
-                    .set(state.ids.m1_slot, ui);
-            },
-            XpBar::OnGain => {
-                // Displays the Exp Bar at the top of the screen when exp is gained and fades it
-                // out afterwards
-                const FADE_IN_XP: f32 = 1.0;
-                const FADE_HOLD_XP: f32 = 3.0;
-                const FADE_OUT_XP: f32 = 2.0;
-                let current_xp = self.stats.exp.current();
-                // Check if no other popup is displayed and a new one is needed
-                if state.last_update_xp.elapsed()
-                    > Duration::from_secs_f32(FADE_IN_XP + FADE_HOLD_XP + FADE_OUT_XP)
-                    && state.last_xp_value != current_xp
-                {
-                    // Update last_value
-                    state.update(|s| s.last_xp_value = current_xp);
-                    state.update(|s| s.last_update_xp = Instant::now());
-                }
-
-                let seconds_xp = state.last_update_xp.elapsed().as_secs_f32();
-                let fade_xp = if current_xp == 0 {
-                    0.0
-                } else if seconds_xp < FADE_IN_XP {
-                    seconds_xp / FADE_IN_XP
-                } else if seconds_xp < FADE_IN_XP + FADE_HOLD_XP {
-                    1.0
-                } else {
-                    (1.0 - (seconds_xp - FADE_IN_XP - FADE_HOLD_XP) / FADE_OUT_XP).max(0.0)
-                };
-                // Hotbar parts
-                Image::new(self.imgs.xp_bar_mid)
-                    .w_h(80.0 * scale * 1.5, 10.0 * scale * 1.5)
-                    .mid_top_with_margin_on(ui.window, 20.0)
-                    .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_xp)))
-                    .set(state.ids.xp_bar_mid_top, ui);
-                Image::new(self.imgs.xp_bar_right)
-                    .w_h(100.0 * scale * 1.5, 10.0 * scale * 1.5)
-                    .right_from(state.ids.xp_bar_mid_top, 0.0)
-                    .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_xp)))
-                    .set(state.ids.xp_bar_right_top, ui);
-                Image::new(self.imgs.xp_bar_left)
-                    .w_h(100.0 * scale * 1.5, 10.0 * scale * 1.5)
-                    .left_from(state.ids.xp_bar_mid_top, 0.0)
-                    .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_xp)))
-                    .set(state.ids.xp_bar_left_top, ui);
-                Image::new(self.imgs.bar_content)
-                    .w_h(260.0 * scale * 1.5 * exp_percentage, 6.0 * scale * 1.5)
-                    .color(Some(Color::Rgba(0.59, 0.41, 0.67, fade_xp)))
-                    .top_left_with_margins_on(
-                        state.ids.xp_bar_left_top,
-                        2.0 * scale * 1.5,
-                        10.0 * scale * 1.5,
-                    )
-                    .set(state.ids.xp_bar_filling_top, ui);
-                // Level Display
-                if self.stats.level.level() < 10 {
-                    Text::new(&level)
-                        .bottom_left_with_margins_on(
-                            state.ids.xp_bar_left_top,
-                            3.0 * scale * 1.5,
-                            4.0 * scale * 1.5,
-                        )
-                        .font_size(self.fonts.cyri.scale(17))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
-                        .set(state.ids.level_text, ui);
-                    Text::new(&next_level)
-                        .bottom_right_with_margins_on(
-                            state.ids.xp_bar_right_top,
-                            3.0 * scale * 1.5,
-                            4.0 * scale * 1.5,
-                        )
-                        .font_size(self.fonts.cyri.scale(15))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
-                        .set(state.ids.next_level_text, ui);
-                } else if self.stats.level.level() < 100 {
-                    // Change offset and fontsize for levels > 9
-                    Text::new(&level)
-                        .bottom_left_with_margins_on(
-                            state.ids.xp_bar_left_top,
-                            3.0 * scale * 1.5,
-                            3.0 * scale * 1.5,
-                        )
-                        .font_size(self.fonts.cyri.scale(15))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
-                        .set(state.ids.level_text, ui);
-                    Text::new(&next_level)
-                        .bottom_right_with_margins_on(
-                            state.ids.xp_bar_right_top,
-                            3.0 * scale * 1.5,
-                            3.0 * scale * 1.5,
-                        )
-                        .font_size(self.fonts.cyri.scale(15))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
-                        .set(state.ids.next_level_text, ui);
-                } else {
-                    // Change offset and fontsize for levels > 9
-                    Text::new(&level)
-                        .bottom_left_with_margins_on(
-                            state.ids.xp_bar_left_top,
-                            3.0 * scale * 1.5,
-                            2.75 * scale * 1.5,
-                        )
-                        .font_size(self.fonts.cyri.scale(12))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
-                        .set(state.ids.level_text, ui);
-                    Text::new(&next_level)
-                        .bottom_right_with_margins_on(
-                            state.ids.xp_bar_right_top,
-                            3.0 * scale * 1.5,
-                            2.75 * scale * 1.5,
-                        )
-                        .font_size(self.fonts.cyri.scale(12))
-                        .font_id(self.fonts.cyri.conrod_id)
-                        .color(Color::Rgba(1.0, 1.0, 1.0, fade_xp))
-                        .set(state.ids.next_level_text, ui);
-                }
-                // Alignment for hotbar
-                Rectangle::fill_with([80.0 * scale, 1.0], color::TRANSPARENT)
-                    .mid_bottom_with_margin_on(ui.window, 9.0)
-                    .set(state.ids.hotbar_align, ui);
-                // M1 Slot
-
-                match self.character_state {
-                    CharacterState::BasicMelee { .. } => {
-                        if self.controller.primary.is_pressed() {
-                            let fade_pulse = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.6; //Animation timer;
-                            Image::new(self.imgs.skillbar_slot_big)
-                                .w_h(40.0 * scale, 40.0 * scale)
-                                .top_left_with_margins_on(
-                                    state.ids.hotbar_align,
-                                    -40.0 * scale,
-                                    0.0,
-                                )
-                                .set(state.ids.m1_slot, ui);
-                            Image::new(self.imgs.skillbar_slot_big_act)
-                                .w_h(40.0 * scale, 40.0 * scale)
-                                .middle_of(state.ids.m1_slot)
-                                .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_pulse)))
-                                .floating(true)
-                                .set(state.ids.m1_slot_act, ui);
-                        } else {
-                            Image::new(self.imgs.skillbar_slot_big)
-                                .w_h(40.0 * scale, 40.0 * scale)
-                                .top_left_with_margins_on(
-                                    state.ids.hotbar_align,
-                                    -40.0 * scale,
-                                    0.0,
-                                )
-                                .set(state.ids.m1_slot, ui);
-                        }
-                    },
-                    _ => {
-                        Image::new(self.imgs.skillbar_slot_big)
-                            .w_h(40.0 * scale, 40.0 * scale)
-                            .top_left_with_margins_on(state.ids.hotbar_align, -40.0 * scale, 0.0)
-                            .set(state.ids.m1_slot, ui);
-                    },
-                }
-            },
+        // Skillbar
+        // Alignment and BG
+        Rectangle::fill_with([524.0, 80.0], color::TRANSPARENT)
+            .mid_bottom_with_margin_on(ui.window, 10.0)
+            .set(state.ids.alignment, ui);
+        Image::new(self.imgs.skillbar_bg)
+            .w_h(480.0, 80.0)
+            .color(Some(UI_MAIN))
+            .middle_of(state.ids.alignment)
+            .set(state.ids.bg, ui);
+        // Level
+        let lvl_size = match self.stats.level.level() {
+            11..=99 => 13,
+            100..=999 => 10,
+            _ => 14,
+        };
+        Text::new(&level)
+            .mid_top_with_margin_on(state.ids.bg, 3.0)
+            .font_size(self.fonts.cyri.scale(lvl_size))
+            .font_id(self.fonts.cyri.conrod_id)
+            .color(TEXT_COLOR)
+            .set(state.ids.level, ui);
+        // Exp-Bar
+        Rectangle::fill_with([476.0, 8.0], color::TRANSPARENT)
+            .mid_bottom_with_margin_on(state.ids.bg, 4.0)
+            .set(state.ids.exp_alignment, ui);
+        Image::new(self.imgs.bar_content)
+            .w_h(476.0 * exp_percentage, 8.0)
+            .color(Some(XP_COLOR))
+            .bottom_left_with_margins_on(state.ids.exp_alignment, 0.0, 0.0)
+            .set(state.ids.exp_filling, ui);
+        // Health and Stamina bar
+        // Alignment
+        Rectangle::fill_with([240.0, 17.0], color::TRANSPARENT)
+            .top_left_with_margins_on(state.ids.alignment, 0.0, 0.0)
+            .set(state.ids.hp_alignment, ui);
+        Rectangle::fill_with([240.0, 17.0], color::TRANSPARENT)
+            .top_right_with_margins_on(state.ids.alignment, 0.0, 0.0)
+            .set(state.ids.stamina_alignment, ui);
+        let health_col = match hp_percentage as u8 {
+            0..=20 => crit_hp_color,
+            21..=40 => LOW_HP_COLOR,
+            _ => HP_COLOR,
+        };
+        // Content
+        Image::new(self.imgs.bar_content)
+            .w_h(216.0 * hp_percentage / 100.0, 14.0)
+            .color(Some(health_col))
+            .top_right_with_margins_on(state.ids.hp_alignment, 4.0, 0.0)
+            .set(state.ids.hp_filling, ui);
+        Image::new(self.imgs.bar_content)
+            .w_h(216.0 * energy_percentage / 100.0, 14.0)
+            .color(Some(STAMINA_COLOR))
+            .top_left_with_margins_on(state.ids.stamina_alignment, 4.0, 0.0)
+            .set(state.ids.stamina_filling, ui);
+        Rectangle::fill_with([219.0, 14.0], color::TRANSPARENT)
+            .top_left_with_margins_on(state.ids.hp_alignment, 4.0, 20.0)
+            .set(state.ids.hp_txt_alignment, ui);
+        Rectangle::fill_with([219.0, 14.0], color::TRANSPARENT)
+            .top_right_with_margins_on(state.ids.stamina_alignment, 4.0, 20.0)
+            .set(state.ids.stamina_txt_alignment, ui);
+        // Bar Text
+        // Values
+        if let BarNumbers::Values = bar_values {
+            let mut hp_txt = format!(
+                "{}/{}",
+                (self.stats.health.current() / 10).max(1) as u32, /* Don't show 0 health for
+                                                                   * living players */
+                (self.stats.health.maximum() / 10) as u32
+            );
+            let mut energy_txt = format!("{}", energy_percentage as u32);
+            if self.stats.is_dead {
+                hp_txt = self.localized_strings.get("hud.group.dead").to_string();
+                energy_txt = self.localized_strings.get("hud.group.dead").to_string();
+            };
+            Text::new(&hp_txt)
+                .middle_of(state.ids.hp_txt_alignment)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
+                .set(state.ids.hp_txt_bg, ui);
+            Text::new(&hp_txt)
+                .bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(TEXT_COLOR)
+                .set(state.ids.hp_txt, ui);
+            Text::new(&energy_txt)
+                .middle_of(state.ids.stamina_txt_alignment)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
+                .set(state.ids.stamina_txt_bg, ui);
+            Text::new(&energy_txt)
+                .bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(TEXT_COLOR)
+                .set(state.ids.stamina_txt, ui);
         }
-        // M1 Slot
-        Image::new(self.imgs.skillbar_slot_big_bg)
-            .w_h(38.0 * scale, 38.0 * scale)
-            .color(
-                match self.loadout.active_item.as_ref().map(|i| i.item.kind()) {
-                    Some(ItemKind::Tool(Tool { kind, .. })) => match kind {
-                        ToolKind::Bow(_) => Some(BG_COLOR_2),
-                        ToolKind::Staff(_) => Some(BG_COLOR_2),
-                        _ => Some(BG_COLOR_2),
-                    },
-                    _ => Some(BG_COLOR_2),
-                },
-            )
-            .middle_of(state.ids.m1_slot)
-            .set(state.ids.m1_slot_bg, ui);
-        Button::image(
-            match self.loadout.active_item.as_ref().map(|i| i.item.kind()) {
-                Some(ItemKind::Tool(Tool { kind, .. })) => match kind {
-                    ToolKind::Sword(_) => self.imgs.twohsword_m1,
-                    ToolKind::Dagger(_) => self.imgs.onehdagger_m1,
-                    ToolKind::Shield(_) => self.imgs.onehshield_m1,
-                    ToolKind::Hammer(_) => self.imgs.twohhammer_m1,
-                    ToolKind::Axe(_) => self.imgs.twohaxe_m1,
-                    ToolKind::Bow(_) => self.imgs.bow_m1,
-                    ToolKind::Sceptre(_) => self.imgs.heal_0,
-                    ToolKind::Staff(_) => self.imgs.fireball,
-                    ToolKind::Debug(kind) => match kind.as_ref() {
-                        "Boost" => self.imgs.flyingrod_m1,
-                        _ => self.imgs.nothing,
-                    },
-                    _ => self.imgs.nothing,
-                },
-                _ => self.imgs.nothing,
-            },
-        ) // Insert Icon here
-        .w_h(32.0 * scale, 32.0 * scale)
-        .middle_of(state.ids.m1_slot_bg)
-        .set(state.ids.m1_content, ui);
-        // M2 Slot
-        match self.character_state {
-            CharacterState::BasicMelee { .. } => {
-                let fade_pulse = (self.pulse * 4.0/* speed factor */).cos() * 0.5 + 0.6; //Animation timer;
-                if self.controller.secondary.is_pressed() {
-                    Image::new(self.imgs.skillbar_slot_big)
-                        .w_h(40.0 * scale, 40.0 * scale)
-                        .right_from(state.ids.m1_slot, 0.0)
-                        .set(state.ids.m2_slot, ui);
-                    Image::new(self.imgs.skillbar_slot_big_act)
-                        .w_h(40.0 * scale, 40.0 * scale)
-                        .middle_of(state.ids.m2_slot)
-                        .color(Some(Color::Rgba(1.0, 1.0, 1.0, fade_pulse)))
-                        .floating(true)
-                        .set(state.ids.m2_slot_act, ui);
-                } else {
-                    Image::new(self.imgs.skillbar_slot_big)
-                        .w_h(40.0 * scale, 40.0 * scale)
-                        .right_from(state.ids.m1_slot, 0.0)
-                        .set(state.ids.m2_slot, ui);
-                }
-            },
-            _ => {
-                Image::new(self.imgs.skillbar_slot_big)
-                    .w_h(40.0 * scale, 40.0 * scale)
-                    .right_from(state.ids.m1_slot, 0.0)
-                    .set(state.ids.m2_slot, ui);
-            },
+        //Percentages
+        if let BarNumbers::Percent = bar_values {
+            let mut hp_txt = format!("{}%", hp_percentage as u32);
+            let mut energy_txt = format!("{}", energy_percentage as u32);
+            if self.stats.is_dead {
+                hp_txt = self.localized_strings.get("hud.group.dead").to_string();
+                energy_txt = self.localized_strings.get("hud.group.dead").to_string();
+            };
+            Text::new(&hp_txt)
+                .middle_of(state.ids.hp_txt_alignment)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
+                .set(state.ids.hp_txt_bg, ui);
+            Text::new(&hp_txt)
+                .bottom_left_with_margins_on(state.ids.hp_txt_bg, 2.0, 2.0)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(TEXT_COLOR)
+                .set(state.ids.hp_txt, ui);
+            Text::new(&energy_txt)
+                .middle_of(state.ids.stamina_txt_alignment)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
+                .set(state.ids.stamina_txt_bg, ui);
+            Text::new(&energy_txt)
+                .bottom_left_with_margins_on(state.ids.stamina_txt_bg, 2.0, 2.0)
+                .font_size(self.fonts.cyri.scale(12))
+                .font_id(self.fonts.cyri.conrod_id)
+                .color(TEXT_COLOR)
+                .set(state.ids.stamina_txt, ui);
         }
-
-        let active_tool_kind = match self.loadout.active_item.as_ref().map(|i| i.item.kind()) {
-            Some(ItemKind::Tool(Tool { kind, .. })) => Some(kind),
-            _ => None,
-        };
-
-        let second_tool_kind = match self.loadout.second_item.as_ref().map(|i| i.item.kind()) {
-            Some(ItemKind::Tool(Tool { kind, .. })) => Some(kind),
-            _ => None,
-        };
-
-        let tool_kind = match (
-            active_tool_kind.map(|tk| tk.hands()),
-            second_tool_kind.map(|tk| tk.hands()),
-        ) {
-            (Some(Hands::TwoHand), _) => active_tool_kind,
-            (_, Some(Hands::OneHand)) => second_tool_kind,
-            (_, _) => None,
-        };
-
-        Image::new(self.imgs.skillbar_slot_big_bg)
-            .w_h(38.0 * scale, 38.0 * scale)
-            .color(match tool_kind {
-                Some(ToolKind::Bow(_)) => Some(BG_COLOR_2),
-                Some(ToolKind::Staff(_)) => Some(BG_COLOR_2),
-                _ => Some(BG_COLOR_2),
-            })
-            .middle_of(state.ids.m2_slot)
-            .set(state.ids.m2_slot_bg, ui);
-        Button::image(match tool_kind {
-            Some(ToolKind::Sword(_)) => self.imgs.twohsword_m2,
-            Some(ToolKind::Dagger(_)) => self.imgs.onehdagger_m2,
-            Some(ToolKind::Shield(_)) => self.imgs.onehshield_m2,
-            Some(ToolKind::Hammer(_)) => self.imgs.hammergolf,
-            Some(ToolKind::Axe(_)) => self.imgs.axespin,
-            Some(ToolKind::Bow(_)) => self.imgs.bow_m2,
-            Some(ToolKind::Sceptre(_)) => self.imgs.heal_bomb,
-            Some(ToolKind::Staff(_)) => self.imgs.flamethrower,
-            Some(ToolKind::Debug(kind)) => match kind.as_ref() {
-                "Boost" => self.imgs.flyingrod_m2,
-                _ => self.imgs.nothing,
-            },
-            _ => self.imgs.nothing,
-        })
-        .w_h(32.0 * scale, 32.0 * scale)
-        .middle_of(state.ids.m2_slot_bg)
-        .image_color(match tool_kind {
-            Some(ToolKind::Sword(_)) => {
-                if self.energy.current() as f64 >= 200.0 {
-                    Color::Rgba(1.0, 1.0, 1.0, 1.0)
-                } else {
-                    Color::Rgba(0.3, 0.3, 0.3, 0.8)
-                }
-            },
-            Some(ToolKind::Sceptre(_)) => {
-                if self.energy.current() as f64 >= 400.0 {
-                    Color::Rgba(1.0, 1.0, 1.0, 1.0)
-                } else {
-                    Color::Rgba(0.3, 0.3, 0.3, 0.8)
-                }
-            },
-            Some(ToolKind::Axe(_)) => {
-                if self.energy.current() as f64 >= 100.0 {
-                    Color::Rgba(1.0, 1.0, 1.0, 1.0)
-                } else {
-                    Color::Rgba(0.3, 0.3, 0.3, 0.8)
-                }
-            },
-            _ => Color::Rgba(1.0, 1.0, 1.0, 1.0),
-        })
-        .set(state.ids.m2_content, ui);
         // Slots
         let content_source = (self.hotbar, self.inventory, self.loadout, self.energy); // TODO: avoid this
         let image_source = (self.item_imgs, self.imgs);
-
         let mut slot_maker = SlotMaker {
             // TODO: is a separate image needed for the frame?
-            empty_slot: self.imgs.skillbar_slot,
-            filled_slot: self.imgs.skillbar_slot,
-            selected_slot: self.imgs.skillbar_slot_act,
+            empty_slot: self.imgs.inv_slot,
+            filled_slot: self.imgs.inv_slot,
+            selected_slot: self.imgs.inv_slot_sel,
             background_color: None,
             content_size: ContentSize {
                 width_height_ratio: 1.0,
@@ -792,14 +524,6 @@ impl<'a> Widget for Skillbar<'a> {
                         .map(|i| i.item.kind())
                         .and_then(|kind| match kind {
                             ItemKind::Tool(Tool { kind, .. }) => match kind {
-                                ToolKind::Hammer(_) => Some((
-                                    "Smash of Doom",
-                                    "\nAn AOE attack with knockback. \nLeaps to position of \
-                                     cursor.",
-                                )),
-                                ToolKind::Axe(_) => {
-                                    Some(("Spin Leap", "\nA slashing running spin leap."))
-                                },
                                 ToolKind::Staff(_) => Some((
                                     "Firebomb",
                                     "\nWhirls a big fireball into the air. \nExplodes the ground \
@@ -809,10 +533,6 @@ impl<'a> Widget for Skillbar<'a> {
                                     "Whirlwind",
                                     "\nMove forward while spinning with \n your sword.",
                                 )),
-                                ToolKind::Bow(_) => Some((
-                                    "Burst",
-                                    "\nLaunches a burst of arrows at the top \nof a running leap.",
-                                )),
                                 ToolKind::Debug(kind) => match kind.as_ref() {
                                     "Boost" => Some((
                                         "Possessing Arrow",
@@ -827,71 +547,172 @@ impl<'a> Widget for Skillbar<'a> {
                         }),
                 })
         };
-
-        //Slot 5
-        let slot = slot_maker
-            .fabricate(hotbar::Slot::Five, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
-            .bottom_left_with_margins_on(state.ids.m1_slot, 0.0, -20.0 * scale);
-        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Five) {
-            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
-                .set(state.ids.slot5, ui);
-        } else {
-            slot.set(state.ids.slot5, ui);
-        }
-        // Slot 4
-        let slot = slot_maker
-            .fabricate(hotbar::Slot::Four, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
-            .left_from(state.ids.slot5, 0.0);
-        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Four) {
-            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
-                .set(state.ids.slot4, ui);
-        } else {
-            slot.set(state.ids.slot4, ui);
-        }
-        // Slot 3
-        let slot = slot_maker
-            .fabricate(hotbar::Slot::Three, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
-            .left_from(state.ids.slot4, 0.0);
-        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) {
-            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
-                .set(state.ids.slot3, ui);
-        } else {
-            slot.set(state.ids.slot3, ui);
-        }
-        // Slot 2
-        let slot = slot_maker
-            .fabricate(hotbar::Slot::Two, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
-            .left_from(state.ids.slot3, 0.0);
-        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Two) {
-            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
-                .set(state.ids.slot2, ui);
-        } else {
-            slot.set(state.ids.slot2, ui);
-        }
+        // Slot 1-5
         // Slot 1
-        slot_maker.empty_slot = self.imgs.skillbar_slot_l;
-        slot_maker.selected_slot = self.imgs.skillbar_slot_l_act;
+        slot_maker.empty_slot = self.imgs.inv_slot;
+        slot_maker.selected_slot = self.imgs.inv_slot;
         let slot = slot_maker
-            .fabricate(hotbar::Slot::One, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot_l)
-            .left_from(state.ids.slot2, 0.0);
+            .fabricate(hotbar::Slot::One, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
+            .bottom_left_with_margins_on(state.ids.frame, 15.0, 22.0);
         if let Some((title, desc)) = tooltip_text(hotbar::Slot::One) {
             slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
                 .set(state.ids.slot1, ui);
         } else {
             slot.set(state.ids.slot1, ui);
         }
-        // Slot 6
-        slot_maker.empty_slot = self.imgs.skillbar_slot;
-        slot_maker.selected_slot = self.imgs.skillbar_slot_act;
+        // Slot 2
         let slot = slot_maker
-            .fabricate(hotbar::Slot::Six, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
-            .bottom_right_with_margins_on(state.ids.m2_slot, 0.0, -20.0 * scale);
+            .fabricate(hotbar::Slot::Two, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
+            .right_from(state.ids.slot1, 0.0);
+        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Two) {
+            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
+                .set(state.ids.slot2, ui);
+        } else {
+            slot.set(state.ids.slot2, ui);
+        }
+        // Slot 3
+        let slot = slot_maker
+            .fabricate(hotbar::Slot::Three, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
+            .right_from(state.ids.slot2, 0.0);
+        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) {
+            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
+                .set(state.ids.slot3, ui);
+        } else {
+            slot.set(state.ids.slot3, ui);
+        }
+        // Slot 4
+        let slot = slot_maker
+            .fabricate(hotbar::Slot::Four, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
+            .right_from(state.ids.slot3, 0.0);
+        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) {
+            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
+                .set(state.ids.slot4, ui);
+        } else {
+            slot.set(state.ids.slot4, ui);
+        }
+        // Slot 5
+        let slot = slot_maker
+            .fabricate(hotbar::Slot::Five, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
+            .right_from(state.ids.slot4, 0.0);
+        if let Some((title, desc)) = tooltip_text(hotbar::Slot::Three) {
+            slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
+                .set(state.ids.slot5, ui);
+        } else {
+            slot.set(state.ids.slot5, ui);
+        }
+        // Slot M1
+        Image::new(self.imgs.inv_slot)
+            .w_h(40.0, 40.0)
+            .right_from(state.ids.slot5, 0.0)
+            .set(state.ids.m1_slot_bg, ui);
+        Button::image(
+            match self.loadout.active_item.as_ref().map(|i| i.item.kind()) {
+                Some(ItemKind::Tool(Tool { kind, .. })) => match kind {
+                    ToolKind::Sword(_) => self.imgs.twohsword_m1,
+                    ToolKind::Dagger(_) => self.imgs.onehdagger_m1,
+                    ToolKind::Shield(_) => self.imgs.onehshield_m1,
+                    ToolKind::Hammer(_) => self.imgs.twohhammer_m1,
+                    ToolKind::Axe(_) => self.imgs.twohaxe_m1,
+                    ToolKind::Bow(_) => self.imgs.bow_m1,
+                    ToolKind::Sceptre(_) => self.imgs.heal_0,
+                    ToolKind::Staff(_) => self.imgs.fireball,
+                    ToolKind::Debug(kind) => match kind.as_ref() {
+                        "Boost" => self.imgs.flyingrod_m1,
+                        _ => self.imgs.nothing,
+                    },
+                    _ => self.imgs.nothing,
+                },
+                _ => self.imgs.nothing,
+            },
+        ) // Insert Icon here
+        .w_h(36.0, 36.0)
+        .middle_of(state.ids.m1_slot_bg)
+        .set(state.ids.m1_content, ui);
+        // Slot M2
+        Image::new(self.imgs.inv_slot)
+            .w_h(40.0, 40.0)
+            .right_from(state.ids.m1_slot_bg, 0.0)
+            .set(state.ids.m2_slot, ui);
+
+        let active_tool_kind = match self.loadout.active_item.as_ref().map(|i| i.item.kind()) {
+            Some(ItemKind::Tool(Tool { kind, .. })) => Some(kind),
+            _ => None,
+        };
+
+        let second_tool_kind = match self.loadout.second_item.as_ref().map(|i| i.item.kind()) {
+            Some(ItemKind::Tool(Tool { kind, .. })) => Some(kind),
+            _ => None,
+        };
+
+        let tool_kind = match (
+            active_tool_kind.map(|tk| tk.hands()),
+            second_tool_kind.map(|tk| tk.hands()),
+        ) {
+            (Some(Hands::TwoHand), _) => active_tool_kind,
+            (_, Some(Hands::OneHand)) => second_tool_kind,
+            (_, _) => None,
+        };
+
+        Image::new(self.imgs.inv_slot)
+            .w_h(40.0, 40.0)
+            .middle_of(state.ids.m2_slot)
+            .set(state.ids.m2_slot_bg, ui);
+        Button::image(match tool_kind {
+            Some(ToolKind::Sword(_)) => self.imgs.twohsword_m2,
+            Some(ToolKind::Dagger(_)) => self.imgs.onehdagger_m2,
+            Some(ToolKind::Shield(_)) => self.imgs.onehshield_m2,
+            Some(ToolKind::Hammer(_)) => self.imgs.hammergolf,
+            Some(ToolKind::Axe(_)) => self.imgs.axespin,
+            Some(ToolKind::Bow(_)) => self.imgs.bow_m2,
+            Some(ToolKind::Sceptre(_)) => self.imgs.heal_bomb,
+            Some(ToolKind::Staff(_)) => self.imgs.flamethrower,
+            Some(ToolKind::Debug(kind)) => match kind.as_ref() {
+                "Boost" => self.imgs.flyingrod_m2,
+                _ => self.imgs.nothing,
+            },
+            _ => self.imgs.nothing,
+        })
+        .w_h(36.0, 36.0)
+        .middle_of(state.ids.m2_slot_bg)
+        .image_color(match tool_kind {
+            // TODO Automate this to grey out unavailable M2 skills
+            Some(ToolKind::Sword(_)) => {
+                if self.energy.current() as f64 >= 200.0 {
+                    Color::Rgba(1.0, 1.0, 1.0, 1.0)
+                } else {
+                    Color::Rgba(0.3, 0.3, 0.3, 0.8)
+                }
+            },
+            Some(ToolKind::Sceptre(_)) => {
+                if self.energy.current() as f64 >= 400.0 {
+                    Color::Rgba(1.0, 1.0, 1.0, 1.0)
+                } else {
+                    Color::Rgba(0.3, 0.3, 0.3, 0.8)
+                }
+            },
+            Some(ToolKind::Axe(_)) => {
+                if self.energy.current() as f64 >= 100.0 {
+                    Color::Rgba(1.0, 1.0, 1.0, 1.0)
+                } else {
+                    Color::Rgba(0.3, 0.3, 0.3, 0.8)
+                }
+            },
+            _ => Color::Rgba(1.0, 1.0, 1.0, 1.0),
+        })
+        .set(state.ids.m2_content, ui);
+        // Slot 6-10
+        // Slot 6
+        slot_maker.empty_slot = self.imgs.inv_slot;
+        slot_maker.selected_slot = self.imgs.inv_slot;
+        let slot = slot_maker
+            .fabricate(hotbar::Slot::Six, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
+            .right_from(state.ids.m2_slot_bg, 0.0);
         if let Some((title, desc)) = tooltip_text(hotbar::Slot::Six) {
             slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
                 .set(state.ids.slot6, ui);
@@ -900,8 +721,8 @@ impl<'a> Widget for Skillbar<'a> {
         }
         // Slot 7
         let slot = slot_maker
-            .fabricate(hotbar::Slot::Seven, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
+            .fabricate(hotbar::Slot::Seven, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
             .right_from(state.ids.slot6, 0.0);
         if let Some((title, desc)) = tooltip_text(hotbar::Slot::Seven) {
             slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
@@ -911,8 +732,8 @@ impl<'a> Widget for Skillbar<'a> {
         }
         // Slot 8
         let slot = slot_maker
-            .fabricate(hotbar::Slot::Eight, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
+            .fabricate(hotbar::Slot::Eight, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
             .right_from(state.ids.slot7, 0.0);
         if let Some((title, desc)) = tooltip_text(hotbar::Slot::Eight) {
             slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
@@ -922,8 +743,8 @@ impl<'a> Widget for Skillbar<'a> {
         }
         // Slot 9
         let slot = slot_maker
-            .fabricate(hotbar::Slot::Nine, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot)
+            .fabricate(hotbar::Slot::Nine, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
             .right_from(state.ids.slot8, 0.0);
         if let Some((title, desc)) = tooltip_text(hotbar::Slot::Nine) {
             slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
@@ -932,11 +753,11 @@ impl<'a> Widget for Skillbar<'a> {
             slot.set(state.ids.slot9, ui);
         }
         // Quickslot
-        slot_maker.empty_slot = self.imgs.skillbar_slot_r;
-        slot_maker.selected_slot = self.imgs.skillbar_slot_r_act;
+        slot_maker.empty_slot = self.imgs.inv_slot;
+        slot_maker.selected_slot = self.imgs.inv_slot;
         let slot = slot_maker
-            .fabricate(hotbar::Slot::Ten, [20.0 * scale as f32; 2])
-            .filled_slot(self.imgs.skillbar_slot_r)
+            .fabricate(hotbar::Slot::Ten, [40.0; 2])
+            .filled_slot(self.imgs.inv_slot)
             .right_from(state.ids.slot9, 0.0);
         if let Some((title, desc)) = tooltip_text(hotbar::Slot::Ten) {
             slot.with_tooltip(self.tooltip_manager, title, desc, &item_tooltip, TEXT_COLOR)
@@ -1042,7 +863,7 @@ impl<'a> Widget for Skillbar<'a> {
                     .color(TEXT_COLOR)
                     .set(state.ids.slot5_text, ui);
             }
-            if let Some(m1) = &self
+            /*if let Some(m1) = &self
                 .global_state
                 .settings
                 .controls
@@ -1079,7 +900,7 @@ impl<'a> Widget for Skillbar<'a> {
                     .font_id(self.fonts.cyri.conrod_id)
                     .color(TEXT_COLOR)
                     .set(state.ids.m2_text, ui);
-            }
+            }*/
             if let Some(slot6) = &self
                 .global_state
                 .settings
@@ -1176,114 +997,22 @@ impl<'a> Widget for Skillbar<'a> {
                     .set(state.ids.slot10_text, ui);
             }
         };
-
-        // Lifebar
-        Image::new(self.imgs.healthbar_bg)
-            .w_h(100.0 * scale, 20.0 * scale)
-            .top_left_with_margins_on(state.ids.m1_slot, 0.0, -100.0 * scale)
-            .set(state.ids.healthbar_bg, ui);
-        let health_col = match hp_percentage as u8 {
-            0..=20 => crit_hp_color,
-            21..=40 => LOW_HP_COLOR,
-            _ => HP_COLOR,
-        };
-        Image::new(self.imgs.bar_content)
-            .w_h(97.0 * scale * hp_percentage / 100.0, 16.0 * scale)
-            .color(Some(health_col))
-            .top_right_with_margins_on(state.ids.healthbar_bg, 2.0 * scale, 1.0 * scale)
-            .set(state.ids.healthbar_filling, ui);
-        // Energybar
-        Image::new(self.imgs.energybar_bg)
-            .w_h(100.0 * scale, 20.0 * scale)
-            .top_right_with_margins_on(state.ids.m2_slot, 0.0, -100.0 * scale)
-            .set(state.ids.energybar_bg, ui);
-        Image::new(self.imgs.bar_content)
-            .w_h(97.0 * scale * energy_percentage / 100.0, 16.0 * scale)
-            .top_left_with_margins_on(state.ids.energybar_bg, 2.0 * scale, 1.0 * scale)
-            .color(Some(match self.current_resource {
-                ResourceType::Mana => MANA_COLOR,
-                /*ResourceType::Focus => FOCUS_COLOR,
-                 *ResourceType::Rage => RAGE_COLOR, */
-            }))
-            .set(state.ids.energybar_filling, ui);
-        // Bar Text
-        // Values
-        if let BarNumbers::Values = bar_values {
-            let mut hp_text = format!(
-                "{}/{}",
-                (self.stats.health.current() / 10).max(1) as u32, /* Don't show 0 health for
-                                                                   * living players */
-                (self.stats.health.maximum() / 10) as u32
-            );
-            let mut energy_text = format!(
-                "{}/{}",
-                self.energy.current() as u32 / 10, /* TODO Fix regeneration with smaller energy
-                                                    * numbers instead of dividing by 10 here */
-                self.energy.maximum() as u32 / 10
-            );
-            if self.stats.is_dead {
-                hp_text = self.localized_strings.get("hud.group.dead").to_string();
-                energy_text = self.localized_strings.get("hud.group.dead").to_string();
-            };
-            Text::new(&hp_text)
-                .mid_top_with_margin_on(state.ids.healthbar_bg, 6.0 * scale)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
-                .set(state.ids.health_text_bg, ui);
-            Text::new(&hp_text)
-                .bottom_left_with_margins_on(state.ids.health_text_bg, 2.0, 2.0)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(TEXT_COLOR)
-                .set(state.ids.health_text, ui);
-            Text::new(&energy_text)
-                .mid_top_with_margin_on(state.ids.energybar_bg, 6.0 * scale)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
-                .set(state.ids.energy_text_bg, ui);
-            Text::new(&energy_text)
-                .bottom_left_with_margins_on(state.ids.energy_text_bg, 2.0, 2.0)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(TEXT_COLOR)
-                .set(state.ids.energy_text, ui);
-        }
-        //Percentages
-        if let BarNumbers::Percent = bar_values {
-            let hp_text = format!("{}%", hp_percentage as u32);
-            Text::new(&hp_text)
-                .mid_top_with_margin_on(state.ids.healthbar_bg, 6.0 * scale)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
-                .set(state.ids.health_text_bg, ui);
-            Text::new(&hp_text)
-                .bottom_left_with_margins_on(state.ids.health_text_bg, 2.0, 2.0)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(TEXT_COLOR)
-                .set(state.ids.health_text, ui);
-            let energy_text = format!("{}%", energy_percentage as u32);
-            Text::new(&energy_text)
-                .mid_top_with_margin_on(state.ids.energybar_bg, 6.0 * scale)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(Color::Rgba(0.0, 0.0, 0.0, 1.0))
-                .set(state.ids.energy_text_bg, ui);
-            Text::new(&energy_text)
-                .bottom_left_with_margins_on(state.ids.energy_text_bg, 2.0, 2.0)
-                .font_size(self.fonts.cyri.scale(14))
-                .font_id(self.fonts.cyri.conrod_id)
-                .color(TEXT_COLOR)
-                .set(state.ids.energy_text, ui);
-        }
+        // Frame
+        Image::new(self.imgs.skillbar_frame)
+            .w_h(524.0, 80.0)
+            .color(Some(UI_HIGHLIGHT_0))
+            .middle_of(state.ids.bg)
+            .floating(true)
+            .set(state.ids.frame, ui);
+        // M1 and M2 icons
+        // TODO Don't show this if key bindings are changed
+        Image::new(self.imgs.m1_ico)
+            .w_h(16.0, 18.0)
+            .mid_bottom_with_margin_on(state.ids.m1_content, -11.0)
+            .set(state.ids.m1_ico, ui);
+        Image::new(self.imgs.m2_ico)
+            .w_h(16.0, 18.0)
+            .mid_bottom_with_margin_on(state.ids.m2_content, -11.0)
+            .set(state.ids.m2_ico, ui);
     }
-
-    // Buffs
-    // Add debuff slots above the health bar
-    // Add buff slots above the mana bar
-
-    // Debuffs
 }
diff --git a/voxygen/src/menu/main/ui.rs b/voxygen/src/menu/main/ui.rs
index 81355d8996..8ce9fb4fcb 100644
--- a/voxygen/src/menu/main/ui.rs
+++ b/voxygen/src/menu/main/ui.rs
@@ -18,7 +18,6 @@ use conrod_core::{
     widget_ids, Borderable, Color, Colorable, Labelable, Positionable, Sizeable, Widget,
 };
 use image::DynamicImage;
-//use inline_tweak::*;
 use rand::{seq::SliceRandom, thread_rng, Rng};
 use std::time::Duration;
 
diff --git a/voxygen/src/session.rs b/voxygen/src/session.rs
index 9d752aeed3..d0b3d3a8c9 100644
--- a/voxygen/src/session.rs
+++ b/voxygen/src/session.rs
@@ -894,6 +894,10 @@ impl PlayState for SessionState {
                         global_state.settings.gameplay.shortcut_numbers = shortcut_numbers;
                         global_state.settings.save_to_file_warn();
                     },
+                    HudEvent::BuffPosition(buff_position) => {
+                        global_state.settings.gameplay.buff_position = buff_position;
+                        global_state.settings.save_to_file_warn();
+                    },
                     HudEvent::UiScale(scale_change) => {
                         global_state.settings.gameplay.ui_scale =
                             self.hud.scale_change(scale_change);
@@ -921,6 +925,10 @@ impl PlayState for SessionState {
                         global_state.settings.graphics.max_fps = fps;
                         global_state.settings.save_to_file_warn();
                     },
+                    HudEvent::RemoveBuff(buff_id) => {
+                        let mut client = self.client.borrow_mut();
+                        client.remove_buff(buff_id);
+                    },
                     HudEvent::UseSlot(x) => self.client.borrow_mut().use_slot(x),
                     HudEvent::SwapSlots(a, b) => self.client.borrow_mut().swap_slots(a, b),
                     HudEvent::DropSlot(x) => {
diff --git a/voxygen/src/settings.rs b/voxygen/src/settings.rs
index be4eed60db..1f65e800de 100644
--- a/voxygen/src/settings.rs
+++ b/voxygen/src/settings.rs
@@ -1,5 +1,5 @@
 use crate::{
-    hud::{BarNumbers, CrosshairType, Intro, PressBehavior, ShortcutNumbers, XpBar},
+    hud::{BarNumbers, BuffPosition, CrosshairType, Intro, PressBehavior, ShortcutNumbers, XpBar},
     i18n,
     render::RenderMode,
     ui::ScaleMode,
@@ -507,6 +507,7 @@ pub struct GameplaySettings {
     pub intro_show: Intro,
     pub xp_bar: XpBar,
     pub shortcut_numbers: ShortcutNumbers,
+    pub buff_position: BuffPosition,
     pub bar_numbers: BarNumbers,
     pub ui_scale: ScaleMode,
     pub free_look_behavior: PressBehavior,
@@ -537,6 +538,7 @@ impl Default for GameplaySettings {
             intro_show: Intro::Show,
             xp_bar: XpBar::Always,
             shortcut_numbers: ShortcutNumbers::On,
+            buff_position: BuffPosition::Map,
             bar_numbers: BarNumbers::Values,
             ui_scale: ScaleMode::RelativeToWindow([1920.0, 1080.0].into()),
             free_look_behavior: PressBehavior::Toggle,