Merge branch 'master' into samual/weapons
authorRudolf Polzer <divverent@xonotic.org>
Thu, 16 Oct 2014 09:50:07 +0000 (11:50 +0200)
committerRudolf Polzer <divverent@xonotic.org>
Thu, 16 Oct 2014 09:50:07 +0000 (11:50 +0200)
Conflicts:
qcsrc/client/hud.qc

1  2 
qcsrc/client/autocvars.qh
qcsrc/client/hud.qc

@@@ -62,9 -62,8 +62,9 @@@ float autocvar_cl_particles_quality
  float autocvar_cl_projectiles_sloppy;
  float autocvar_cl_readpicture_force;
  var float autocvar_cl_reticle = 1;
 -float autocvar_cl_reticle_item_nex;
 -float autocvar_cl_reticle_item_normal;
 +var float autocvar_cl_reticle_normal_alpha = 1;
 +var float autocvar_cl_reticle_weapon = 1;
 +var float autocvar_cl_reticle_weapon_alpha = 1;
  float autocvar_cl_reticle_stretch;
  float autocvar_cl_spawn_event_particles;
  var float autocvar_cl_spawn_event_sound = 1;
@@@ -126,14 -125,14 +126,14 @@@ float autocvar_crosshair_ring_minelayer
  float autocvar_crosshair_ring_minelayer_alpha;
  float autocvar_crosshair_ring_hagar;
  float autocvar_crosshair_ring_hagar_alpha;
 -float autocvar_crosshair_ring_nex;
 -float autocvar_crosshair_ring_nex_alpha;
 -float autocvar_crosshair_ring_nex_currentcharge_movingavg_rate;
 -float autocvar_crosshair_ring_nex_currentcharge_scale;
 -float autocvar_crosshair_ring_nex_inner_alpha;
 -float autocvar_crosshair_ring_nex_inner_color_blue;
 -float autocvar_crosshair_ring_nex_inner_color_green;
 -float autocvar_crosshair_ring_nex_inner_color_red;
 +float autocvar_crosshair_ring_vortex;
 +float autocvar_crosshair_ring_vortex_alpha;
 +float autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate;
 +float autocvar_crosshair_ring_vortex_currentcharge_scale;
 +float autocvar_crosshair_ring_vortex_inner_alpha;
 +float autocvar_crosshair_ring_vortex_inner_color_blue;
 +float autocvar_crosshair_ring_vortex_inner_color_green;
 +float autocvar_crosshair_ring_vortex_inner_color_red;
  float autocvar_crosshair_ring_size;
  float autocvar_crosshair_ring_reload;
  float autocvar_crosshair_ring_reload_alpha;
@@@ -269,6 -268,7 +269,7 @@@ float autocvar_hud_panel_notify_fadetim
  float autocvar_hud_panel_notify_flip;
  float autocvar_hud_panel_notify_fontsize;
  float autocvar_hud_panel_notify_time;
+ float autocvar_hud_panel_notify_icon_aspect;
  float autocvar_hud_panel_physics;
  float autocvar_hud_panel_physics_acceleration_progressbar_mode;
  float autocvar_hud_panel_physics_acceleration_progressbar_scale;
diff --combined qcsrc/client/hud.qc
@@@ -408,6 -408,42 +408,6 @@@ float weaponorder_cmp(float i, float j
        return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string)
  }
  
 -float GetAmmoStat(float i)
 -{
 -      switch(i)
 -      {
 -              case 0: return STAT_SHELLS;
 -              case 1: return STAT_NAILS;
 -              case 2: return STAT_ROCKETS;
 -              case 3: return STAT_CELLS;
 -              case 4: return STAT_FUEL;
 -              default: return -1;
 -      }
 -}
 -
 -float GetAmmoTypeForWep(float i)
 -{
 -      switch(i)
 -      {
 -              case WEP_SHOTGUN: return 0;
 -              case WEP_UZI: return 1;
 -              case WEP_GRENADE_LAUNCHER: return 2;
 -              case WEP_MINE_LAYER: return 2;
 -              case WEP_ELECTRO: return 3;
 -              case WEP_CRYLINK: return 3;
 -              case WEP_HLAC: return 3;
 -              case WEP_MINSTANEX: return 3;
 -              case WEP_NEX: return 3;
 -              case WEP_RIFLE: return 1;
 -              case WEP_HAGAR: return 2;
 -              case WEP_ROCKET_LAUNCHER: return 2;
 -              case WEP_SEEKER: return 2;
 -              case WEP_FIREBALL: return 4;
 -              case WEP_HOOK: return 3;
 -              default: return -1;
 -      }
 -}
 -
  void HUD_Weapons(void)
  {
        // declarations
        float timein_effect_length = autocvar_hud_panel_weapons_timeout_speed_in; //? 0.375 : 0);
        float timeout_effect_length = autocvar_hud_panel_weapons_timeout_speed_out; //? 0.75 : 0);
  
 -      float ammo_type, ammo_full;
 +      float ammo_full;
        float barsize_x = 0, barsize_y = 0, baroffset_x = 0, baroffset_y = 0;
        vector ammo_color = '1 0 1';
        float ammo_alpha = 1;
                if(weapons_stat & WepSet_FromWeapon(self.weapon))
                {
                        // draw the weapon image
 -                      drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 +                      drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
  
                        // draw weapon label string
                        switch(autocvar_hud_panel_weapons_label)
                                        break;
  
                                case 3: // weapon name
 -                                      drawstring(weapon_pos, self.netname, '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 +                                      drawstring(weapon_pos, strtolower(self.message), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
                                        break;
  
                                default: // nothing
                        }
  
                        // draw ammo status bar
 -                      if(autocvar_hud_panel_weapons_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO)
 +                      if(autocvar_hud_panel_weapons_ammo && (self.ammo_field != ammo_none))
                        {
 -                              a = 0;
 -                              ammo_type = GetAmmoTypeForWep(self.weapon);
 -                              if(ammo_type != -1)
 -                                      a = getstati(GetAmmoStat(ammo_type)); // how much ammo do we have?
 +                              a = getstati(GetAmmoStat(self.ammo_field)); // how much ammo do we have?
  
                                if(a > 0)
                                {
 -                                      switch(ammo_type) {
 -                                              case 0: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break;
 -                                              case 1: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break;
 -                                              case 2: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
 -                                              case 3: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break;
 -                                              case 4: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break;
 +                                      switch(self.ammo_field)
 +                                      {
 +                                              case ammo_shells:  ammo_full = autocvar_hud_panel_weapons_ammo_full_shells;  break;
 +                                              case ammo_nails:   ammo_full = autocvar_hud_panel_weapons_ammo_full_nails;   break;
 +                                              case ammo_rockets: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
 +                                              case ammo_cells:   ammo_full = autocvar_hud_panel_weapons_ammo_full_cells;   break;
 +                                              case ammo_fuel:    ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel;    break;
                                                default: ammo_full = 60;
                                        }
  
                                                weapon_pos_x + baroffset_x,
                                                weapon_pos_y + baroffset_y,
                                                barsize_x * bound(0, a/ammo_full, 1),
 -                                              barsize_y);
 -                                      drawpic_aspect_skin(weapon_pos, "weapon_ammo", weapon_size, ammo_color, ammo_alpha, DRAWFLAG_NORMAL);
 +                                              barsize_y
 +                                      );
 +
 +                                      drawpic_aspect_skin(
 +                                              weapon_pos,
 +                                              "weapon_ammo",
 +                                              weapon_size,
 +                                              ammo_color,
 +                                              ammo_alpha,
 +                                              DRAWFLAG_NORMAL
 +                                      );
 +
                                        drawresetcliparea();
                                }
                        }
                }
                else // draw a "ghost weapon icon" if you don't have the weapon
                {
 -                      drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
 +                      drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
                }
  
                // draw the complain message
  }
  
  // Ammo (#1)
 -//
 -// TODO: macro
 -float GetAmmoItemCode(float i)
 +void DrawAmmoItem(vector myPos, vector mySize, .float ammotype, float currently_selected, float infinite_ammo)
  {
 -      switch(i)
 +      float a = 0;
 +      if(ammotype != ammo_none)
        {
 -              case 0: return IT_SHELLS;
 -              case 1: return IT_NAILS;
 -              case 2: return IT_ROCKETS;
 -              case 3: return IT_CELLS;
 -              case 4: return IT_FUEL;
 -              default: return -1;
 -      }
 -}
 -
 -string GetAmmoPicture(float i)
 -{
 -      switch(i)
 -      {
 -              case 0: return "ammo_shells";
 -              case 1: return "ammo_bullets";
 -              case 2: return "ammo_rockets";
 -              case 3: return "ammo_cells";
 -              case 4: return "ammo_fuel";
 -              default: return "";
 +              if(autocvar__hud_configure)
 +              {
 +                      currently_selected = (ammotype == ammo_rockets); //rockets always selected
 +                      a = 60;
 +              }
 +              else
 +              {
 +                      // how much ammo do we have of this ammotype?
 +                      a = getstati(GetAmmoStat(ammotype));
 +              }
        }
 -}
 -
 -void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected, float infinite_ammo)
 -{
 -      float a;
 -      if(autocvar__hud_configure)
 +      else
        {
 -              currently_selected = (itemcode == 2); //rockets always selected
 -              a = 31 + mod(itemcode*93, 128);
 +              #if 0
 +              infinite_ammo = TRUE;
 +              #else
 +              return; // just don't draw infinite ammo at all.
 +              #endif
        }
 -      else
 -              a = getstati(GetAmmoStat(itemcode)); // how much ammo do we have of type itemcode?
  
        vector color;
        if(infinite_ammo)
                picpos = myPos;
        }
  
 -      if (currently_selected)
 +      if(currently_selected)
                drawpic_aspect_skin(myPos, "ammo_current_bg", mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
  
      if(a > 0 && autocvar_hud_panel_ammo_progressbar)
              drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
      }
        if(a > 0 || infinite_ammo)
 -              drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
 +              drawpic_aspect_skin(picpos, GetAmmoPicture(ammotype), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
        else // "ghost" ammo icon
 -              drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
 +              drawpic_aspect_skin(picpos, GetAmmoPicture(ammotype), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
  }
  
  void HUD_Ammo(void)
        const float AMMO_COUNT = 4;
        float rows = 0, columns, row, column;
        vector ammo_size;
 -      if (autocvar_hud_panel_ammo_onlycurrent)
 +      if(autocvar_hud_panel_ammo_onlycurrent)
                ammo_size = mySize;
        else
        {
                ammo_size_y = newSize;
        }
  
 -      float i, stat_items, currently_selected, infinite_ammo;
 -      infinite_ammo = FALSE;
 -      if (autocvar_hud_panel_ammo_onlycurrent)
 +      float i;
 +      float infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
 +      if(autocvar_hud_panel_ammo_onlycurrent)
        {
                if(autocvar__hud_configure)
                {
 -                      DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets
 +                      DrawAmmoItem(pos, ammo_size, ammo_rockets, TRUE, FALSE);
                }
                else
                {
 -                      stat_items = getstati(STAT_ITEMS, 0, 24);
 -                      if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
 -                              infinite_ammo = TRUE;
 -                      for (i = 0; i < AMMO_COUNT; ++i) {
 -                              currently_selected = stat_items & GetAmmoItemCode(i);
 -                              if (currently_selected)
 -                              {
 -                                      DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo);
 -                                      break;
 -                              }
 -                      }
 +                      DrawAmmoItem(
 +                              pos,
 +                              ammo_size,
 +                              (get_weaponinfo(switchweapon)).ammo_field,
 +                              TRUE,
 +                              infinite_ammo
 +                      );
                }
        }
        else
        {
 -              stat_items = getstati(STAT_ITEMS, 0, 24);
 -              if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
 -                      infinite_ammo = TRUE;
 +              .float ammotype;
                row = column = 0;
 -              for (i = 0; i < AMMO_COUNT; ++i) {
 -                      currently_selected = stat_items & GetAmmoItemCode(i);
 -                      DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo);
 +              for(i = 0; i < AMMO_COUNT; ++i)
 +              {
 +                      ammotype = GetAmmoFieldFromNum(i);
 +                      DrawAmmoItem(
 +                              pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y),
 +                              ammo_size,
 +                              ammotype,
 +                              ((get_weaponinfo(switchweapon)).ammo_field == ammotype),
 +                              infinite_ammo
 +                      );
 +
                        ++row;
                        if(row >= rows)
                        {
@@@ -1561,148 -1601,154 +1561,154 @@@ void HUD_HealthArmor(void
  
  void HUD_Notify_Push(string icon, string attacker, string victim)
  {
-       if(icon != "")
-       {
-               --kn_index;
-               if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; }
-               notify_times[kn_index] = time;
+       if (icon == "")
+               return;
+       ++notify_count;
+       --notify_index;
+       if (notify_index == -1)
+               notify_index = NOTIFY_MAX_ENTRIES-1;
+       // Free old strings
+       if (notify_attackers[notify_index])
+               strunzone(notify_attackers[notify_index]);
  
-               // icon
-               if(notify_icon[kn_index]) { strunzone(notify_icon[kn_index]); }
-               notify_icon[kn_index] = strzone(icon);
+       if (notify_victims[notify_index])
+               strunzone(notify_victims[notify_index]);
  
-               // attacker
-               if(notify_attackers[kn_index]) { strunzone(notify_attackers[kn_index]); }
-               notify_attackers[kn_index] = strzone(attacker);
+       if (notify_icons[notify_index])
+               strunzone(notify_icons[notify_index]);
  
-               // victim
-               if(notify_victims[kn_index]) { strunzone(notify_victims[kn_index]); }
-               notify_victims[kn_index] = strzone(victim);
+       // Allocate new strings
+       if (victim != "")
+       {
+               notify_attackers[notify_index] = strzone(attacker);
+               notify_victims[notify_index] = strzone(victim);
        }
+       else
+       {
+               // In case of a notification without a victim, the attacker
+               // is displayed on the victim's side. Instead of special
+               // treatment later on, we can simply switch them here.
+               notify_attackers[notify_index] = string_null;
+               notify_victims[notify_index] = strzone(attacker);
+       }
+       notify_icons[notify_index] = strzone(icon);
+       notify_times[notify_index] = time;
  }
  
  void HUD_Notify(void)
  {
-       if(!autocvar__hud_configure)
-       {
-               if(!autocvar_hud_panel_notify) return;
-       }
+       if (!autocvar__hud_configure)
+               if (!autocvar_hud_panel_notify)
+                       return;
  
        HUD_Panel_UpdateCvars();
-       vector pos, mySize;
-       pos = panel_pos;
-       mySize = panel_size;
        HUD_Panel_DrawBg(1);
-       if(panel_bg_padding)
+       if (!autocvar__hud_configure)
+               if (notify_count == 0)
+                       return;
+       vector pos, size;
+       pos  = panel_pos;
+       size = panel_size;
+       if (panel_bg_padding)
        {
-               pos += '1 1 0' * panel_bg_padding;
-               mySize -= '2 2 0' * panel_bg_padding;
+               pos  += '1 1 0' * panel_bg_padding;
+               size -= '2 2 0' * panel_bg_padding;
        }
  
-       float entries, height;
-       entries = bound(1, floor(KN_MAX_ENTRIES * mySize_y/mySize_x), KN_MAX_ENTRIES);
-       height = mySize_y/entries;
+       float fade_start = max(0, autocvar_hud_panel_notify_time);
+       float fade_time = max(0, autocvar_hud_panel_notify_fadetime);
+       float icon_aspect = max(1, autocvar_hud_panel_notify_icon_aspect);
+       float entry_count = bound(1, floor(NOTIFY_MAX_ENTRIES * size_y / size_x), NOTIFY_MAX_ENTRIES);
+       float entry_height = size_y / entry_count;
  
-       vector fontsize;
-       float fontheight = height * autocvar_hud_panel_notify_fontsize;
-       fontsize = '0.5 0.5 0' * fontheight;
+       float panel_width_half = size_x * 0.5;
+       float icon_width_half = entry_height * icon_aspect / 2;
+       float name_maxwidth = panel_width_half - icon_width_half - size_x * NOTIFY_ICON_MARGIN;
  
-       float a;
-       float when;
-       when = autocvar_hud_panel_notify_time;
-       float fadetime;
-       fadetime = autocvar_hud_panel_notify_fadetime;
+       vector font_size = '0.5 0.5 0' * entry_height * autocvar_hud_panel_notify_fontsize;
+       vector icon_size = (eX * icon_aspect + eY) * entry_height;
+       vector icon_left = eX * (panel_width_half - icon_width_half);
+       vector attacker_right = eX * name_maxwidth;
+       vector victim_left = eX * (size_x - name_maxwidth);
  
-       vector pos_attacker, pos_victim, pos_icon;
-       float width_attacker;
+       vector attacker_pos, victim_pos, icon_pos;
        string attacker, victim, icon;
+       float i, j, count, step, limit, alpha;
  
-       float i, j, step, limit;
-       if(autocvar_hud_panel_notify_flip) //order items from the top down
+       if (autocvar_hud_panel_notify_flip)
        {
+               // Order items from the top down
                i = 0;
                step = +1;
-               limit = entries;
+               limit = entry_count;
        }
-       else //order items from the bottom up
+       else
        {
-               i = entries - 1;
+               // Order items from the bottom up
+               i = entry_count - 1;
                step = -1;
                limit = -1;
        }
  
-       for(j = kn_index;  i != limit;  i += step, ++j)
+       for (j = notify_index, count = 0; i != limit; i += step, ++j, ++count)
        {
                if(autocvar__hud_configure)
                {
-                       if (step == +1)
-                               a = i;
-                       else // inverse order
-                               a = entries - 1 - i;
-                       attacker = textShortenToWidth(sprintf(_("Player %d"), a+1), 0.48 * mySize_x - height, fontsize, stringwidth_colors);
-                       victim = textShortenToWidth(sprintf(_("Player %d"), a+2), 0.48 * mySize_x - height, fontsize, stringwidth_colors);
-                       icon = get_weaponinfo(WEP_FIRST + mod(floor(a*2.4), WEP_LAST)).model2;
-                       a = bound(0, (when - a) / 4, 1);
-                       goto hud_config_notifyprint;
+                       attacker = sprintf(_("Player %d"), count + 1);
+                       victim = sprintf(_("Player %d"), count + 2);
 -                      icon = strcat("weapon", get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).netname);
++                      icon = get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).model2;
+                       alpha = bound(0, 1.2 - count / entry_count, 1);
                }
                else
                {
-                       if (j == KN_MAX_ENTRIES)
+                       if (j == NOTIFY_MAX_ENTRIES)
                                j = 0;
  
-                       if(notify_times[j] + when > time)
-                               a = 1;
-                       else if(fadetime)
+                       if (notify_times[j] + fade_start > time)
+                               alpha = 1;
+                       else if (fade_time != 0)
                        {
-                               a = bound(0, (notify_times[j] + when + fadetime - time) / fadetime, 1);
-                               if(!a)
-                               {
+                               alpha = bound(0, (notify_times[j] + fade_start + fade_time - time) / fade_time, 1);
+                               if (alpha == 0)
                                        break;
-                               }
                        }
                        else
-                       {
                                break;
-                       }
  
                        attacker = notify_attackers[j];
                        victim = notify_victims[j];
-                       icon = notify_icon[j];
+                       icon = notify_icons[j];
                }
  
-               //type = notify_deathtype[j];
-               //w = DEATH_WEAPONOF(type);
-               if(icon != "")
+               if (icon != "" && victim != "")
                {
-                       if((attacker != "") && (victim == ""))
-                       {
-                               // Y [used by] X
-                               attacker = textShortenToWidth(attacker, 0.73 * mySize_x - height, fontsize, stringwidth_colors);
-                               pos_attacker = pos + eX * (0.27 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
-                               pos_icon = pos + eX * 0.25 * mySize_x - eX * height + eY * i * height;
+                       vector name_top = eY * (i * entry_height + 0.5 * (entry_height - font_size_y));
  
-                               drawpic_aspect_skin(pos_icon, icon, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
-                               drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
-                       }
-                       else if((attacker != "") && (victim != ""))
+                       icon_pos = pos + icon_left + eY * i * entry_height;
+                       drawpic_aspect_skin(icon_pos, icon, icon_size, '1 1 1', panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
+                       victim = textShortenToWidth(victim, name_maxwidth, font_size, stringwidth_colors);
+                       victim_pos = pos + victim_left + name_top;
+                       drawcolorcodedstring(victim_pos, victim, font_size, panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
+                       if (attacker != "")
                        {
-                               // X [did action to] Y
-                               attacker = textShortenToWidth(attacker, 0.48 * mySize_x - height, fontsize, stringwidth_colors);
-                               victim = textShortenToWidth(victim, 0.48 * mySize_x - height, fontsize, stringwidth_colors);
- :hud_config_notifyprint
-                               width_attacker = stringwidth(attacker, TRUE, fontsize);
-                               pos_attacker = pos + eX * (0.48 * mySize_x - height - width_attacker) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
-                               pos_victim = pos + eX * (0.52 * mySize_x + height) + eY * ((0.5 * fontsize_y + i * height) + (0.5 * (height - fontheight)));
-                               pos_icon = pos + eX * 0.5 * mySize_x - eX * height + eY * i * height;
-                               drawpic_aspect_skin(pos_icon, icon, '2 1 0' * height, '1 1 1', panel_fg_alpha * a, DRAWFLAG_NORMAL);
-                               drawcolorcodedstring(pos_attacker, attacker, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
-                               drawcolorcodedstring(pos_victim, victim, fontsize, panel_fg_alpha * a, DRAWFLAG_NORMAL);
+                               attacker = textShortenToWidth(attacker, name_maxwidth, font_size, stringwidth_colors);
+                               attacker_pos = pos + attacker_right - eX * stringwidth(attacker, TRUE, font_size) + name_top;
+                               drawcolorcodedstring(attacker_pos, attacker, font_size, panel_fg_alpha * alpha, DRAWFLAG_NORMAL);
                        }
                }
        }
+       notify_count = count;
  }
  
  // Timer (#5)