// ==================================
// Normally do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-#define CLIENT_COMMANDS(request, arguments) \
- CLIENT_COMMAND("blurtest", LocalCommand_blurtest(request), "Feature for testing blur postprocessing") \
- CLIENT_COMMAND("boxparticles", LocalCommand_boxparticles(request, arguments), "Spawn particles manually") \
- CLIENT_COMMAND("create_scrshot_ent", LocalCommand_create_scrshot_ent(request), "Create an entity at this location for automatic screenshots") \
- CLIENT_COMMAND("debugmodel", LocalCommand_debugmodel(request, arguments), "Spawn a debug model manually") \
- CLIENT_COMMAND("handlevote", LocalCommand_handlevote(request, arguments), "System to handle selecting a vote or option") \
- CLIENT_COMMAND("hud", LocalCommand_hud(request, arguments), "Commands regarding/controlling the HUD system") \
- CLIENT_COMMAND("localprint", LocalCommand_localprint(request, arguments), "Create your own centerprint sent to yourself") \
- CLIENT_COMMAND("find", LocalCommand_find(request, arguments), "Search through entities for matching classname") \
- CLIENT_COMMAND("mv_download", LocalCommand_mv_download(request, arguments), "Retrieve mapshot picture from the server") \
- CLIENT_COMMAND("sendcvar", LocalCommand_sendcvar(request, arguments), "Send a cvar to the server (like weaponpriority)") \
- /* nothing */
+CLIENT_COMMAND(blurtest, "Feature for testing blur postprocessing") { LocalCommand_blurtest(request); }
+CLIENT_COMMAND(boxparticles, "Spawn particles manually") { LocalCommand_boxparticles(request, arguments); }
+CLIENT_COMMAND(create_scrshot_ent, "Create an entity at this location for automatic screenshots") { LocalCommand_create_scrshot_ent(request); }
+CLIENT_COMMAND(debugmodel, "Spawn a debug model manually") { LocalCommand_debugmodel(request, arguments); }
+CLIENT_COMMAND(handlevote, "System to handle selecting a vote or option") { LocalCommand_handlevote(request, arguments); }
+CLIENT_COMMAND(hud, "Commands regarding/controlling the HUD system") { LocalCommand_hud(request, arguments); }
+CLIENT_COMMAND(localprint, "Create your own centerprint sent to yourself") { LocalCommand_localprint(request, arguments); }
+CLIENT_COMMAND(find, "Search through entities for matching classname") { LocalCommand_find(request, arguments); }
+CLIENT_COMMAND(mv_download, "Retrieve mapshot picture from the server") { LocalCommand_mv_download(request, arguments); }
+CLIENT_COMMAND(sendcvar, "Send a cvar to the server (like weaponpriority)") { LocalCommand_sendcvar(request, arguments); }
void LocalCommand_macro_help()
{
- #define CLIENT_COMMAND(name, function, description) \
- { if (strtolower(description) != "") { LOG_INFO(" ^2", name, "^7: ", description, "\n"); } }
-
- CLIENT_COMMANDS(0, 0);
- #undef CLIENT_COMMAND
+ FOREACH(CLIENT_COMMANDS, true, LAMBDA(LOG_INFOF(" ^2%s^7: %s\n", it.m_name, it.m_description)));
}
-bool LocalCommand_macro_command(int argc)
+bool LocalCommand_macro_command(int argc, string command)
{
- #define CLIENT_COMMAND(name, function, description) \
- { if (name == strtolower(argv(0))) { function; return true; } }
-
- CLIENT_COMMANDS(CMD_REQUEST_COMMAND, argc);
- #undef CLIENT_COMMAND
-
+ string c = strtolower(argv(0));
+ FOREACH(CLIENT_COMMANDS, it.m_name == c, LAMBDA(
+ it.m_invokecmd(CMD_REQUEST_COMMAND, NULL, argc, command);
+ return true;
+ ));
return false;
}
bool LocalCommand_macro_usage(int argc)
{
- #define CLIENT_COMMAND(name, function, description) \
- { if (name == strtolower(argv(1))) { function; return true; } }
-
- CLIENT_COMMANDS(CMD_REQUEST_USAGE, argc);
- #undef CLIENT_COMMAND
-
+ string c = strtolower(argv(1));
+ FOREACH(CLIENT_COMMANDS, it.m_name == c, LAMBDA(
+ it.m_invokecmd(CMD_REQUEST_USAGE, NULL, argc, "");
+ return true;
+ ));
return false;
}
void LocalCommand_macro_write_aliases(int fh)
{
- #define CLIENT_COMMAND(name, function, description) \
- { if (strtolower(description) != "") { CMD_Write_Alias("qc_cmd_cl", name, description); } }
-
- CLIENT_COMMANDS(0, 0);
- #undef CLIENT_COMMAND
+ FOREACH(CLIENT_COMMANDS, true, LAMBDA(CMD_Write_Alias("qc_cmd_cl", it.m_name, it.m_description)));
}
}
// continue as usual and scan for normal commands
if (GenericCommand(command) // handled by common/command/generic.qc
- || LocalCommand_macro_command(argc) // handled by one of the above LocalCommand_* functions
+ || LocalCommand_macro_command(argc, command) // handled by one of the above LocalCommand_* functions
|| MUTATOR_CALLHOOK(CSQC_ConsoleCommand, s, argc, command) // handled by a mutator
) return;
#ifndef CLIENT_COMMANDS_CL_CMD_H
#define CLIENT_COMMANDS_CL_CMD_H
-// ==============================================
-// CSQC client commands code, written by Samual
-// Last updated: December 17th, 2011
-// ==============================================
void Cmd_HUD_SetFields(int);
void Cmd_HUD_Help();
// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
void LocalCommand_macro_write_aliases(int fh);
+
+REGISTRY(CLIENT_COMMANDS, BITS(7))
+#define CLIENT_COMMANDS_from(i) _CLIENT_COMMANDS_from(i, NULL)
+REGISTER_REGISTRY(CLIENT_COMMANDS)
+REGISTRY_SORT(CLIENT_COMMANDS)
+
+#define CLIENT_COMMAND(id, description) \
+ CLASS(clientcommand_##id, Command) \
+ ATTRIB(clientcommand_##id, m_name, string, #id); \
+ ATTRIB(clientcommand_##id, m_description, string, description); \
+ ENDCLASS(clientcommand_##id) \
+ REGISTER(CLIENT_COMMANDS, CMD_CL, id, m_id, NEW(clientcommand_##id)); \
+ METHOD(clientcommand_##id, m_invokecmd, void(int request, entity caller, int arguments, string command))
+
+STATIC_INIT(CLIENT_COMMANDS_aliases) {
+ FOREACH(CLIENT_COMMANDS, true, LAMBDA(localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_cl"))));
+}
+
#endif
if (isnew) this.classname = it.netname;
if (autocvar_developer_csqcentities)
LOG_INFOF("CSQC_Ent_Update(%d) at %f with this=%i {.entnum=%d, .enttype=%d} t=%s (%d)\n", isnew, savetime, this, this.entnum, this.enttype, this.classname, t);
- done = it.m_read(this, isnew);
+ done = it.m_read(this, NULL, isnew);
break;
));
time = savetime;
FOREACH(TempEntities, it.m_id == nTEID, LAMBDA(
if (autocvar_developer_csqcentities)
LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)\n", it.netname, nTEID);
- return it.m_read(NULL, true);
+ return it.m_read(NULL, NULL, true);
));
if (autocvar_developer_csqcentities)
REGISTRY(Animations, BITS(8))
REGISTER_REGISTRY(Animations)
#define Animations_from(id) _Animations_from(id, NULL)
-#define WriteAnimation(to, it) WriteRegistry(Animations, to, it)
-#define ReadAnimation() ReadRegistry(Animations)
+#define WriteAnimation(to, it) WriteRegistered(Animations, to, it)
+#define ReadAnimation() ReadRegistered(Animations)
#define REGISTER_ANIMATION(id, framenames) \
.vector anim_##id; \
REGISTER(Animations, ANIM_##id, m_id, NEW(Animation)) { \
}
#endif
+REGISTER_NET_C2S(w_whereis)
+#ifdef SVQC
+void Weapon_whereis(Weapon this, entity cl);
+NET_HANDLE(w_whereis, bool)
+{
+ Weapon wpn = ReadRegistered(Weapons);
+ if (wpn != WEP_Null) Weapon_whereis(wpn, sender);
+ return true;
+}
+#else
+void w_whereis(Weapon this)
+{
+ int channel = MSG_C2S;
+ WriteHeader(channel, w_whereis);
+ WriteRegistered(Weapons, channel, this);
+}
+CLIENT_COMMAND(weapon_find, "Show spawn locations of a weapon")
+{
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ string s = argv(1);
+ if (s == "all")
+ {
+ FOREACH(Weapons, it != WEP_Null, w_whereis(it));
+ return;
+ }
+ if (s == "unowned")
+ {
+ FOREACH(Weapons, it != WEP_Null && !(STAT(WEAPONS) & it.m_wepset), w_whereis(it));
+ return;
+ }
+ FOREACH(Weapons, it != WEP_Null && it.netname == s,
+ {
+ w_whereis(it);
+ return;
+ });
+ }
+ default:
+ {
+ LOG_INFOF("Incorrect parameters for ^2%s^7\n", "weapon_find");
+ }
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_INFO("\nUsage:^3 cl_cmd weapon_find weapon\n");
+ LOG_INFO(" Where 'weapon' is the lowercase weapon name, 'all' or 'unowned'.\n");
+ return;
+ }
+ }
+}
+#endif
+
+
#endif
#endif
.string netname;
.int m_id;
-.bool(entity this, bool isNew) m_read;
-#define NET_HANDLE(id, param) bool Net_Handle_##id(entity this, param)
+.bool(entity this, entity sender, bool isNew) m_read;
+#define NET_HANDLE(id, param) bool Net_Handle_##id(entity this, entity sender, param)
#ifdef CSQC
int ReadByte();
- void Net_ClientCommand(string command)
+ void Net_ClientCommand(entity sender, string command)
{
// command matches `c2s "(.+)"`
string buf = substring(command, argv_start_index(1) + 1, -2);
for (int C2S; (C2S = ReadByte()) >= 0; )
{
entity reader = C2S_Protocol_from(C2S);
- if (reader && reader.m_read && reader.m_read(NULL, true)) continue;
+ if (reader && reader.m_read && reader.m_read(NULL, sender, true)) continue;
LOG_SEVEREF("Net_ClientCommand() with malformed C2S=%d\n", C2S);
return;
}
} MACRO_END
#endif
-#define ReadRegistry(r) r##_from(Read_byte())
-#define WriteRegistry(r, to, it) Write_byte(to, it.m_id)
+#define ReadRegistered(r) r##_from(Read_byte())
+#define WriteRegistered(r, to, it) Write_byte(to, it.m_id)
#define Read_byte() ReadByte()
#define Write_byte(to, f) WriteByte(to, f)
case "prespawn": break; // handled by engine in host_cmd.c
case "sentcvar": break; // handled by server in this file
case "spawn": break; // handled by engine in host_cmd.c
- case "c2s": Net_ClientCommand(command); return; // handled by net.qh
+ case "c2s": Net_ClientCommand(this, command); return; // handled by net.qh
default:
if (SV_ParseClientCommand_floodcheck()) break; // "true": continue, as we're not flooding yet
WriteByte(MSG_ONE, type);
}
+void Weapon_whereis(Weapon this, entity cl)
+{
+ if (!autocvar_g_showweaponspawns) return;
+ for (entity it = NULL; (it = findfloat(it, weapon, this.m_id)); )
+ {
+ if (it.classname == "droppedweapon" && autocvar_g_showweaponspawns < 2)
+ continue;
+ if (!(it.flags & FL_ITEM))
+ continue;
+ entity wp = WaypointSprite_Spawn(
+ WP_Weapon,
+ 1, 0,
+ NULL, it.origin + ('0 0 1' * it.maxs.z) * 1.2,
+ cl, 0,
+ NULL, enemy,
+ 0,
+ RADARICON_NONE
+ );
+ wp.wp_extra = this.m_id;
+ }
+}
+
bool client_hasweapon(entity cl, Weapon wpn, float andammo, bool complain)
{
float f = 0;
if (weaponsInMap & WepSet_FromWeapon(wpn))
{
Send_WeaponComplain(cl, wpn.m_id, 1);
-
- if(autocvar_g_showweaponspawns)
- {
- for(entity e = world; (e = findfloat(e, weapon, wpn.m_id)); )
- {
- if(e.classname == "droppedweapon" && autocvar_g_showweaponspawns < 2)
- continue;
- if(!(e.flags & FL_ITEM))
- continue;
- entity wp = WaypointSprite_Spawn(
- WP_Weapon,
- 1, 0,
- world, e.origin + ('0 0 1' * e.maxs.z) * 1.2,
- cl, 0,
- world, enemy,
- 0,
- RADARICON_NONE
- );
- wp.wp_extra = wpn.m_id;
- }
- }
+ Weapon_whereis(wpn, cl);
}
else
{