]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/client/hud.qc
fix dumb mistake, fix hurttrigger notification
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / hud.qc
index 66e182fdd0ef0421f817ad859e0471444757fe5d..487b82148618693fd25236ebf01ff476f2f79333 100644 (file)
@@ -217,31 +217,30 @@ void HUD_DrawXNum (vector pos, float num, float digits, float showsign, float le
        }
 }
 
-// color the number differently based on how big it is (used in the health/armor panel)
-void HUD_DrawXNum_Colored (vector pos, float x, float digits, float lettersize, float alpha)
+vector HUD_Get_Num_Color (float x, float maxvalue)
 {
        vector color;
-       if(x > 200) {
+       if(x > maxvalue) {
                color_x = 0;
                color_y = 1;
                color_z = 0;
        }
-       else if(x > 150) {
+       else if(x > maxvalue * 0.75) {
                color_x = 0.4 - (x-150)*0.02 * 0.4; //red value between 0.4 -> 0
                color_y = 0.9 + (x-150)*0.02 * 0.1; // green value between 0.9 -> 1
                color_z = 0;
        }
-       else if(x > 100) {
+       else if(x > maxvalue * 0.5) {
                color_x = 1 - (x-100)*0.02 * 0.6; //red value between 1 -> 0.4
                color_y = 1 - (x-100)*0.02 * 0.1; // green value between 1 -> 0.9
                color_z = 1 - (x-100)*0.02; // blue value between 1 -> 0
        }
-       else if(x > 50) {
+       else if(x > maxvalue * 0.25) {
                color_x = 1;
                color_y = 1;
                color_z = 0.2 + (x-50)*0.02 * 0.8; // blue value between 0.2 -> 1
        }
-       else if(x > 20) {
+       else if(x > maxvalue * 0.1) {
                color_x = 1;
                color_y = (x-20)*90/27/100; // green value between 0 -> 1
                color_z = (x-20)*90/27/100 * 0.2; // blue value between 0 -> 0.2
@@ -251,6 +250,13 @@ void HUD_DrawXNum_Colored (vector pos, float x, float digits, float lettersize,
                color_y = 0;
                color_z = 0;
        }
+       return color;
+}
+// color the number differently based on how big it is (used in the health/armor panel)
+void HUD_DrawXNum_Colored (vector pos, float x, float digits, float lettersize, float alpha)
+{
+       vector color;
+       color = HUD_Get_Num_Color (x, 200);
        HUD_DrawXNum(pos, x, digits, 0, lettersize, color, 0, 0, alpha, DRAWFLAG_NORMAL);
 }
 
@@ -597,7 +603,6 @@ void HUD_Panel_ExportCfg(string cfgname)
                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_bg_padding \"", cvar_string(strcat("hud_", HUD_Panel_GetName(i), "_bg_padding")), "\"", "\n"));
                        switch(i) {
                                case 0:
-                                       fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_accuracy_height ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_accuracy_height"))), "\n"));
                                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_accuracy_yellow ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_accuracy_yellow"))), "\n"));
                                        break;
                                case 1:
@@ -614,6 +619,8 @@ void HUD_Panel_ExportCfg(string cfgname)
                                case 4:
                                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_flip ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_flip"))), "\n"));
                                        break;
+                               case 6:
+                                       fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_foreground_alpha ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_foreground_alpha"))), "\n"));
                                case 9:
                                        fputs(fh, strcat("seta hud_", HUD_Panel_GetName(i), "_alreadyvoted_alpha ", ftos(cvar(strcat("hud_", HUD_Panel_GetName(i), "_alreadyvoted_alpha"))), "\n"));
                                        break;
@@ -670,6 +677,9 @@ vector HUD_Panel_GetMinSize(float id)
                case 11: 
                        mySize_y = 0.5898; // 0.5898 * width, reason: bg has weird dimensions...
                        break;
+               case 13: 
+                       mySize_y = 0.25; // 0.25 * width, trial and error...
+                       break;
        }
        if(!mySize_x && mySize_y)
                mySize_x = 1/mySize_y;
@@ -2211,14 +2221,16 @@ string Weapon_KillMessage(float deathtype)
 
 float killnotify_times[10];
 float killnotify_deathtype[10];
+float killnotify_actiontype[10]; // 0 = "Y [used by] X", 1 = "X [did action to] Y"
 string killnotify_attackers[10];
 string killnotify_victims[10];
-void HUD_KillNotify_Push(string attacker, string victim, float wpn)
+void HUD_KillNotify_Push(string attacker, string victim, float actiontype, float wpn)
 {
        float i;
        for (i = 9; i > 0; --i) {
                killnotify_times[i] = killnotify_times[i-1];
                killnotify_deathtype[i] = killnotify_deathtype[i-1];
+               killnotify_actiontype[i] = killnotify_actiontype[i-1];
                if(killnotify_attackers[i])
                        strunzone(killnotify_attackers[i]);
                killnotify_attackers[i] = strzone(killnotify_attackers[i-1]);
@@ -2228,6 +2240,7 @@ void HUD_KillNotify_Push(string attacker, string victim, float wpn)
        }
        killnotify_times[0] = time;
        killnotify_deathtype[0] = wpn;
+       killnotify_actiontype[0] = actiontype;
        if(killnotify_attackers[0])
                strunzone(killnotify_attackers[0]);
        killnotify_attackers[0] = strzone(attacker);
@@ -2239,124 +2252,175 @@ void HUD_KillNotify_Push(string attacker, string victim, float wpn)
 void HUD_KillNotify(string s1, string s2, string s3, float type, float msg)
 {
        float w;
+       float alsoprint;
+       alsoprint = (cvar("hud_notify_print") || !HUD_Panel_CheckActive(4)); // print message to console if: notify panel disabled, or cvar to do so enabled
+       
        if(msg == MSG_SUICIDE) {
-               HUD_KillNotify_Push(s1, "", DEATH_KILL);
-
                // TODO: cl_gentle
                w = DEATH_WEAPONOF(type);
                if(WEP_VALID(w)) {
-                       if (!HUD_Panel_CheckActive(4) || cvar("hud_notify_print"))
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if (alsoprint)
                                print("^1", s1, "^1 ", Weapon_SuicideMessage(type), "\n");
-               }
-               else if (type == DEATH_KILL)
-                       print ("^1",s1, "^1 couldn't take it anymore\n");
-               else if (type == DEATH_ROT)
-                       print ("^1",s1, "^1 died\n");
-               else if (type == DEATH_NOAMMO)
-                       print ("^7",s1, "^7 committed suicide. What's the point of living without ammo?\n");
-               else if (type == DEATH_CAMP)
-                       print ("^1",s1, "^1 thought they found a nice camping ground\n");
-               else if (type == DEATH_MIRRORDAMAGE)
-                       print ("^1",s1, "^1 didn't become friends with the Lord of Teamplay\n");
-               else if (type == DEATH_CHEAT)
-                       print ("^1",s1, "^1 unfairly eliminated themself\n");
-               else if (type == DEATH_FIRE)
-                       print ("^1",s1, "^1 burned to death\n");
-               else if (type != DEATH_TEAMCHANGE && type != DEATH_QUIET)
-                       print ("^1",s1, "^1 couldn't resist the urge to self-destruct\n");
+               } else if (type == DEATH_KILL) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_KILL);
+                       if (alsoprint)
+                               print ("^1",s1, "^1 couldn't take it anymore\n");
+               } else if (type == DEATH_ROT) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if (alsoprint)
+                               print ("^1",s1, "^1 died\n");
+               } else if (type == DEATH_NOAMMO) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_NOAMMO);
+                       if (alsoprint)
+                               print ("^7",s1, "^7 committed suicide. What's the point of living without ammo?\n");
+               } else if (type == DEATH_CAMP) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_CAMP);
+                       if (alsoprint)
+                               print ("^1",s1, "^1 thought they found a nice camping ground\n");
+               } else if (type == DEATH_MIRRORDAMAGE) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_MIRRORDAMAGE);
+                       if (alsoprint)
+                               print ("^1",s1, "^1 didn't become friends with the Lord of Teamplay\n");
+               } else if (type == DEATH_CHEAT) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if (alsoprint)
+                               print ("^1",s1, "^1 unfairly eliminated themself\n");
+               } else if (type == DEATH_FIRE) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if (alsoprint)
+                               print ("^1",s1, "^1 burned to death\n");
+               } else if (type != DEATH_TEAMCHANGE && type != DEATH_QUIET) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if (alsoprint)
+                               print ("^1",s1, "^1 couldn't resist the urge to self-destruct\n");
+               } 
+               
                if (stof(s2) > 2) // killcount > 2
                        print ("^1",s1,"^1 ended it all after a ",s2," kill spree\n");
        } else if(msg == MSG_KILL) {
                w = DEATH_WEAPONOF(type);
                if(WEP_VALID(w)) {
-                       HUD_KillNotify_Push(s2, s1, w);
-                       if (!HUD_Panel_CheckActive(4) || cvar("hud_notify_print"))
+                       HUD_KillNotify_Push(s2, s1, 1, w);
+                       if (alsoprint)
                                print("^1", s1, "^1 ", Weapon_KillMessage(type), "\n");
                }
                else if(type == KILL_TEAM || type == KILL_TEAM_SPREE) {
+                       HUD_KillNotify_Push(s1, s2, 1, DEATH_MIRRORDAMAGE);
+                       if(alsoprint)
+                       {
                                if(cvar("cl_gentle")) {
                                        print ("^1", s1, "^1 took action against a team mate\n");
                                } else {
                                        print ("^1", s1, "^1 mows down a team mate\n");
                                }
-                               if (stof(s2) > 2 && type == KILL_TEAM_SPREE) {
-                                       if(cvar("cl_gentle"))
-                                               print ("^1",s1,"^1 ended a ",s2," scoring spree by going against a team mate\n");
-                                       else
-                                               print ("^1",s1,"^1 ended a ",s2," kill spree by killing a team mate\n");
-                               }
-                               else if (stof(s2) > 2) {
-                                       if(cvar("cl_gentle"))
-                                               print ("^1",s1,"'s ^1",s2," scoring spree was ended by a team mate!\n");
-                                       else
-                                               print ("^1",s1,"'s ^1",s2," kill spree was ended by a team mate!\n");
-                               }
+                       }
+                       if (stof(s2) > 2 && type == KILL_TEAM_SPREE) {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1,"^1 ended a ",s2," scoring spree by going against a team mate\n");
+                               else
+                                       print ("^1",s1,"^1 ended a ",s2," kill spree by killing a team mate\n");
+                       }
+                       else if (stof(s2) > 2) {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1,"'s ^1",s2," scoring spree was ended by a team mate!\n");
+                               else
+                                       print ("^1",s1,"'s ^1",s2," kill spree was ended by a team mate!\n");
+                       }
                }
                else if(type == KILL_FIRST_BLOOD)
                        print("^1",s1, "^1 drew first blood", "\n");
+               // TODO: icon!
                else if (type == DEATH_TELEFRAG)
                        print ("^1",s1, "^1 was telefragged by ", s2, "\n");
                else if (type == DEATH_DROWN) {
-                       HUD_KillNotify_Push(s2, s1, DEATH_FALL);
-                       print ("^1",s1, "^1 was drowned by ", s2, "\n");
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_DROWN);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was drowned by ", s2, "\n");
                }
                else if (type == DEATH_SLIME) {
-                       HUD_KillNotify_Push(s2, s1, DEATH_FALL);
-                       print ("^1",s1, "^1 was slimed by ", s2, "\n");
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_SLIME);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was slimed by ", s2, "\n");
                }
                else if (type == DEATH_LAVA) {
-                       HUD_KillNotify_Push(s2, s1, DEATH_FALL);
-                       print ("^1",s1, "^1 was cooked by ", s2, "\n");
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_LAVA);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was cooked by ", s2, "\n");
                }
                else if (type == DEATH_FALL) {
-                       HUD_KillNotify_Push(s2, s1, DEATH_FALL);
-                       print ("^1",s1, "^1 was grounded by ", s2, "\n");
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_FALL);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was grounded by ", s2, "\n");
                }
                else if (type == DEATH_SHOOTING_STAR) {
-                       HUD_KillNotify_Push(s2, s1, DEATH_FALL);
-                       print ("^1",s1, "^1 was shot into space by ", s2, "\n");
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_SHOOTING_STAR);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was shot into space by ", s2, "\n");
                }
                else if (type == DEATH_SWAMP) {
-                       HUD_KillNotify_Push(s2, s1, DEATH_FALL);
-                       print ("^1",s1, "^1 was conserved by ", s2, "\n");
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was conserved by ", s2, "\n");
                }
-               else if (type == DEATH_HURTTRIGGER && s3 != "")
+               else if (type == DEATH_HURTTRIGGER)
                {
-                       HUD_KillNotify_Push(s2, s1, DEATH_FALL);
-                       // p ?!?! :o
-                       //if(p < 0)
-                               print("^1", s1, "^1 ", s3, " ", s2, "\n");
-                       //else
-                       //      bprint("^1", s1, "^1 ", substring(s3, 0, p), s2, "^1", substring(s3, p+1, strlen(s3) - (p+1)), "\n");
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_HURTTRIGGER);
+                       if(alsoprint)
+                               print("^1",s1, "^1 was thrown into a world of hurt by ", s2, "\n");
+               } else if(type == DEATH_SBCRUSH) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was crushed by ^1", s2, "\n");
+               } else if(type == DEATH_SBMINIGUN) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 got shredded by ^1", s2, "\n");
+               } else if(type == DEATH_SBROCKET) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was blased to bits by ^1", s2, "\n");
+               } else if(type == DEATH_SBBLOWUP) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 got caught in the destruction of ^1", s2, "'s vehicle\n");
+               } else if(type == DEATH_WAKIGUN) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was bolted down by ^1", s2, "\n");
+               } else if(type == DEATH_WAKIROCKET) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 could find no shelter from ^1", s2, "'s rockets\n");
+               } else if(type == DEATH_WAKIBLOWUP) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 dies when ^1", s2, "'s wakizashi dies.\n");
+               } else if(type == DEATH_TURRET) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was pushed into the line of fire by ^1", s2, "\n");
+               } else if(type == DEATH_TOUCHEXPLODE) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was pushed into an accident by ^1", s2, "\n");
+               } else if(type == DEATH_CHEAT) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was unfairly eliminated by ^1", s2, "\n");
+               } else if (type == DEATH_FIRE) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was burnt to death by ^1", s2, "\n");
+               } else if (type == DEATH_CUSTOM) {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_CUSTOM);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 ", s2, "\n");
+               } else {
+                       HUD_KillNotify_Push(s2, s1, 1, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was fragged by ", s2, "\n");
                }
-               else if(type == DEATH_SBCRUSH)
-                       print ("^1",s1, "^1 was crushed by ^1", s2, "\n");
-               else if(type == DEATH_SBMINIGUN)
-                       print ("^1",s1, "^1 got shredded by ^1", s2, "\n");
-               else if(type == DEATH_SBROCKET)
-                       print ("^1",s1, "^1 was blased to bits by ^1", s2, "\n");
-               else if(type == DEATH_SBBLOWUP)
-                       print ("^1",s1, "^1 got cought in the destruction of ^1", s2, "'s vehicle\n");
-
-               else if(type == DEATH_WAKIGUN)
-                       print ("^1",s1, "^1 was bolted down by ^1", s2, "\n");
-               else if(type == DEATH_WAKIROCKET)
-                       print ("^1",s1, "^1 could find no shelter from ^1", s2, "'s rockets\n");
-               else if(type == DEATH_WAKIBLOWUP)
-                       print ("^1",s1, "^1 dies when ^1", s2, "'s wakizashi dies.\n");
-
-               else if(type == DEATH_TURRET)
-                       print ("^1",s1, "^1 was pushed into the line of fire by ^1", s2, "\n");
-               else if(type == DEATH_TOUCHEXPLODE)
-                       print ("^1",s1, "^1 was pushed into an accident by ^1", s2, "\n");
-               else if(type == DEATH_CHEAT)
-                       print ("^1",s1, "^1 was unfairly eliminated by ^1", s2, "\n");
-               else if (type == DEATH_FIRE)
-                       print ("^1",s1, "^1 was burnt to death by ^1", s2, "\n");
-               else if (type == DEATH_CUSTOM)
-                       print ("^1",s1, "^1 ", s2, "\n");
-               else
-                       print ("^1",s1, "^1 was fragged by ", s2, "\n");
        } else if(msg == MSG_SPREE) {
                if(type == KILL_END_SPREE) {
                        if(cvar("cl_gentle"))
@@ -2405,82 +2469,114 @@ void HUD_KillNotify(string s1, string s2, string s3, float type, float msg)
                                print (s1,"^7 unleashes ^1ARMAGEDDON!\n");
                }
        } else if(msg == MSG_KILL_ACTION) { // wtf is this? isnt it basically the same as MSG_SUICIDE?
-               HUD_KillNotify_Push(s1, "", DEATH_KILL);
                if (type == DEATH_DROWN) {
-                       if(cvar("cl_gentle"))
-                               print ("^1",s1, "^1 was in the water for too long\n");
-                       else
-                               print ("^1",s1, "^1 drowned\n");
-               }
-               else if (type == DEATH_SLIME)
-                       print ("^1",s1, "^1 was slimed\n");
-               else if (type == DEATH_LAVA) {
-                       if(cvar("cl_gentle"))
-                               print ("^1",s1, "^1 found a hot place\n");
-                       else
-                               print ("^1",s1, "^1 turned into hot slag\n");
-               }
-               else if (type == DEATH_FALL) {
-                       if(cvar("cl_gentle"))
-                               print ("^1",s1, "^1 tested gravity (and it worked)\n");
-                       else
-                               print ("^1",s1, "^1 hit the ground with a crunch\n");
-               }
-               else if (type == DEATH_SHOOTING_STAR)
-                       print ("^1",s1, "^1 became a shooting star\n");
-               else if (type == DEATH_SWAMP) {
-                       if(cvar("cl_gentle"))
-                               print ("^1",s1, "^1 discovered a swamp\n");
-                       else
-                               print ("^1",s1, "^1 is now conserved for centuries to come\n");
-               }
-               else if(type == DEATH_TURRET)
-                       print ("^1",s1, "^1 was mowed down by a turret \n");
-               else if (type == DEATH_CUSTOM)
-                       print ("^1",s1, "^1 ", s2, "\n");
-               else if(type == DEATH_TOUCHEXPLODE)
-                       print ("^1",s1, "^1 died in an accident\n");
-               else if(type == DEATH_CHEAT)
-                       print ("^1",s1, "^1 was unfairly eliminated\n");
-               else if(type == DEATH_FIRE) {
-                       if(cvar("cl_gentle"))
-                               print ("^1",s1, "^1 felt a little hot\n");
-                       else
-                               print ("^1",s1, "^1 burnt to death\n");
-               }
-               else {
-                       if(cvar("cl_gentle"))
-                               print ("^1",s1, "^1 needs a restart\n");
-                       else
-                               print ("^1",s1, "^1 died\n");
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_DROWN);
+                       if(alsoprint)
+                       {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1, "^1 was in the water for too long\n");
+                               else
+                                       print ("^1",s1, "^1 drowned\n");
+                       }
+               } else if (type == DEATH_SLIME) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_SLIME);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was slimed\n");
+               } else if (type == DEATH_LAVA) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_LAVA);
+                       if(alsoprint)
+                       {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1, "^1 found a hot place\n");
+                               else
+                                       print ("^1",s1, "^1 turned into hot slag\n");
+                       }
+               } else if (type == DEATH_FALL) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if(alsoprint)
+                       {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1, "^1 tested gravity (and it worked)\n");
+                               else
+                                       print ("^1",s1, "^1 hit the ground with a crunch\n");
+                       }
+               } else if (type == DEATH_SHOOTING_STAR) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_SHOOTING_STAR);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 became a shooting star\n");
+               } else if (type == DEATH_SWAMP) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if(alsoprint)
+                       {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1, "^1 discovered a swamp\n");
+                               else
+                                       print ("^1",s1, "^1 is now conserved for centuries to come\n");
+                       }
+               } else if(type == DEATH_TURRET) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was mowed down by a turret \n");
+               } else if (type == DEATH_CUSTOM) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_CUSTOM);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 ", s2, "\n");
+               } else if (type == DEATH_HURTTRIGGER) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_HURTTRIGGER);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was in the wrong place\n");
+               } else if(type == DEATH_TOUCHEXPLODE) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 died in an accident\n");
+               } else if(type == DEATH_CHEAT) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if(alsoprint)
+                               print ("^1",s1, "^1 was unfairly eliminated\n");
+               } else if(type == DEATH_FIRE) {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if(alsoprint)
+                       {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1, "^1 felt a little hot\n");
+                               else
+                                       print ("^1",s1, "^1 burnt to death\n");
+                               }
+               } else {
+                       HUD_KillNotify_Push(s1, "", 0, DEATH_GENERIC);
+                       if(alsoprint)
+                       {
+                               if(cvar("cl_gentle"))
+                                       print ("^1",s1, "^1 needs a restart\n");
+                               else
+                                       print ("^1",s1, "^1 died\n");
+                       }
                }
        } else if(msg == MSG_KILL_ACTION_SPREE) {
-               HUD_KillNotify_Push(s1, "", DEATH_KILL);
                if(cvar("cl_gentle"))
                        print ("^1",s1,"^1 needs a restart after a ",s2," scoring spree\n");
                else
                        print ("^1",s1,"^1 died with a ",s2," kill spree\n");
        } else if(msg == MSG_INFO) {
-               if(type == INFO_GOTFLAG) {
-                       HUD_KillNotify_Push(s1, s2, INFO_GOTFLAG);
+               if(type == INFO_GOTFLAG) { // here, s2 is the flag name
+                       HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG);
                        print(s1, "^7 got the ", s2, "\n");
                } else if(type == INFO_LOSTFLAG) {
-                       HUD_KillNotify_Push(s1, s2, INFO_LOSTFLAG);
+                       HUD_KillNotify_Push(s1, s2, 0, INFO_LOSTFLAG);
                        print(s1, "^7 lost the ", s2, "\n");
                } else if(type == INFO_PICKUPFLAG) {
-                       HUD_KillNotify_Push(s1, s2, INFO_GOTFLAG);
+                       HUD_KillNotify_Push(s1, s2, 0, INFO_GOTFLAG);
                        print(s1, "^7 picked up the ", s2, "\n");
                } else if(type == INFO_RETURNFLAG) {
-                       HUD_KillNotify_Push(s1, s2, INFO_RETURNFLAG);
+                       HUD_KillNotify_Push(s1, s2, 0, INFO_RETURNFLAG);
                        print(s1, "^7 returned the ", s2, "\n");
                }
        }
-
 }
 
 #define DAMAGE_CENTERPRINT_SPACER NEWLINES
 
-void HUD_Centerprint(string s1, float type, float msg)
+void HUD_Centerprint(string s1, string s2, float type, float msg)
 {
        if(msg == MSG_SUICIDE) {
                if (type == DEATH_TEAMCHANGE) {
@@ -2534,29 +2630,29 @@ void HUD_Centerprint(string s1, float type, float msg)
                        } else {
                                centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1First victim"));
                        }
-               } else if (type == KILL_TYPEFRAG) {
+               } else if (type == KILL_TYPEFRAG) { // s2 contains "advanced kill messages" such as ping, handicap...
                        if(cvar("cl_gentle")) {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You scored against ^7", s1, "^7 who was typing!"));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You scored against ^7", s1, "^7 who was typing!", s2));
                        } else {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You typefragged ^7", s1));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You typefragged ^7", s1, s2));
                        }
                } else if (type == KILL_TYPEFRAGGED) {
                        if(cvar("cl_gentle")) {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were scored against by ^7", s1, "^7 while you were typing!"));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were scored against by ^7", s1, "^7 while you were typing!", s2));
                        } else {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were typefragged by ^7", s1));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^1You were typefragged by ^7", s1, s2));
                        }
                } else if (type == KILL_FRAG) {
                        if(cvar("cl_gentle")) {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You scored against ^7", s1));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You scored against ^7", s1, s2));
                        } else {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You fragged ^7", s1));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You fragged ^7", s1, s2));
                        }
                } else if (type == KILL_FRAGGED) {
                        if(cvar("cl_gentle")) {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You were scored against by ^7", s1));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You were scored against by ^7", s1, s2));
                        } else {
-                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You were fragged by ^7", s1));
+                               centerprint(strcat(DAMAGE_CENTERPRINT_SPACER, "^4You were fragged by ^7", s1, s2));
                        }
                }
        } else if(msg == MSG_KILL_ACTION) {
@@ -2584,6 +2680,7 @@ void HUD_Notify (void)
        float entries, height;
        entries = bound(1, floor(12 * mySize_y/mySize_x), 10);
        height = mySize_y/entries;
+       entries -= 2; // top/bottom two lines reserved for info messaged, such as spec instructions
        
        vector fontsize;
        fontsize = '0.5 0.5 0' * height;
@@ -2608,6 +2705,8 @@ void HUD_Notify (void)
                        i = j;
                else // rather nasty hack for ordering items from the bottom up
                        i = entries - j - 1;
+               if(cvar("hud_notify_info_top"))
+                       i += 2; // top/bottom two lines reserved for info messaged, such as spec instructions
 
                if(fadetime)
                {
@@ -2626,9 +2725,102 @@ void HUD_Notify (void)
 
                // TODO: maybe print in team colors?
                // TODO: maybe this could be cleaned up somehow...
+               // TODO: less copypaste code below
                //
+               // Y [used by] X
+               if(killnotify_actiontype[j] == 0 && !hud_configure) 
+               {
+                       attacker = textShortenToWidth(killnotify_attackers[j], mySize_x - 2 * height, fontsize, stringwidth_colors);
+
+                       width_attacker = stringwidth(attacker, TRUE, fontsize);
+                       pos_attacker = pos + eX * 0.5 * (mySize_x - width_attacker + 2 * height) + eY * 0.5 * fontsize_y + eY * i * height;
+
+                       weap_pos = pos + eX * 0.5 * (mySize_x - width_attacker) - eX * height + eY * i * height;
+                       if(killnotify_deathtype[j] == DEATH_GENERIC)
+                       {
+                               drawpic_skin(weap_pos, "notify_death", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_NOAMMO)
+                       {
+                               drawpic_skin(weap_pos, "notify_outofammo", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_KILL)
+                       {
+                               drawpic_skin(weap_pos, "notify_selfkill", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_CAMP)
+                       {
+                               drawpic_skin(weap_pos, "notify_camping", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_MIRRORDAMAGE)
+                       {
+                               drawpic_skin(weap_pos, "notify_teamkill", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_DROWN)
+                       {
+                               drawpic_skin(weap_pos, "notify_water", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_SLIME)
+                       {
+                               drawpic_skin(weap_pos, "notify_slime", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_LAVA)
+                       {
+                               drawpic_skin(weap_pos, "notify_lava", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_FALL)
+                       {
+                               drawpic_skin(weap_pos, "notify_fall", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_SHOOTING_STAR)
+                       {
+                               drawpic_skin(weap_pos, "notify_shootingstar", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_HURTTRIGGER || killnotify_deathtype[j] == DEATH_CUSTOM)
+                       {
+                               drawpic_skin(weap_pos, "notify_void", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == INFO_GOTFLAG)
+                       {
+                               if(killnotify_victims[j] == "^1RED^7 flag")
+                                       s = "red";
+                               else
+                                       s = "blue";
+                               drawpic_skin(weap_pos, strcat("flag_", s, "_carrying"), '1 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == INFO_RETURNFLAG)
+                       {
+                               if(killnotify_victims[j] == "^1RED^7 flag")
+                                       s = "red";
+                               else
+                                       s = "blue";
+                               drawpic_skin(weap_pos, strcat("flag_", s, "_taken"), '1 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == INFO_LOSTFLAG)
+                       {
+                               if(killnotify_victims[j] == "^1RED^7 flag")
+                                       s = "red";
+                               else
+                                       s = "blue";
+                               drawpic_skin(weap_pos, strcat("flag_", s, "_lost"), '1 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+               }
                // X [did action to] Y
-               if(hud_configure || WEP_VALID(killnotify_deathtype[j]) || killnotify_deathtype[j] == DEATH_FALL)
+               else
                {
                        if(hud_configure)
                        {
@@ -2660,86 +2852,92 @@ void HUD_Notify (void)
                                drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                        }
-                       else if(killnotify_deathtype[j] == DEATH_FALL)
+                       else if(killnotify_deathtype[j] == DEATH_MIRRORDAMAGE)
                        {
-                               drawpic_skin(weap_pos, "notify_pushoffedge", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawpic_skin(weap_pos, "notify_teamkill", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                        }
-               }
-
-               // Y [used by] X
-               else
-               {
-                       attacker = textShortenToWidth(killnotify_attackers[j], mySize_x - 2 * height, fontsize, stringwidth_colors);
-
-                       width_attacker = stringwidth(attacker, TRUE, fontsize);
-                       pos_attacker = pos + eX * 0.5 * (mySize_x - width_attacker + 2 * height) + eY * 0.5 * fontsize_y + eY * i * height;
-
-                       weap_pos = pos + eX * 0.5 * (mySize_x - width_attacker) - eX * height + eY * i * height;
-                       if(killnotify_deathtype[j] == DEATH_KILL)
+                       else if(killnotify_deathtype[j] == DEATH_DROWN)
                        {
-                               drawpic_skin(weap_pos, "notify_selfkill", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawpic_skin(weap_pos, "notify_water", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                        }
-                       else if(killnotify_deathtype[j] == INFO_GOTFLAG)
+                       else if(killnotify_deathtype[j] == DEATH_SLIME)
                        {
-                               if(killnotify_victims[j] == "^1RED^7 flag")
-                                       s = "red";
-                               else
-                                       s = "blue";
-                               drawpic_skin(weap_pos, strcat("flag_", s, "_carrying"), '1 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawpic_skin(weap_pos, "notify_slime", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                        }
-                       else if(killnotify_deathtype[j] == INFO_RETURNFLAG)
+                       else if(killnotify_deathtype[j] == DEATH_LAVA)
                        {
-                               if(killnotify_victims[j] == "^1RED^7 flag")
-                                       s = "red";
-                               else
-                                       s = "blue";
-                               drawpic_skin(weap_pos, strcat("flag_", s, "_taken"), '1 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawpic_skin(weap_pos, "notify_lava", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                        }
-                       else if(killnotify_deathtype[j] == INFO_LOSTFLAG)
+                       else if(killnotify_deathtype[j] == DEATH_FALL)
                        {
-                               if(killnotify_victims[j] == "^1RED^7 flag")
-                                       s = "red";
-                               else
-                                       s = "blue";
-                               drawpic_skin(weap_pos, strcat("flag_", s, "_lost"), '1 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawpic_skin(weap_pos, "notify_fall", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_SHOOTING_STAR)
+                       {
+                               drawpic_skin(weap_pos, "notify_shootingstar", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                       }
+                       else if(killnotify_deathtype[j] == DEATH_HURTTRIGGER || killnotify_deathtype[j] == DEATH_CUSTOM) // DEATH_CUSTOM is also void, right?
+                       {
+                               drawpic_skin(weap_pos, "notify_void", '2 1 0' * height, '1 1 1', HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                                drawcolorcodedstring(pos_attacker, attacker, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
+                               drawcolorcodedstring(pos_victim, victim, fontsize, HUD_Panel_GetFgAlpha(id) * a, DRAWFLAG_NORMAL);
                        }
                }
+
        }
-       /* This will come later.
-       string s;
+
+       // Info messages
+       //
        entity tm;
+       vector o;
+       o = pos;
+       if(cvar("hud_notify_info_top"))
+               o = pos + eY;
+       else
+               o = pos + eY * mySize_y - eY * 2 * height;
+       
        if(spectatee_status && !intermission)
        {
-               drawfont = hud_bigfont;
+               //drawfont = hud_bigfont;
                if(spectatee_status == -1)
                        s = "^1Observing";
                else
                        s = GetPlayerName(spectatee_status - 1);
-               // spectated player name between HUD and chat area, aligned to the left
-               pos_x = 0;
-               pos_y = - 50 - hud_fontsize_spec_y;
-               s = textShortenToWidth(s, vid_conwidth/2.5, hud_fontsize_spec, stringwidth_colors);
-               drawcolorcodedstring(pos, s, hud_fontsize_spec, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
-               drawfont = hud_font;
+
+               //s = textShortenToWidth(s, mySize_y, 0.5 * height, stringwidth_colors);
+               //drawcolorcodedstring(pos + eY * 0.25 * height, s, 0.5 * height, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               //drawfont = hud_font;
 
                // spectator text in the upper right corner
                if(spectatee_status == -1)
                        s = strcat("^1Press ^3", getcommandkey("primary fire", "+attack"), "^1 to spectate");
                else
                        s = strcat("^1Press ^3", getcommandkey("primary fire", "+attack"), "^1 for another player");
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
 
                if(spectatee_status == -1)
                        s = strcat("^1Use ^3", getcommandkey("next weapon", "weapnext"), "^1 or ^3", getcommandkey("previous weapon", "weapprev"), "^1 to change the speed");
                else
                        s = strcat("^1Press ^3", getcommandkey("secondary fire", "+attack2"), "^1 to observe");
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
 
                s = strcat("^1Press ^3", getcommandkey("server info", "+show_info"), "^1 for gamemode info");
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
 
                if(gametype == GAME_ARENA)
                        s = "^1Wait for your turn to join";
@@ -2756,6 +2954,8 @@ void HUD_Notify (void)
                }
                else
                        s = strcat("^1Press ^3", getcommandkey("jump", "+jump"), "^1 to join");
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
 
                //show restart countdown:
                if (time < getstatf(STAT_GAMESTARTTIME)) {
@@ -2763,15 +2963,17 @@ void HUD_Notify (void)
                        //we need to ceil, otherwise the countdown would be off by .5 when using round()
                        countdown = ceil(getstatf(STAT_GAMESTARTTIME) - time);
                        s = strcat("^1Game starts in ^3", ftos(countdown), "^1 seconds");
+                       drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+                       o += eY * fontsize_y;
                }
        }
        if(warmup_stage && !intermission)
        {
                s = "^2Currently in ^1warmup^2 stage!";
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
        }
 
-       // move more important stuff more to the middle so its more visible
-
        string blinkcolor;
        if(mod(time, 1) >= 0.5)
                blinkcolor = "^1";
@@ -2794,10 +2996,14 @@ void HUD_Notify (void)
                        else
                                s = strcat("^2Waiting for others to ready up...");
                }
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
        }
        else if(warmup_stage && !intermission && !spectatee_status)
        {
                s = strcat("^2Press ^3", getcommandkey("ready", "ready"), "^2 to end warmup");
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
        }
 
        if(teamplay && !intermission && !spectatee_status && gametype != GAME_CA && teamnagger)
@@ -2824,10 +3030,20 @@ void HUD_Notify (void)
                                if (tm.team_size == ts_max)
                                        s = strcat(s, " Press ^3", getcommandkey("team menu", "menu_showteamselect"), blinkcolor, " to adjust");
 
+                               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+                               o += eY * fontsize_y;
                        }
                }
        }
-       */
+       if(hud_configure)
+       {
+               s = "^7Press ^3ESC ^7to show HUD options.";
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
+               s = "^3Doubleclick a panel for panel-specific options.";
+               drawcolorcodedstring(o, s, fontsize, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+               o += eY * fontsize_y;
+       }
 }
 
 // Timer (#5)
@@ -3932,6 +4148,61 @@ void HUD_Chat(void)
        }
 }
 
+// Engine info panel (#13)
+//
+float prevfps;
+float prevfps_time;
+float framecounter;
+
+float frametimeavg;
+float frametimeavg1; // 1 frame ago
+float frametimeavg2; // 2 frames ago
+void HUD_EngineInfo(void)
+{
+       float id = HUD_PANEL_ENGINEINFO;
+       vector pos, mySize;
+       pos = HUD_Panel_GetPos(id);
+       mySize = HUD_Panel_GetSize(id);
+
+       HUD_Panel_DrawBg(id, pos, mySize, 0);
+       float padding;
+       padding = HUD_Panel_GetPadding(id);
+       if(padding)
+       {
+               pos += '1 1 0' * padding;
+               mySize -= '2 2 0' * padding;
+       }
+
+       if(cvar("hud_engineinfo_framecounter_exponentialmovingaverage"))
+       {
+               frametimeavg = (frametimeavg + frametimeavg1 + frametimeavg2 + frametime)/4; // average three frametimes into framecounter for slightly more stable fps readings :P
+               frametimeavg2 = frametimeavg1;
+               frametimeavg1 = frametimeavg;
+               
+               float weight;
+               weight = cvar("hud_engineinfo_framecounter_exponentialmovingaverage_new_weight");
+               if(frametime > 0.0001) // filter out insane values which sometimes seem to occur and throw off the average? If you are getting 10,000 fps or more, then you don't need a framerate counter.
+               {
+                       if(fabs(prevfps - (1/frametimeavg)) > prevfps * cvar("hud_engineinfo_framecounter_exponentialmovingaverage_instantupdate_change_threshold")) // if there was a big jump in fps, just force prevfps at current (1/frametime) to make big updates instant
+                               prevfps = (1/frametime);
+                       prevfps = (1 - weight) * prevfps + weight * (1/frametimeavg); // framecounter just used so there's no need for a new variable, think of it as "frametime average"
+               }
+       }
+       else
+       {
+               framecounter += 1;
+               if(time - prevfps_time > cvar("hud_engineinfo_framecounter_time"))
+               {
+                       prevfps = framecounter/cvar("hud_engineinfo_framecounter_time");
+                       framecounter = 0;
+                       prevfps_time = time;
+               }
+       }
+
+       vector color;
+       color = HUD_Get_Num_Color (prevfps, 100);
+       drawstring(pos, strcat("FPS: ", ftos_decimals(prevfps, cvar("hud_engineinfo_framecounter_decimals"))), '1 1 0' * 0.5 * mySize_y, color, HUD_Panel_GetFgAlpha(id), DRAWFLAG_NORMAL);
+}
 /*
 ==================
 Main HUD system
@@ -4114,6 +4385,8 @@ void HUD_Main (void)
                HUD_Chat();
        else
                cvar_set("con_csqcpositioning", "0");
+       if(HUD_Panel_CheckActive(HUD_PANEL_ENGINEINFO) || hud_configure)
+               HUD_EngineInfo();
 
        // TODO hud_'ify these
        if (cvar("cl_showspeed"))