X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fnotifications.qc;h=1fc3a052147027085ff0db9f5af0efb9203a86a3;hb=902776d303651e49fd84100459abd860f8a50d23;hp=26505273c5f57a1db86e496317785dfcde95010b;hpb=e53a7fa61810047536f1e2b2da0a7d0bc5c8c8a0;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/notifications.qc b/qcsrc/common/notifications.qc index 26505273c..1fc3a0521 100644 --- a/qcsrc/common/notifications.qc +++ b/qcsrc/common/notifications.qc @@ -1,114 +1,100 @@ // ================================================ // Unified notification system, written by Samual -// Last updated: December, 2012 +// Last updated: February, 2013 // ================================================ -// ====================== -// Supporting Functions -// ====================== - -// team code replace -string TCR(string input, string teamcolor, string teamtext) // TODO: MOVE TO UTIL.QC -{ - input = strreplace("^TC", teamcolor, input); - input = strreplace("^TT", teamtext, input); - return input; -} - -// color code replace, place inside of sprintf and parse the string -string CCR(string input) // TODO: MOVE TO UTIL.QC +string Get_Notif_TypeName(float net_type) { - // foreground/normal colors - input = strreplace("^F1", "^2", input); // primary priority (important names, etc) - input = strreplace("^F2", "^3", input); // secondary priority (items, locations, numbers, etc) - - // "kill" colors - input = strreplace("^K1", "^1", input); // "bad" or "dangerous" text (death messages against you, kill notifications, etc) - input = strreplace("^K2", "^3", input); // similar to above, but less important... OR, a highlight out of above message type - input = strreplace("^K3", "^4", input); // "good" or "beneficial" text (you fragging someone, etc) - - // background colors - input = strreplace("^BG", "^7", input); // neutral/unimportant text - input = strreplace("^N", "^7", input); // "none"-- reset to white... - return input; + switch(net_type) + { + case MSG_INFO: return "MSG_INFO"; + case MSG_CENTER: return "MSG_CENTER"; + case MSG_WEAPON: return "MSG_WEAPON"; + case MSG_DEATH: return "MSG_DEATH"; + } + backtrace(sprintf("Get_Notif_TypeName(%d): Improper net type!\n", net_type)); + return "your ass"; } -#ifndef MENUQC -// select between the normal or the gentle message string based on client (or server) settings -string normal_or_gentle(string normal, string gentle) +entity Get_Notif_Ent(float net_type, float net_name) { - #ifdef CSQC - if(autocvar_cl_gentle || autocvar_cl_gentle_messages) - #else - if(autocvar_sv_gentle) - #endif - return ((gentle != "") ? gentle : normal); - else - return normal; + switch(net_type) + { + case MSG_INFO: return msg_info_notifs[net_name - 1]; + case MSG_CENTER: return msg_center_notifs[net_name - 1]; + case MSG_WEAPON: return msg_weapon_notifs[net_name - 1]; + case MSG_DEATH: return msg_death_notifs[net_name - 1]; + } + backtrace(sprintf("Get_Notif_Ent(%d, %d): Improper net type!\n", net_type, net_name)); + return world; } -float notif_checkstring(string input) +string Notification_CheckArgs_TypeName(float net_type, float net_name) { - if not(input == "") { return TRUE; } - else { return FALSE; } + // check supplied type and name for errors + string checkargs = ""; + #define CHECKARG_TYPENAME(type) case MSG_##type##: \ + { if(!net_name || (net_name > NOTIF_##type##_COUNT)) \ + { checkargs = sprintf("Improper name: %d!", net_name); } break; } + switch(net_type) + { + CHECKARG_TYPENAME(INFO) + CHECKARG_TYPENAME(CENTER) + CHECKARG_TYPENAME(WEAPON) + CHECKARG_TYPENAME(DEATH) + default: { checkargs = sprintf("Improper type: %d!", checkargs, net_type); break; } + } + #undef CHECKARG_TYPENAME + return checkargs; } -// get the actual name of a notification and return it as a string -string Get_Field_Value(float field, float net_type, float net_name) +#ifdef SVQC +string Notification_CheckArgs(float broadcast, entity client, float net_type, float net_name) { - string output = ""; - - #define GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) \ - switch(field) { \ - case F_NAME: { output = VAR_TO_TEXT(name); break; } \ - case F_STRNUM: { output = ftos(strnum); break; } \ - case F_FLNUM: { output = ftos(flnum); break; } } - - switch(net_type) + // check supplied broadcast, target, type, and name for errors + string checkargs = Notification_CheckArgs_TypeName(net_type, net_name); + if(checkargs != "") { checkargs = strcat(checkargs, " "); } + switch(broadcast) { - case MSG_INFO: + case NOTIF_ONE: + case NOTIF_ONE_ONLY: { - #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \ - { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } } - MSG_INFO_NOTIFICATIONS - #undef MSG_INFO_NOTIF + if(IS_NOT_A_CLIENT(client)) + { checkargs = sprintf("%sNo client provided!", checkargs); } break; } - case MSG_CENTER: + + case NOTIF_ANY_EXCEPT: { - #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \ - { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name,strnum,flnum) } } - MSG_CENTER_NOTIFICATIONS - #undef MSG_CENTER_NOTIF + if(IS_NOT_A_CLIENT(client)) + { checkargs = sprintf("%sException can't be a non-client!", checkargs); } break; } - case MSG_WEAPON: + + case NOTIF_ANY: { - #define MSG_WEAPON_NOTIF(name,infoname,centername) \ - { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name, \ - max(stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername))), \ - max(stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)))) } } - MSG_WEAPON_NOTIFICATIONS - #undef MSG_WEAPON_NOTIF + if(client) + { checkargs = sprintf("%sEntity provided when world was required!", checkargs); } break; } - case MSG_DEATH: + + case NOTIF_TEAM: + case NOTIF_TEAM_EXCEPT: { - #define MSG_DEATH_NOTIF(name,infoname,centername) \ - { NOTIF_MATCH(name, net_name) { GET_FIELD_VALUE_OUTPUT(field,name, \ - max(stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername))), \ - max(stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)))) } } - MSG_DEATH_NOTIFICATIONS - #undef MSG_DEATH_NOTIF + if not(teamplay) { checkargs = sprintf("%sTeamplay not active!", checkargs); } + else if(IS_NOT_A_CLIENT(client)) + { + if(broadcast == NOTIF_TEAM) { checkargs = sprintf("%sNo client provided!", checkargs); } + else { checkargs = sprintf("%sException can't be a non-client!", checkargs); } + } break; } + + default: { checkargs = sprintf("%sImproper broadcast: %d!", checkargs, broadcast); break; } } - - #undef GET_FIELD_VALUE_OUTPUT - return output; + return checkargs; } -#endif // ifndef MENUQC - +#endif // =============================== // Frontend Notification Pushing @@ -116,176 +102,348 @@ string Get_Field_Value(float field, float net_type, float net_name) void Dump_Notifications(float fh, float alsoprint) { - float MSG_INFO_NOTIFS = 0, MSG_CENTER_NOTIFS = 0, MSG_WEAPON_NOTIFS = 0, MSG_DEATH_NOTIFS = 0; + #define NOTIF_WRITE(a) { \ + fputs(fh, a); \ + if(alsoprint) { print(a); } } + #define NOTIF_WRITE_SETA(name,default,text) { \ + notif_msg = \ + sprintf( \ + "seta notification_%s %d \"notif string: %s^7\"\n", \ + name, default, strreplace("\{3}", "", strreplace("\n", "\\n", text)) \ + ); \ + NOTIF_WRITE(notif_msg) } + string notif_msg; + float i; + entity e; + + // Note: This warning only applies to the notifications.cfg file that is output... + + // You ARE supposed to manually edit this function to add i.e. hard coded + // notification variables for mutators or game modes or such and then + // regenerate the notifications.cfg file from the new code. + + NOTIF_WRITE("// ********************************************** //\n"); + NOTIF_WRITE("// ** WARNING - DO NOT MANUALLY EDIT THIS FILE ** //\n"); + NOTIF_WRITE("// ** ** //\n"); + NOTIF_WRITE("// ** This file is automatically generated ** //\n"); + NOTIF_WRITE("// ** by code with the command 'dumpnotifs'. ** //\n"); + NOTIF_WRITE("// ** ** //\n"); + NOTIF_WRITE("// ** If you add a new notification, please ** //\n"); + NOTIF_WRITE("// ** regenerate this file with that command ** //\n"); + NOTIF_WRITE("// ** making sure that the output matches ** //\n"); + NOTIF_WRITE("// ** with the lists and defaults in code. ** //\n"); + NOTIF_WRITE("// ** ** //\n"); + NOTIF_WRITE("// ********************************************** //\n"); + + // These notifications will also append their string as a comment... + // This is not necessary, and does not matter if they vary between config versions, + // it is just a semi-helpful tool for those who want to manually change their user settings. + + NOTIF_WRITE(sprintf("\n// MSG_INFO notifications (count = %d):\n", NOTIF_INFO_COUNT)); + for(i = 1; i <= NOTIF_INFO_COUNT; ++i) + { + e = Get_Notif_Ent(MSG_INFO, i); + if not(e) { backtrace("Dump_Notifications(): Missing notification entity!\n"); return; } + NOTIF_WRITE_SETA(e.nent_name, e.nent_default, e.nent_string); + } - #define NOTIF_WRITE(type,name,text) notif_msg = sprintf("seta %s 1 // %s - %s\n", name, type, strreplace("\n", "\\n", text)); fputs(fh, notif_msg); if(alsoprint) { print(strreplace("^", "^^", notif_msg)); } - #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) { ++MSG_INFO_NOTIFS; NOTIF_WRITE("MSG_INFO", VAR_TO_TEXT(name), normal) } - #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) { ++MSG_CENTER_NOTIFS; NOTIF_WRITE("MSG_CENTER", VAR_TO_TEXT(name), normal) } - #define MSG_WEAPON_NOTIF(name,infoname,centername) { ++MSG_WEAPON_NOTIFS; NOTIF_WRITE("MSG_WEAPON", VAR_TO_TEXT(name),sprintf("infoname: %s, centername: %s", VAR_TO_TEXT(infoname), VAR_TO_TEXT(centername))) } - #define MSG_DEATH_NOTIF(name,infoname,centername) { ++MSG_DEATH_NOTIFS; NOTIF_WRITE("MSG_DEATH", VAR_TO_TEXT(name), sprintf("infoname: %s, centername: %s", VAR_TO_TEXT(infoname), VAR_TO_TEXT(centername))) } - MSG_INFO_NOTIFICATIONS - MSG_CENTER_NOTIFICATIONS - MSG_WEAPON_NOTIFICATIONS - MSG_DEATH_NOTIFICATIONS - #undef NOTIF_WRITE - #undef MSG_INFO_NOTIF - #undef MSG_CENTER_NOTIF - #undef MSG_WEAPON_NOTIF - #undef MSG_DEATH_NOTIF + NOTIF_WRITE(sprintf("\n// MSG_CENTER notifications (count = %d):\n", NOTIF_CENTER_COUNT)); + for(i = 1; i <= NOTIF_CENTER_COUNT; ++i) + { + e = Get_Notif_Ent(MSG_CENTER, i); + if not(e) { backtrace("Dump_Notifications(): Missing notification entity!\n"); return; } + NOTIF_WRITE_SETA(e.nent_name, e.nent_default, e.nent_string); + } + + NOTIF_WRITE(sprintf("\n// MSG_WEAPON notifications (count = %d):\n", NOTIF_WEAPON_COUNT)); + for(i = 1; i <= NOTIF_WEAPON_COUNT; ++i) + { + e = Get_Notif_Ent(MSG_WEAPON, i); + if not(e) { backtrace("Dump_Notifications(): Missing notification entity!\n"); return; } + NOTIF_WRITE_SETA(e.nent_name, e.nent_default, sprintf("infoname: %s, centername: %s", + e.nent_msginfo.nent_name, e.nent_msgcenter.nent_name)); + } + + NOTIF_WRITE(sprintf("\n// MSG_DEATH notifications (count = %d):\n", NOTIF_DEATH_COUNT)); + for(i = 1; i <= NOTIF_DEATH_COUNT; ++i) + { + e = Get_Notif_Ent(MSG_DEATH, i); + if not(e) { backtrace("Dump_Notifications(): Missing notification entity!\n"); return; } + NOTIF_WRITE_SETA(e.nent_name, e.nent_default, sprintf("infoname: %s, centername: %s", + e.nent_msginfo.nent_name, e.nent_msgcenter.nent_name)); + } + + // edit these to match whichever cvars are used for specific notification options + NOTIF_WRITE("\n// HARD CODED notification variables:\n"); + NOTIF_WRITE("seta notification_allow_chatboxprint 1 \"Allow notifications to be printed to chat box by setting notification cvar to 2 (You can also set this cvar to 2 to force ALL notifications to be printed to the chatbox)\"\n"); + NOTIF_WRITE("seta notification_show_location 0 \"Append location information to MSG_INFO death/kill messages\"\n"); + NOTIF_WRITE("seta notification_show_location_string \"\" \"Replacement string piped into sprintf, so you can do different messages like this: ' at the %s' or ' (near %s)'\"\n"); + NOTIF_WRITE("seta notification_show_sprees 1 \"Print information about sprees in death/kill messages\"\n"); + NOTIF_WRITE("seta notification_show_sprees_center 1 \"Show spree information in MSG_CENTER messages... 0 = off, 1 = target (but only for first victim) and attacker\"\n"); + NOTIF_WRITE("seta notification_show_sprees_center_specialonly 1 \"Don't show spree information in MSG_CENTER messages if it isn't an achievement\"\n"); + NOTIF_WRITE("seta notification_show_sprees_info 3 \"Show spree information in MSG_INFO messages... 0 = off, 1 = target only, 2 = attacker only, 3 = target and attacker\"\n"); + NOTIF_WRITE("seta notification_show_sprees_info_newline 0 \"Show attacker spree information for MSG_INFO messages on a separate line than the death notification itself\"\n"); + NOTIF_WRITE("seta notification_show_sprees_info_specialonly 1 \"Don't show attacker spree information in MSG_INFO messages if it isn't an achievement\"\n"); + NOTIF_WRITE("seta notification_errors_are_fatal 1 \"If a notification fails upon initialization, cause a Host_Error to stop the program\"\n"); + NOTIF_WRITE("seta notification_ctf_pickup_team_verbose 1 \"Show extra information if a team mate picks up a flag\"\n"); + NOTIF_WRITE("seta notification_ctf_pickup_enemy_verbose 1 \"Show extra information if an enemy picks up a flag\"\n"); + NOTIF_WRITE("seta notification_ctf_capture_verbose 1 \"Show extra information when someone captures a flag\"\n"); + NOTIF_WRITE("seta notification_frag_verbose 1 \"Show extra information when you frag someone (or when you are fragged\"\n"); + NOTIF_WRITE("seta notification_lifetime_runtime 0.5 \"Amount of time that notification entities last on the server during runtime (In seconds)\"\n"); + NOTIF_WRITE("seta notification_lifetime_mapload 10 \"Amount of time that notification entities last immediately at mapload (in seconds) to help prevent notifications from being lost on early init (like gamestart countdown)\"\n"); + + NOTIF_WRITE(sprintf("\n// Notification counts (total = %d): MSG_INFO = %d, MSG_CENTER = %d, MSG_WEAPON = %d, MSG_DEATH = %d\n", + (NOTIF_INFO_COUNT + NOTIF_CENTER_COUNT + NOTIF_WEAPON_COUNT + NOTIF_DEATH_COUNT), + NOTIF_INFO_COUNT, NOTIF_CENTER_COUNT, NOTIF_WEAPON_COUNT, NOTIF_DEATH_COUNT)); - print(sprintf("Notification counts: MSG_INFO = %d, MSG_CENTER = %d, MSG_WEAPON = %d, MSG_DEATH = %d\n", MSG_INFO_NOTIFS, MSG_CENTER_NOTIFS, MSG_WEAPON_NOTIFS, MSG_DEATH_NOTIFS)); return; + #undef NOTIF_WRITE_SETA + #undef NOTIF_WRITE } -#ifndef MENUQC -#ifdef CSQC -void HUD_Notify_Push(string icon, string attacker, string victim) +#ifdef SVQC +void Notification_GetCvars() { - if(icon != "") - { - --kn_index; - if (kn_index == -1) { kn_index = KN_MAX_ENTRIES-1; } - killnotify_times[kn_index] = time; + GetCvars_handleFloat(get_cvars_s, get_cvars_f, FRAG_VERBOSE, "notification_frag_verbose"); +} +#endif - // icon - if(killnotify_icon[kn_index]) { strunzone(killnotify_icon[kn_index]); } - killnotify_icon[kn_index] = strzone(icon); +string Local_Notification_sprintf(string input, string args, + string s1, string s2, string s3, string s4, + float f1, float f2, float f3, float f4) +{ + #ifdef NOTIFICATIONS_DEBUG + dprint( + sprintf("Local_Notification_sprintf('%s^7', '%s', %s, %s);\n", + strreplace("\n", "\\n", input), + args, + sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4), + sprintf("%d, %d, %d, %d", f1, f2, f3, f4) + ) + ); + #endif + + string selected; + float sel_num; + for(sel_num = 0; sel_num < NOTIF_MAX_ARGS; ++sel_num) { arg_slot[sel_num] = ""; } - // attacker - if(killnotify_attackers[kn_index]) { strunzone(killnotify_attackers[kn_index]); } - killnotify_attackers[kn_index] = strzone(attacker); + string tmp_s; - // victim - if(killnotify_victims[kn_index]) { strunzone(killnotify_victims[kn_index]); } - killnotify_victims[kn_index] = strzone(victim); + for(sel_num = 0;(args != "");) + { + selected = car(args); args = cdr(args); + NOTIF_HIT_MAX(NOTIF_MAX_ARGS, "Local_Notification_sprintf") + switch(strtolower(selected)) + { + #define ARG_CASE(prog,selected,result) \ + #ifdef CSQC \ + #if (prog != ARG_SV) \ + case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \ + #endif \ + #else \ + #if (prog != ARG_CS) \ + case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \ + #endif \ + #endif + NOTIF_ARGUMENT_LIST + #undef ARG_CASE + default: NOTIF_HIT_UNKNOWN(NOTIF_MAX_ARGS, "Local_Notification_sprintf") + } } + return sprintf(input, arg_slot[0], arg_slot[1], arg_slot[2], arg_slot[3], arg_slot[4], arg_slot[5], arg_slot[6]); } -void backtrace(string msg) // TODO: MOVE TO UTIL.QC +#ifdef CSQC +void Local_Notification_HUD_Notify_Push(string icon, string hudargs, string s1, string s2, string s3, string s4) { - float dev, war; - dev = cvar("developer"); - war = cvar("prvm_backtraceforwarnings"); - cvar_set("developer", "1"); - cvar_set("prvm_backtraceforwarnings", "1"); - print("\n"); - print("--- CUT HERE ---\nWARNING: "); - print(msg); - print("\n"); - remove(world); // isn't there any better way to cause a backtrace? - print("\n--- CUT UNTIL HERE ---\n"); - cvar_set("developer", ftos(dev)); - cvar_set("prvm_backtraceforwarnings", ftos(war)); + string selected; + float sel_num; + arg_slot[0] = ""; arg_slot[1] = ""; + + for(sel_num = 0;(hudargs != "");) + { + selected = car(hudargs); hudargs = cdr(hudargs); + NOTIF_HIT_MAX(NOTIF_MAX_HUDARGS, "Local_Notification_HUD_Notify_Push") + switch(strtolower(selected)) + { + #define ARG_CASE(prog,selected,result) \ + #if (prog == ARG_CS_SV_HA) \ + case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \ + #endif + NOTIF_ARGUMENT_LIST + #undef ARG_CASE + default: NOTIF_HIT_UNKNOWN(NOTIF_MAX_HUDARGS, "Local_Notification_HUD_Notify_Push") + } + } + HUD_Notify_Push(icon, arg_slot[0], arg_slot[1]); } -#endif // ifdef CSQC + +void Local_Notification_centerprint_generic(string input, string durcnt, float cpid, float f1, float f2) +{ + string selected; + float sel_num; + arg_slot[0] = ""; arg_slot[1] = ""; + + for(sel_num = 0;(durcnt != "");) + { + selected = car(durcnt); durcnt = cdr(durcnt); + NOTIF_HIT_MAX(NOTIF_MAX_DURCNT, "Local_Notification_centerprint_generic") + switch(strtolower(selected)) + { + #define ARG_CASE(prog,selected,result) \ + #if (prog == ARG_CS_SV_DC) \ + case selected: { arg_slot[sel_num] = result; ++sel_num; break; } \ + #endif + NOTIF_ARGUMENT_LIST + #undef ARG_CASE + default: + { + if(ftos(stof(selected)) != "") { arg_slot[sel_num] = selected; ++sel_num; } + else { NOTIF_HIT_UNKNOWN(NOTIF_MAX_DURCNT, "Local_Notification_centerprint_generic") } + break; + } + } + } + centerprint_generic(cpid, input, stof(arg_slot[0]), stof(arg_slot[1])); +} +#endif void Local_Notification(float net_type, float net_name, ...count) { - float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name)); - float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name)); - - string s1 = ((0 < stringcount) ? ...(0, string) : NO_STR_ARG); - string s2 = ((1 < stringcount) ? ...(1, string) : NO_STR_ARG); - string s3 = ((2 < stringcount) ? ...(2, string) : NO_STR_ARG); - string s4 = ((3 < stringcount) ? ...(3, string) : NO_STR_ARG); - float f1 = ((stringcount < count) ? ...(stringcount, float) : NO_FL_ARG); - float f2 = (((stringcount + 1) < count) ? ...((stringcount + 1), float) : NO_FL_ARG); - float f3 = (((stringcount + 2) < count) ? ...((stringcount + 2), float) : NO_FL_ARG); - float f4 = (((stringcount + 3) < count) ? ...((stringcount + 3), float) : NO_FL_ARG); - - dprint("Local_Notification(", ftos(net_type), ", ", Get_Field_Value(F_NAME, net_type, net_name), strcat(", ", s1, ", ", s2, ", ", s3, ", ", s4, ", "), strcat(ftos(f1), strcat(", ", ftos(f2), ", ", ftos(f3), ", ", ftos(f4), ");\n"))); - dprint(" ^--: stringcount: ", ftos(stringcount), ", floatcount: ", ftos(floatcount), ".\n"); + // check supplied type and name for errors + string checkargs = Notification_CheckArgs_TypeName(net_type, net_name); + if(checkargs != "") { backtrace(sprintf("Incorrect usage of Local_Notification: %s\n", checkargs)); return; } - if((stringcount + floatcount) > count) { backtrace(strcat("Not enough arguments for Local_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), ")"), " > count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; } - else if((stringcount + floatcount) < count) { backtrace(strcat("Too many arguments for Local_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), ")"), " < count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; } + entity notif = Get_Notif_Ent(net_type, net_name); + if not(notif) { backtrace("Local_Notification: Could not find notification entity!\n"); return; } + if not(notif.nent_enabled) { dprint(sprintf("Local_Notification(%s, %s): Entity was disabled...\n", Get_Notif_TypeName(net_type), notif.nent_name)); return; } + if((notif.nent_stringcount + notif.nent_floatcount) > count) + { + backtrace(sprintf( + strcat( + "Not enough arguments for Local_Notification(%s, %s, ...)! ", + "stringcount(%d) + floatcount(%d) > count(%d)\n", + "Check the definition and function call for accuracy...?\n" + ), + Get_Notif_TypeName(net_type), notif.nent_name, notif.nent_stringcount, notif.nent_floatcount, count)); + return; + } + else if((notif.nent_stringcount + notif.nent_floatcount) < count) + { + backtrace(sprintf( + strcat( + "Too many arguments for Local_Notification(%s, %s, ...)! ", + "stringcount(%d) + floatcount(%d) < count(%d)\n", + "Check the definition and function call for accuracy...?\n" + ), + Get_Notif_TypeName(net_type), notif.nent_name, notif.nent_stringcount, notif.nent_floatcount, count)); + return; + } + + string s1 = ((0 < notif.nent_stringcount) ? ...(0, string) : ""); + string s2 = ((1 < notif.nent_stringcount) ? ...(1, string) : ""); + string s3 = ((2 < notif.nent_stringcount) ? ...(2, string) : ""); + string s4 = ((3 < notif.nent_stringcount) ? ...(3, string) : ""); + float f1 = ((0 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 0), float) : 0); + float f2 = ((1 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 1), float) : 0); + float f3 = ((2 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 2), float) : 0); + float f4 = ((3 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 3), float) : 0); + + #ifdef NOTIFICATIONS_DEBUG + dprint( + sprintf("Local_Notification(%s, %s, %s, %s);\n", + Get_Notif_TypeName(net_type), + notif.nent_name, + sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4), + sprintf("%d, %d, %d, %d", f1, f2, f3, f4) + ) + ); + #endif + switch(net_type) { case MSG_INFO: { - #define MSG_INFO_NOTIF(name,strnum,flnum,args,hudargs,icon,normal,gentle) \ - { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \ - { \ - if(notif_checkstring(normal)) { print(sprintf(CCR(normal_or_gentle(normal, gentle)), args)); } \ - #ifdef CSQC \ - if(notif_checkstring(icon)) { HUD_Notify_Push(icon, hudargs); } \ - #endif \ - } } - MSG_INFO_NOTIFICATIONS - #undef MSG_INFO_NOTIF + print( + Local_Notification_sprintf( + notif.nent_string, + notif.nent_args, + s1, s2, s3, s4, + f1, f2, f3, f4) + ); + #ifdef CSQC + if(notif.nent_icon != "") + { + Local_Notification_HUD_Notify_Push( + notif.nent_icon, + notif.nent_hudargs, + s1, s2, s3, s4); + } + #endif break; } + #ifdef CSQC case MSG_CENTER: { - #define MSG_CENTER_NOTIF(name,strnum,flnum,args,cpid,durcnt,normal,gentle) \ - { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \ - { \ - if(notif_checkstring(normal)) { centerprint_generic(HANDLE_CPID(cpid), sprintf(CCR(normal_or_gentle(normal, gentle)), args), durcnt); } \ - } } - MSG_CENTER_NOTIFICATIONS - #undef MSG_CENTER_NOTIF + Local_Notification_centerprint_generic( + Local_Notification_sprintf( + notif.nent_string, + notif.nent_args, + s1, s2, s3, s4, + f1, f2, f3, f4), + notif.nent_durcnt, + notif.nent_cpid, + f1, f2); break; } #endif + case MSG_WEAPON: - { - #define MSG_WEAPON_NOTIF(name,infoname,centername) \ - { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \ - { \ - #if infoname != NO_MSG \ - Local_Notification_Without_VarArgs(MSG_INFO, infoname, \ - stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), \ - stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), \ - s1, s2, s3, s4, f1, f2, f3, f4); \ - #endif \ - #ifdef CSQC \ - #if centername != NO_MSG \ - Local_Notification_Without_VarArgs(MSG_CENTER, centername, \ - stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername)), \ - stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)), \ - s1, s2, s3, s4, f1, f2, f3, f4); \ - #endif \ - #endif \ - } } - MSG_WEAPON_NOTIFICATIONS - #undef MSG_WEAPON_NOTIF - break; - } case MSG_DEATH: { - #define MSG_DEATH_NOTIF(name,infoname,centername) \ - { NOTIF_MATCH(name, net_name) CHECK_AUTOCVAR(name) \ - { \ - #if infoname != NO_MSG \ - Local_Notification_Without_VarArgs(MSG_INFO, infoname, \ - stof(Get_Field_Value(F_STRNUM, MSG_INFO, infoname)), \ - stof(Get_Field_Value(F_FLNUM, MSG_INFO, infoname)), \ - s1, s2, s3, s4, f1, f2, f3, f4); \ - #endif \ - #ifdef CSQC \ - #if centername != NO_MSG \ - Local_Notification_Without_VarArgs(MSG_CENTER, centername, \ - stof(Get_Field_Value(F_STRNUM, MSG_CENTER, centername)), \ - stof(Get_Field_Value(F_FLNUM, MSG_CENTER, centername)), \ - s1, s2, s3, s4, f1, f2, f3, f4); \ - #endif \ - #endif \ - } } - MSG_DEATH_NOTIFICATIONS - #undef MSG_DEATH_NOTIF + if(notif.nent_msginfo) + if(notif.nent_msginfo.nent_enabled) + { + Local_Notification_WOVA( + MSG_INFO, + notif.nent_msginfo.nent_id, + notif.nent_msginfo.nent_stringcount, + notif.nent_msginfo.nent_floatcount, + s1, s2, s3, s4, + f1, f2, f3, f4); + } + #ifdef CSQC + if(notif.nent_msgcenter) + if(notif.nent_msgcenter.nent_enabled) + { + Local_Notification_WOVA( + MSG_CENTER, + notif.nent_msgcenter.nent_id, + notif.nent_msgcenter.nent_stringcount, + notif.nent_msgcenter.nent_floatcount, + s1, s2, s3, s4, + f1, f2, f3, f4); + } + #endif break; } } } -void Local_Notification_Without_VarArgs(float net_type, float net_name, float stringcount, float floatcount, string s1, string s2, string s3, string s4, float f1, float f2, float f3, float f4) +// WOVA = Without Variable Arguments +void Local_Notification_WOVA(float net_type, float net_name, + float stringcount, float floatcount, + string s1, string s2, string s3, string s4, + float f1, float f2, float f3, float f4) { - #define VARITEM(stringc,floatc,args) if((stringcount == stringc) && (floatcount == floatc)) { Local_Notification(net_type, net_name, args); return; } + #define VARITEM(stringc,floatc,args) \ + if((stringcount == stringc) && (floatcount == floatc)) \ + { Local_Notification(net_type, net_name, args); return; } EIGHT_VARS_TO_VARARGS_VARLIST #undef VARITEM - Local_Notification(net_type, net_name); // some notifications don't have any arguments at all } @@ -300,126 +458,294 @@ void Read_Notification(float is_new) float net_type = ReadByte(); float net_name = ReadShort(); - float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name)); - float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name)); + if(net_type == MSG_CENTER_KILL) + { + if(is_new) + { + if(net_name == 0) { reset_centerprint_messages(); } + else + { + entity notif = Get_Notif_Ent(MSG_CENTER, net_name); + if not(notif) { print("Read_Notification: Could not find notification entity!\n"); return; } + centerprint_generic(notif.nent_cpid, "", 0, 0); + } + } + } + else + { + entity notif = Get_Notif_Ent(net_type, net_name); + if not(notif) { print("Read_Notification: Could not find notification entity!\n"); return; } - string s1 = ((stringcount >= 1) ? ReadString() : NO_STR_ARG); - string s2 = ((stringcount >= 2) ? ReadString() : NO_STR_ARG); - string s3 = ((stringcount >= 3) ? ReadString() : NO_STR_ARG); - string s4 = ((stringcount == 4) ? ReadString() : NO_STR_ARG); - float f1 = ((floatcount >= 1) ? ReadLong() : NO_FL_ARG); - float f2 = ((floatcount >= 2) ? ReadLong() : NO_FL_ARG); - float f3 = ((floatcount >= 3) ? ReadLong() : NO_FL_ARG); - float f4 = ((floatcount == 4) ? ReadLong() : NO_FL_ARG); + #ifdef NOTIFICATIONS_DEBUG + dprint(sprintf("Read_Notification(%d) at %f: net_type = %s, net_name = %s\n", is_new, time, Get_Notif_TypeName(net_type), notif.nent_name)); + #endif - if(is_new) { Local_Notification_Without_VarArgs(net_type, net_name, stringcount, floatcount, s1, s2, s3, s4, f1, f2, f3, f4); } - else { print("received old notification? net_name = ", ftos(net_name), ".\n"); } + string s1 = ((0 < notif.nent_stringcount) ? ReadString() : ""); + string s2 = ((1 < notif.nent_stringcount) ? ReadString() : ""); + string s3 = ((2 < notif.nent_stringcount) ? ReadString() : ""); + string s4 = ((3 < notif.nent_stringcount) ? ReadString() : ""); + float f1 = ((0 < notif.nent_floatcount) ? ReadLong() : 0); + float f2 = ((1 < notif.nent_floatcount) ? ReadLong() : 0); + float f3 = ((2 < notif.nent_floatcount) ? ReadLong() : 0); + float f4 = ((3 < notif.nent_floatcount) ? ReadLong() : 0); + + if(is_new) + { + Local_Notification_WOVA( + net_type, net_name, + notif.nent_stringcount, + notif.nent_floatcount, + s1, s2, s3, s4, + f1, f2, f3, f4); + } + } } #endif #ifdef SVQC -float Write_Notification(entity client, float sf) +void Net_Notification_Remove() +{ + float i; + for(i = 0; i < 4; ++i) { if(self.nent_strings[i]) { strunzone(self.nent_strings[i]); } } + remove(self); +} + +float Net_Write_Notification(entity client, float sf) { float i, send = FALSE; switch(self.nent_broadcast) { - case NOTIF_ONE: { if((client == self.nent_client) || (client.classname == STR_SPECTATOR && client.enemy == self.nent_client)) { send = TRUE; } break; } - case NOTIF_ONE_ONLY: { if(client == self.nent_client) { send = TRUE; } break; } - case NOTIF_TEAM: { if((client.team == self.nent_client.team) || (client.classname == STR_SPECTATOR && client.enemy.team == self.nent_client.team)) { send = TRUE; } break; } - case NOTIF_TEAM_EXCEPT: { if(((client != self.nent_client) && (client.team == self.nent_client.team) && !(client.classname == STR_SPECTATOR && client.enemy == self.nent_client))) { send = TRUE; } break; } - case NOTIF_ANY: { send = TRUE; break; } - case NOTIF_ANY_EXCEPT: { if((client != self.nent_client) && !(client.classname == STR_SPECTATOR && client.enemy == self.nent_client)) { send = TRUE; } break; } + case NOTIF_ONE: // send to one client and their spectator + { + if( + (client == self.nent_client) + || + ( + (client.classname == STR_SPECTATOR) + && + (client.enemy == self.nent_client) + ) + ) { send = TRUE; } + break; + } + case NOTIF_ONE_ONLY: // send ONLY to one client + { + if(client == self.nent_client) { send = TRUE; } + break; + } + case NOTIF_TEAM: // send only to X team and their spectators + { + if( + (client.team == self.nent_client.team) + || + ( + (client.classname == STR_SPECTATOR) + && + (client.enemy.team == self.nent_client.team) + ) + ) { send = TRUE; } + break; + } + case NOTIF_TEAM_EXCEPT: // send only to X team and their spectators, except for Y person and their spectators + { + if( + (client != self.nent_client) + && + ( + (client.team == self.nent_client.team) + || + ( + (client.classname == STR_SPECTATOR) + && + ( + (client.enemy != self.nent_client) + && + (client.enemy.team == self.nent_client.team) + ) + ) + ) + ) { send = TRUE; } + break; + } + case NOTIF_ANY: // send to everyone + { + send = TRUE; + break; + } + case NOTIF_ANY_EXCEPT: // send to everyone except X person and their spectators + { + if( + (client != self.nent_client) + && + !( + (client.classname == STR_SPECTATOR) + && + (client.enemy == self.nent_client) + ) + ) { send = TRUE; } + break; + } default: { send = FALSE; break; } } if(send) - { - float stringcount = stof(Get_Field_Value(F_STRNUM, self.nent_net_type, self.nent_net_name)); - float floatcount = stof(Get_Field_Value(F_FLNUM, self.nent_net_type, self.nent_net_name)); - + { WriteByte(MSG_ENTITY, ENT_CLIENT_NOTIFICATION); WriteByte(MSG_ENTITY, self.nent_net_type); WriteShort(MSG_ENTITY, self.nent_net_name); - for(i = 0; i < stringcount; ++i) { WriteString(MSG_ENTITY, self.nent_strings[i]); } - for(i = 0; i < floatcount; ++i) { WriteLong(MSG_ENTITY, self.nent_floats[stringcount + i]); } + for(i = 0; i < self.nent_stringcount; ++i) { WriteString(MSG_ENTITY, self.nent_strings[i]); } + for(i = 0; i < self.nent_floatcount; ++i) { WriteLong(MSG_ENTITY, self.nent_floats[i]); } } return send; } -void Send_Notification(float broadcast, entity client, float net_type, float net_name, ...count) +void Kill_Notification(float broadcast, entity client, float net_type, float net_name) { - if((broadcast == MSG_BROADCAST || broadcast == MSG_ONE) && net_type && net_name) - { - float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name)); - float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name)); - float i, tmp_f; - string tmp_s; + string checkargs = Notification_CheckArgs(broadcast, client, net_type, 1); + if(checkargs != "") { backtrace(sprintf("Incorrect usage of Kill_Notification: %s\n", checkargs)); return; } - dprint("Send_Notification(", ftos(broadcast), ", ", ftos(net_type), ", ", Get_Field_Value(F_NAME, net_type, net_name), strcat(", ", ftos(count), ");\n")); - dprint(" ^--: stringcount: ", ftos(stringcount), ", floatcount: ", ftos(floatcount), ".\n"); + entity notif; - if((stringcount + floatcount) > count) { backtrace(strcat("Not enough arguments for Send_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), "),"), " > count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; } - else if((stringcount + floatcount) < count) { backtrace(strcat("Too many arguments for Send_Notification! ", strcat("stringcount(", ftos(stringcount), ") + floatcount(", ftos(floatcount), "),"), " < count(", ftos(count), ").\nCheck the notification definition and the function call for accuracy...?\n")); return; } - - entity notif = spawn(); + // if this is a centerprint, we must tell the client + // to kill the cpid in the centerprint queue + if(net_type == MSG_CENTER) + { + notif = spawn(); + notif.classname = "net_kill_notification"; notif.nent_broadcast = broadcast; notif.nent_client = client; - notif.nent_net_type = net_type; + notif.nent_net_type = MSG_CENTER_KILL; notif.nent_net_name = net_name; - for(i = 0; i < stringcount; ++i) { tmp_s = ...(i, string); notif.nent_strings[i] = tmp_s; dprint("WriteString(...(", ftos(i), ", string)); - ", tmp_s, "\n"); } - for(i = 0; i < floatcount; ++i) { tmp_f = ...((stringcount + i), float); notif.nent_floats[i] = tmp_f; dprint("WriteLong(...(", ftos((stringcount + i)), ", float)); - ", ftos(tmp_f), "\n"); } - - Net_LinkEntity(notif, FALSE, 0.5, Write_Notification); + Net_LinkEntity(notif, FALSE, autocvar_notification_lifetime_runtime, Net_Write_Notification); + } - if(!server_is_local) + for(notif = world; (notif = find(notif, classname, "net_notification"));) + { + // now kill the old send notification entity + if(notif.nent_net_type == net_type) { - Local_Notification_Without_VarArgs(net_type, net_name, stringcount, floatcount, IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), IFFL(0), IFFL(1), IFFL(2), IFFL(3)); + print(sprintf("killed '%s'\n", notif.classname)); + notif.think(); } } - else { backtrace("Incorrect usage of Send_Notification!\n"); } } -void Send_Notification_Without_VarArgs(float broadcast, entity client, float net_type, float net_name, float stringcount, float floatcount, string s1, string s2, string s3, string s4, float f1, float f2, float f3, float f4) -{ - #define VARITEM(stringc,floatc,args) if((stringcount == stringc) && (floatcount == floatc)) { Send_Notification(broadcast, client, net_type, net_name, args); return; } - EIGHT_VARS_TO_VARARGS_VARLIST - #undef VARITEM +void Send_Notification(float broadcast, entity client, + float net_type, float net_name, ...count) +{ + // check supplied broadcast, target, type, and name for errors + string checkargs = Notification_CheckArgs(broadcast, client, net_type, net_name); + if(checkargs != "") { backtrace(sprintf("Incorrect usage of Send_Notification: %s\n", checkargs)); return; } - Send_Notification(broadcast, client, net_type, net_name); // some notifications don't have any arguments at all -} + // retreive counts for the arguments of this notification + entity notif = Get_Notif_Ent(net_type, net_name); + if not(notif) { backtrace("Send_Notification: Could not find notification entity!\n"); return; } -void Send_Notification_Legacy_Wrapper(float broadcast, entity client, float net_type, float net_name, string s1, string s2, float f1, float f2, float f3) -{ - float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name)); - float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name)); - Send_Notification_Without_VarArgs(broadcast, client, net_type, net_name, stringcount, floatcount, s1, s2, NO_STR_ARG, NO_STR_ARG, f1, f2, f3, NO_FL_ARG); -} + if((notif.nent_stringcount + notif.nent_floatcount) > count) + { + backtrace(sprintf( + strcat( + "Not enough arguments for Send_Notification(%d, %s, %s, ...)! ", + "stringcount(%d) + floatcount(%d) > count(%d)\n", + "Check the definition and function call for accuracy...?\n" + ), + broadcast, Get_Notif_TypeName(net_type), notif.nent_name, notif.nent_stringcount, notif.nent_floatcount, count)); + return; + } + else if((notif.nent_stringcount + notif.nent_floatcount) < count) + { + backtrace(sprintf( + strcat( + "Too many arguments for Send_Notification(%d, %s, %s, ...)! ", + "stringcount(%d) + floatcount(%d) < count(%d)\n", + "Check the definition and function call for accuracy...?\n" + ), + broadcast, Get_Notif_TypeName(net_type), notif.nent_name, notif.nent_stringcount, notif.nent_floatcount, count)); + return; + } -/*void Send_Notification_ToTeam(float targetteam, entity except, float net_type, float net_name, ...count) -{ - float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name)); - float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name)); - Send_Notification_Without_VarArgs(NOTIF_TEAM, tmp_entity, net_type, net_name, stringcount, floatcount, IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), IFFL(0), IFFL(1), IFFL(2), IFFL(3)); -} + #ifdef NOTIFICATIONS_DEBUG + string s1 = ((0 < notif.nent_stringcount) ? ...(0, string) : ""); + string s2 = ((1 < notif.nent_stringcount) ? ...(1, string) : ""); + string s3 = ((2 < notif.nent_stringcount) ? ...(2, string) : ""); + string s4 = ((3 < notif.nent_stringcount) ? ...(3, string) : ""); + float f1 = ((0 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 0), float) : 0); + float f2 = ((1 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 1), float) : 0); + float f3 = ((2 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 2), float) : 0); + float f4 = ((3 < notif.nent_floatcount) ? ...((notif.nent_stringcount + 3), float) : 0); + dprint( + sprintf("Send_Notification(%d, %s, %s, %s, %s - %d %d);\n", + broadcast, + Get_Notif_TypeName(net_type), + notif.nent_name, + sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4), + sprintf("%d, %d, %d, %d", f1, f2, f3, f4), + notif.nent_stringcount, notif.nent_floatcount + ) + ); + #endif -// WARNING: use this ONLY if you need exceptions or want to exclude spectators, otherwise use Send_Notification(world, MSG_BROADCAST, ...) -void Send_Notification_ToAll(entity except, float spectators, float net_type, float net_name, ...count) -{ - float stringcount = stof(Get_Field_Value(F_STRNUM, net_type, net_name)); - float floatcount = stof(Get_Field_Value(F_FLNUM, net_type, net_name)); + entity net_notif = spawn(); + net_notif.classname = "net_notification"; + net_notif.nent_broadcast = broadcast; + net_notif.nent_client = client; + net_notif.nent_net_type = net_type; + net_notif.nent_net_name = net_name; + net_notif.nent_stringcount = notif.nent_stringcount; + net_notif.nent_floatcount = notif.nent_floatcount; - entity tmp_entity; - FOR_EACH_REALCLIENT(tmp_entity) + float i; + for(i = 0; i < net_notif.nent_stringcount; ++i) { net_notif.nent_strings[i] = strzone(...(i, string)); } + for(i = 0; i < net_notif.nent_floatcount; ++i) { net_notif.nent_floats[i] = ...((net_notif.nent_stringcount + i), float); } + + net_notif.think = Net_Notification_Remove; + net_notif.nextthink = ((time > autocvar_notification_lifetime_mapload) ? + (time + autocvar_notification_lifetime_runtime) : + autocvar_notification_lifetime_mapload); + + Net_LinkEntity(net_notif, FALSE, 0, Net_Write_Notification); + + if(server_is_dedicated && (broadcast == NOTIF_ANY || broadcast == NOTIF_ANY_EXCEPT) && (net_type != MSG_CENTER)) { - if((tmp_entity.classname == STR_PLAYER) || spectators) - if(tmp_entity != except) - { - Send_Notification_Without_VarArgs(tmp_entity, MSG_ONE, net_type, net_name, stringcount, floatcount, IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), IFFL(0), IFFL(1), IFFL(2), IFFL(3)); - } + Local_Notification_WOVA( + net_type, net_name, + notif.nent_stringcount, + notif.nent_floatcount, + IFSTR(0), IFSTR(1), IFSTR(2), IFSTR(3), + IFFL(0), IFFL(1), IFFL(2), IFFL(3)); } -}*/ +} + +// WOVA = Without Variable Arguments +void Send_Notification_WOVA(float broadcast, entity client, + float net_type, float net_name, + string s1, string s2, string s3, string s4, + float f1, float f2, float f3, float f4) +{ + entity notif = Get_Notif_Ent(net_type, net_name); + + #ifdef NOTIFICATIONS_DEBUG + dprint( + sprintf("Send_Notification_WOVA(%d, %s, %s, %s, %s - %d %d);\n", + broadcast, + Get_Notif_TypeName(net_type), + notif.nent_name, + sprintf("'%s^7', '%s^7', '%s^7', '%s^7'", s1, s2, s3, s4), + sprintf("%d, %d, %d, %d", f1, f2, f3, f4), + notif.nent_stringcount, notif.nent_floatcount + ) + ); + #endif + + #define VARITEM(stringc,floatc,args) \ + if((notif.nent_stringcount == stringc) && (notif.nent_floatcount == floatc)) \ + { Send_Notification(broadcast, client, net_type, net_name, args); return; } + EIGHT_VARS_TO_VARARGS_VARLIST + #undef VARITEM + Send_Notification(broadcast, client, net_type, net_name); // some notifications don't have any arguments at all +} // ============================= @@ -444,9 +770,4 @@ void Send_CSQC_Centerprint_Generic(entity e, float id, string s, float duration, }); } } -void Send_CSQC_Centerprint_Generic_Expire(entity e, float id) -{ - Send_CSQC_Centerprint_Generic(e, id, "", 1, 0); -} #endif // ifdef SVQC -#endif // ifndef MENUQC