#include <common/notifications/all.qh>
#include <common/stats.qh>
+#include <common/mapinfo.qh>
#include "hud/panel/centerprint.qh"
bool announcer_1min;
{
float starttime = STAT(GAMESTARTTIME);
float roundstarttime = STAT(ROUNDSTARTTIME);
+
+ bool rounds;
+ float countdown;
+
+ // z411 LOG_INFOF("time: %d - starttime: %d - roundstarttime: %d", time, starttime, roundstarttime);
+
if(roundstarttime == -1)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
announcer_countdown = NULL;
return;
}
- if(roundstarttime >= starttime)
- starttime = roundstarttime;
+ //if(roundstarttime >= starttime)
+ // starttime = roundstarttime;
if(starttime <= time && roundstarttime != starttime) // game start time has passed
announcer_5min = announcer_1min = false; // reset maptime announcers now as well
- float countdown = (starttime - time);
+ if(roundstarttime && time >= starttime) {
+ rounds = true;
+ countdown = (roundstarttime - time);
+ } else {
+ rounds = false;
+ countdown = (starttime - time);
+ }
+
float countdown_rounded = floor(0.5 + countdown);
+ if(time >= starttime) centerprint_ClearTitle();
+
if(countdown <= 0) // countdown has finished, starttime is now
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
Local_Notification(MSG_MULTI, MULTI_COUNTDOWN_BEGIN);
delete(this);
announcer_countdown = NULL;
+ centerprint_ClearTitle();
return;
}
else // countdown is still going
{
// if concomitant countdown to round start overrides countdown to game start
- if(roundstarttime == starttime)
+ if(rounds)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTART, countdown_rounded);
Notification annce_num = Announcer_PickNumber(CNT_ROUNDSTART, countdown_rounded);
if(annce_num != NULL)
Local_Notification(MSG_ANNCE, annce_num);
+ this.nextthink = (roundstarttime - (countdown - 1));
}
else
{
Notification annce_num = Announcer_PickNumber(CNT_GAMESTART, countdown_rounded);
if(annce_num != NULL)
Local_Notification(MSG_ANNCE, annce_num);
+ this.nextthink = (starttime - (countdown - 1));
}
-
- this.nextthink = (starttime - (countdown - 1));
+
+
}
}
setthink(announcer_countdown, Announcer_Countdown);
}
+ // z411 set title
+ if(time < STAT(GAMESTARTTIME) && !warmup_stage)
+ centerprint_SetTitle(MapInfo_Type_ToText(gametype));
+
if(time + 5.0 < startTime) // if connecting to server while restart was active don't always play prepareforbattle
- if(time > announcer_countdown.nextthink) { // don't play it again if countdown was already going
- if(teamplay && warmup_stage)
+ if(time > announcer_countdown.nextthink && !warmup_stage) { // don't play it again if countdown was already going
+ if(teamplay && time < startTime)
Local_Notification(MSG_ANNCE, ANNCE_PREPARE_TEAM);
else
Local_Notification(MSG_ANNCE, ANNCE_PREPARE);
int centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
bool centerprint_showing;
+float centerprint_medal_expire_time;
+string centerprint_medal_icon;
+int centerprint_medal_times;
+
+bool centerprint_title_show;
+string centerprint_title;
+
+void centerprint_ClearTitle()
+{
+ centerprint_title_show = false;
+}
+void centerprint_SetTitle(string title)
+{
+ if(title != centerprint_title) {
+ if(centerprint_title)
+ strunzone(centerprint_title);
+ centerprint_title = strzone(title);
+
+ centerprint_title_show = true;
+ }
+}
+
+void centerprint_Medal(string icon, int times)
+{
+ LOG_INFOF("centerprint_Medal: icon: %s times: %d", icon, times);
+
+ centerprint_medal_expire_time = time + autocvar_hud_panel_centerprint_time;
+ centerprint_medal_times = times;
+ if(centerprint_medal_icon)
+ strunzone(centerprint_medal_icon);
+ centerprint_medal_icon = strzone(strcat("gfx/medal/", icon));
+
+ centerprint_showing = true;
+}
+
void centerprint_Add(int new_id, string strMessage, float duration, int countdown_num)
{
TC(int, new_id); TC(int, countdown_num);
int i, j, k, n, g;
float a, sz, align, current_msg_posY = 0, msg_size;
- vector pos;
+ vector pos, mysize, newsize;
string ts;
bool all_messages_expired = true;
pos = panel_pos;
+ height = vid_conheight/50 * 4;
+ pos.y -= height;
+
+ // z411 draw medals first
+ if (centerprint_medal_expire_time > time) {
+ //if(centerprint_medal_expire_time - time > 1)
+ // a = 1;
+ //else
+ // a = min(1, 1 - ((centerprint_medal_expire_time - time + 2) * (1/3)));
+
+ mysize = draw_getimagesize(centerprint_medal_icon);
+ newsize = vec2(height*(mysize.x/mysize.y), height);
+
+ //fontsize = '1 1 0' * vid_conheight/50 * autocvar_hud_panel_centerprint_fontscale;
+ //drawcolorcodedstring(pos + eY * 0.5 * (1 - sz * hud_scale.x) * fontsize.y, ts, fontsize, 1, DRAWFLAG_NORMAL);
+ //drawstring(pos, centerprint_medal_icon, fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+ drawpic(pos + eX * 0.5 * panel_size.x - eX * (newsize.x / 2), centerprint_medal_icon, newsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+
+ all_messages_expired = false;
+ }
+
+ // continue with normal procedure
+ pos.y += height;
+
+ // z411 title
+ if(centerprint_title_show) {
+ fontsize = '1 1 0' * vid_conheight/50 * autocvar_hud_panel_centerprint_fontscale * 1.5;
+ drawstring(pos + '0.5 0 0' * (panel_size.x - stringwidth(centerprint_title, true, fontsize)), centerprint_title, fontsize, '1 1 1', 1, DRAWFLAG_NORMAL);
+ pos.y += fontsize.y + (fontsize.y / 4);
+
+ all_messages_expired = false;
+ }
+
+ // continue with normal procedure this time
+
if (autocvar_hud_panel_centerprint_flip)
pos.y += panel_size.y;
align = bound(0, autocvar_hud_panel_centerprint_align, 1);
#pragma once
#include "../panel.qh"
+void centerprint_ClearTitle();
+void centerprint_SetTitle(string title);
+void centerprint_Medal(string icon, int times);
void centerprint_Add(int new_id, string strMessage, float duration, int countdown_num);
void centerprint_AddStandard(string strMessage);
void centerprint_Kill(int id);
#include <common/mapobjects/target/music.qh>
#include <common/teams.qh>
#include <common/wepent.qh>
+#include <common/notifications/_mod.qh>
#include <common/weapons/weapon/tuba.qh>
UpdateDamage();
HUD_Crosshair(this);
HitSound();
+ Local_Notification_Queue_Process();
}
void ViewLocation_Mouse()
FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, true, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, thiswep.m_id);
if(yoda && flying)
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+ Send_Notification(NOTIF_ONE, actor, MSG_MEDAL, MEDAL_YODA);
if(damage_goodhits && actor.oknex_lasthit)
{
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ //Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ Send_Notification(NOTIF_ONE, actor, MSG_MEDAL, MEDAL_IMPRESSIVE);
damage_goodhits = 0; // only every second time
}
MSG_ANNCE_NOTIF(INSTAGIB_NARROWLY, N_GNTLOFF, "narrowly", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
MSG_ANNCE_NOTIF(INSTAGIB_TERMINATED, N_GNTLOFF, "terminated", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
- MSG_ANNCE_NOTIF(MULTIFRAG, N___NEVER, "multifrag", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
+ MSG_ANNCE_NOTIF(MULTIFRAG, N_GNTLOFF, "multifrag", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
+ MSG_ANNCE_NOTIF(FIRSTBLOOD, N_GNTLOFF, "firstblood", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
MSG_ANNCE_NOTIF(NUM_1, N__ALWAYS, "1", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
MSG_ANNCE_NOTIF(NUM_2, N__ALWAYS, "2", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
MSG_ANNCE_NOTIF(ROUND_TIED, N__ALWAYS, "round_tied", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
MSG_ANNCE_NOTIF(ALONE, N__ALWAYS, "alone", CH_INFO, VOL_BASEVOICE, ATTEN_NONE)
+// MSG_MEDAL_NOTIFICATIONS
+ MSG_MEDAL_NOTIF(AIRSHOT, N__ALWAYS, "airshot", ANNCE_ACHIEVEMENT_AIRSHOT)
+ MSG_MEDAL_NOTIF(HEADSHOT, N__ALWAYS, "headshot", ANNCE_HEADSHOT)
+ MSG_MEDAL_NOTIF(IMPRESSIVE, N__ALWAYS, "impressive", ANNCE_ACHIEVEMENT_IMPRESSIVE)
+ MSG_MEDAL_NOTIF(YODA, N__ALWAYS, "yoda", ANNCE_ACHIEVEMENT_YODA)
+
+ MSG_MEDAL_NOTIF(KILLSTREAK_03, N__ALWAYS, "killstreak_03", ANNCE_KILLSTREAK_03)
+ MSG_MEDAL_NOTIF(KILLSTREAK_05, N__ALWAYS, "killstreak_05", ANNCE_KILLSTREAK_05)
+ MSG_MEDAL_NOTIF(KILLSTREAK_10, N__ALWAYS, "killstreak_10", ANNCE_KILLSTREAK_10)
+ MSG_MEDAL_NOTIF(KILLSTREAK_15, N__ALWAYS, "killstreak_15", ANNCE_KILLSTREAK_15)
+ MSG_MEDAL_NOTIF(KILLSTREAK_20, N__ALWAYS, "killstreak_20", ANNCE_KILLSTREAK_20)
+ MSG_MEDAL_NOTIF(KILLSTREAK_25, N__ALWAYS, "killstreak_25", ANNCE_KILLSTREAK_25)
+ MSG_MEDAL_NOTIF(KILLSTREAK_30, N__ALWAYS, "killstreak_30", ANNCE_KILLSTREAK_30)
+
+ MSG_MEDAL_NOTIF(FIRSTBLOOD, N__ALWAYS, "firstblood", ANNCE_FIRSTBLOOD)
+
+
#undef N___NEVER
#undef N_GNTLOFF
#undef N__ALWAYS
case MSG_CENTER:
case MSG_MULTI:
case MSG_CHOICE:
+ case MSG_MEDAL:
break;
default:
LOG_INFOF(
}
}
+void Create_Notification_Entity_Medal(entity notif,
+ float var_cvar,
+ string namestring,
+ /* MSG_MEDAL */
+ string icon,
+ Notification anncename)
+ {
+ if (icon != "") { notif.nent_icon = strzone(icon); }
+ if (anncename) { notif.nent_msgannce = anncename; }
+ }
// ===============
// Cvar Handling
int NOTIF_CENTER_COUNT = 0;
int NOTIF_MULTI_COUNT = 0;
int NOTIF_CHOICE_COUNT = 0;
+ int NOTIF_MEDAL_COUNT = 0;
FOREACH(Notifications, true, {
switch (it.nent_type)
{
case MSG_CENTER: ++NOTIF_CENTER_COUNT; break;
case MSG_MULTI: ++NOTIF_MULTI_COUNT; break;
case MSG_CHOICE: ++NOTIF_CHOICE_COUNT; break;
+ case MSG_MEDAL: ++NOTIF_MEDAL_COUNT; break;
}
});
"Allow choice for this notification 0 = off, 1 = only in warmup mode, 2 = always"
);
});
+
+ NOTIF_WRITE(sprintf("\n// MSG_MEDAL notifications (count = %d):\n", NOTIF_MEDAL_COUNT));
+ FOREACH(Notifications, it.nent_type == MSG_MEDAL && (!it.nent_teamnum || it.nent_teamnum == NUM_TEAM_1), {
+ NOTIF_WRITE_ENTITY(it,
+ "Enable this multiple notification"
+ );
+ });
// edit these to match whichever cvars are used for specific notification options
NOTIF_WRITE("\n// HARD CODED notification variables:\n");
NOTIF_INFO_COUNT +
NOTIF_CENTER_COUNT +
NOTIF_MULTI_COUNT +
- NOTIF_CHOICE_COUNT
+ NOTIF_CHOICE_COUNT +
+ NOTIF_MEDAL_COUNT
),
NOTIF_ANNCE_COUNT,
NOTIF_INFO_COUNT,
NOTIF_CENTER_COUNT,
NOTIF_MULTI_COUNT,
- NOTIF_CHOICE_COUNT
+ NOTIF_CHOICE_COUNT,
+ NOTIF_MEDAL_COUNT
));
#undef NOTIF_WRITE_HARDCODED
#undef NOTIF_WRITE_ENTITY
#endif
centerprint_Add(ORDINAL(cpid), input, stof(arg_slot[0]), stof(arg_slot[1]));
}
+
+void Local_Notification_Queue_Run(MSG net_type, entity notif)
+{
+ switch (net_type)
+ {
+ case MSG_ANNCE:
+ {
+ Local_Notification_sound(notif.nent_channel, notif.nent_snd, notif.nent_vol, notif.nent_position);
+ break;
+ }
+
+ case MSG_MEDAL:
+ {
+ centerprint_Medal(notif.nent_icon, 1);
+ Local_Notification_sound(notif.nent_msgannce.nent_channel, notif.nent_msgannce.nent_snd, notif.nent_msgannce.nent_vol, notif.nent_msgannce.nent_position);
+ break;
+ }
+ }
+}
+
+void Local_Notification_Queue_Add(MSG net_type, entity notif, float queue_time)
+{
+ if(notif_queue_length >= NOTIF_QUEUE_MAX)
+ return;
+
+ //LOG_INFOF("Comparison %d > %d", time, notif_queue_next_time);
+
+ if(time > notif_queue_next_time) {
+ //LOG_INFOF("Running NOW!");
+ Local_Notification_Queue_Run(net_type, notif);
+ notif_queue_next_time = time + queue_time;
+ } else {
+ //LOG_INFOF("Queueing: %d %d", notif_queue_length, notif_queue_next_time);
+ notif_queue_type[notif_queue_length] = net_type;
+ notif_queue_entity[notif_queue_length] = notif;
+ notif_queue_time[notif_queue_length] = notif_queue_next_time;
+
+ notif_queue_next_time += queue_time;
+ ++notif_queue_length;
+ }
+}
+
+void Local_Notification_Queue_Process()
+{
+ if(!notif_queue_length)
+ return;
+
+ int j;
+
+ if(notif_queue_time[0] <= time) {
+ //LOG_INFOF("Process running: %d <= %d", notif_queue_time[0], time);
+ Local_Notification_Queue_Run(notif_queue_type[0], notif_queue_entity[0]);
+
+ // Shift queue to the left
+ for (j = 0; j < notif_queue_length - 1; j++) {
+ notif_queue_type[j] = notif_queue_type[j+1];
+ notif_queue_entity[j] = notif_queue_entity[j+1];
+ notif_queue_time[j] = notif_queue_time[j+1];
+ }
+
+ --notif_queue_length;
+ }
+}
+
#endif
void Local_Notification(MSG net_type, Notification net_name, ...count)
case MSG_ANNCE:
{
#ifdef CSQC
- Local_Notification_sound(notif.nent_channel, notif.nent_snd, notif.nent_vol, notif.nent_position);
+ //Local_Notification_sound(notif.nent_channel, notif.nent_snd, notif.nent_vol, notif.nent_position);
+ Local_Notification_Queue_Add(net_type, notif, 1);
#else
backtrace("MSG_ANNCE on server?... Please notify Samual immediately!\n");
#endif
found_choice.nent_floatcount,
s1, s2, s3, s4,
f1, f2, f3, f4);
+ break;
}
+
+ #ifdef CSQC
+ case MSG_MEDAL:
+ {
+ Local_Notification_Queue_Add(net_type, notif, 3);
+ break;
+ }
+ #endif
}
}
CASE(MSG, CHOICE)
/** Kill centerprint message @deprecated */
CASE(MSG, CENTER_KILL)
+ /** Medal notification */
+ CASE(MSG, MEDAL)
ENUMCLASS_END(MSG)
string Get_Notif_TypeName(MSG net_type)
case MSG_CENTER: return "MSG_CENTER";
case MSG_MULTI: return "MSG_MULTI";
case MSG_CHOICE: return "MSG_CHOICE";
+ case MSG_MEDAL: return "MSG_MEDAL";
}
LOG_WARNF("Get_Notif_TypeName(%d): Improper net type!", ORDINAL(net_type));
return "";
Notification optiona,
Notification optionb);
+void Create_Notification_Entity_Medal(entity notif,
+ float var_cvar,
+ string namestring,
+ /* MSG_MEDAL */
+ string icon,
+ Notification anncename);
+
void Dump_Notifications(int fh, bool alsoprint);
GENERIC_COMMAND(dumpnotifs, "Dump all notifications into notifications_dump.txt", false)
const float NOTIF_MAX_HUDARGS = 2;
const float NOTIF_MAX_DURCNT = 2;
+#ifdef CSQC
+const int NOTIF_QUEUE_MAX = 10;
+entity notif_queue_entity[NOTIF_QUEUE_MAX];
+MSG notif_queue_type[NOTIF_QUEUE_MAX];
+float notif_queue_time[NOTIF_QUEUE_MAX];
+float notif_queue_next_time;
+int notif_queue_length;
+
+void Local_Notification_Queue_Process();
+#endif
+
string arg_slot[NOTIF_MAX_ARGS];
const float ARG_CS_SV_HA = 1; // enabled on CSQC, SVQC, and Hudargs
optiona, /* optiona */ \
optionb); /* optionb */ \
}
+
+#define MSG_MEDAL_NOTIF(name, defaultvalue, icon, anncename) \
+ NOTIF_ADD_AUTOCVAR(MEDAL_##name, defaultvalue) \
+ MSG_MEDAL_NOTIF_(0, MEDAL_##name, MEDAL_##name, defaultvalue, icon, anncename)
+
+#define MSG_MEDAL_NOTIF_(teamnum, name, cvarname, defaultvalue, icon, anncename) \
+ REGISTER(Notifications, name, m_id, new_pure(msg_medal_notification)) { \
+ Create_Notification_Entity (this, defaultvalue, ACVNN(cvarname), MSG_MEDAL, strtoupper(#name), teamnum); \
+ Create_Notification_Entity_Medal(this, ACVNN(cvarname), strtoupper(#name), \
+ icon, \
+ anncename); \
+ }
REGISTRY_BEGIN(Notifications)
{
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ if(IsFlying(directhitentity)) {
+ //Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ Send_Notification(NOTIF_ONE, this.realowner, MSG_MEDAL, MEDAL_AIRSHOT);
+ }
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ if(IsFlying(directhitentity)) {
+ //Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ Send_Notification(NOTIF_ONE, this.realowner, MSG_MEDAL, MEDAL_AIRSHOT);
+ }
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
if(IS_PLAYER(directhitentity))
if(DIFF_TEAM(this.realowner, directhitentity))
if(!IS_DEAD(directhitentity))
- if(IsFlying(directhitentity))
- Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ if(IsFlying(directhitentity)) {
+ //Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+ Send_Notification(NOTIF_ONE, this.realowner, MSG_MEDAL, MEDAL_AIRSHOT);
+ }
this.event_damage = func_null;
this.takedamage = DAMAGE_NO;
SendCSQCVaporizerBeamParticle(actor, damage_goodhits);
if(yoda && flying)
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+ Send_Notification(NOTIF_ONE, actor, MSG_MEDAL, MEDAL_YODA);
if(damage_goodhits && actor.vaporizer_lasthit)
{
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ Send_Notification(NOTIF_ONE, actor, MSG_MEDAL, MEDAL_IMPRESSIVE);
damage_goodhits = 0; // only every second time
}
FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, false, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, dtype);
if(yoda && flying)
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+ Send_Notification(NOTIF_ONE, actor, MSG_MEDAL, MEDAL_YODA);
if(damage_goodhits && actor.vortex_lasthit)
{
- Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ //Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+ Send_Notification(NOTIF_ONE, actor, MSG_MEDAL, MEDAL_IMPRESSIVE);
damage_goodhits = 0; // only every second time
}
int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol);
const int MAX_SPECTATORS = 7;
+
+#define GIVE_MEDAL(entity,medalname) \
+ Send_Notification(NOTIF_ONE, entity, MSG_ANNCE, ANNCE_ACHIEVEMENT_##medalname); \
+ Send_Notification(NOTIF_ONE, entity, MSG_MEDAL, MEDAL_##medalname);
CS(attacker).killcount = CS(attacker).killcount + 1;
attacker.killsound += 1;
-
+
// TODO: improve SPREE_ITEM and KILL_SPREE_LIST
// these 2 macros are spread over multiple files
#define SPREE_ITEM(counta,countb,center,normal,gentle) \
case counta: \
- Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
+ Send_Notification(NOTIF_ONE, attacker, MSG_MEDAL, MEDAL_KILLSTREAK_##countb); \
if (!warmup_stage) \
PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
break;
{
checkrules_firstblood = true;
notif_firstblood = true; // modify the current messages so that they too show firstblood information
+ Send_Notification(NOTIF_ONE, attacker, MSG_MEDAL, MEDAL_FIRSTBLOOD);
PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
PlayerStats_GameReport_Event_Player(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
BADCVAR("g_forced_respawn");
BADCVAR("g_freezetag_point_leadlimit");
BADCVAR("g_freezetag_point_limit");
+ BADCVAR("g_freezetag_revive_respawn");
+ BADCVAR("g_freezetag_round_stop");
+ BADCVAR("g_freezetag_round_respawn");
BADCVAR("g_glowtrails");
BADCVAR("g_hats");
BADCVAR("g_casings");