- cd darkplaces && make sv-debug -j $(nproc) && export ENGINE="$PWD/darkplaces-dedicated -xonotic"
- cd ..
+ - mkdir -p data/maps
- wget -O data/g-23.pk3 http://beta.xonotic.org/autobuild-bsp/latest/g-23.pk3
+ - wget -O data/maps/g-23.mapinfo https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.mapinfo
+ - wget -O data/maps/g-23.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints
+ - wget -O data/maps/g-23.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.cache
+ - wget -O data/maps/g-23.waypoints.hardwired https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/g-23.waypoints.hardwired
- make
- - EXPECT=07fdfd9a19025920a599995730eb2a78
+ - EXPECT=814b0e609bcf01dc2a44f2b17fa366b4
- HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
| tee /dev/stderr
| grep '^:'
"other gamemodes except DM.\n"));
}
-#define HUD_DefaultColumnLayout() \
-"ping pl name | " \
-"-teams,cts,lms/kills +ft,tdm/kills -teams,lms/deaths +ft,tdm/deaths -teams,lms,rc,ka/suicides +ft,tdm/suicides -cts,dm,tdm,ka,ft/frags " /* tdm already has this in "score" */ \
-"-rc,cts,nb/dmg -rc,cts,nb/dmgtaken " \
-"+ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes " \
-"+lms/lives +lms/rank " \
-"+kh/caps +kh/pushes +kh/destroyed " \
-"?+rc/laps ?+rc/time ?+rc/fastest " \
-"+as/objectives +nb/faults +nb/goals +ka/pickups +ka/bckills +ka/bctime +ft/revivals " \
-"-lms,rc,nb/score"
+// NOTE: adding a gametype with ? to not warn for an optional field
+// make sure it's excluded in a previous exclusive rule, if any
+// otherwise the previous exclusive rule warns anyway
+// e.g. -teams,rc,cts,lms/kills ?+rc/kills
+#define SCOREBOARD_DEFAULT_COLUMNS \
+"ping pl name |" \
+" -teams,rc,cts,inv,lms/kills +ft,tdm/kills ?+rc,inv/kills" \
+" -teams,lms/deaths +ft,tdm/deaths" \
+" -teams,lms,rc,cts,inv,ka/suicides +ft,tdm/suicides ?+rc,inv/suicides" \
+" -cts,dm,tdm,ka,ft/frags" /* tdm already has this in "score" */ \
+" -rc,cts,nb/dmg -rc,cts,nb/dmgtaken" \
+" +ctf/caps +ctf/pickups +ctf/fckills +ctf/returns +ons/caps +ons/takes" \
+" +lms/lives +lms/rank" \
+" +kh/caps +kh/pushes +kh/destroyed" \
+" ?+rc/laps ?+rc/time +rc,cts/fastest" \
+" +as/objectives +nb/faults +nb/goals" \
+" +ka/pickups +ka/bckills +ka/bctime +ft/revivals" \
+" -lms,rc,cts,inv,nb/score"
void Cmd_HUD_SetFields(int argc)
{
argc = tokenizebyseparator(strcat("0 1 ", autocvar_scoreboard_columns), " ");
if(argc < 3)
- argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
+ argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
if(argc == 3)
{
if(argv(2) == "default")
- argc = tokenizebyseparator(strcat("0 1 ", HUD_DefaultColumnLayout()), " ");
+ argc = tokenizebyseparator(strcat("0 1 ", SCOREBOARD_DEFAULT_COLUMNS), " ");
else if(argv(2) == "all")
{
string s;
{
case "ping": hud_field[hud_num_fields] = SP_PING; break;
case "pl": hud_field[hud_num_fields] = SP_PL; break;
- case "pl": hud_field[hud_num_fields] = SP_PL; break;
case "kd": case "kdr": case "kdratio": case "k/d": hud_field[hud_num_fields] = SP_KDRATIO; break;
case "sum": case "diff": case "k-d": hud_field[hud_num_fields] = SP_SUM; break;
case "name": case "nick": hud_field[hud_num_fields] = SP_NAME; have_name = true; break;
other.last_pickup = time;
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
- _sound (other, CH_TRIGGER, (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
+ _sound (other, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
if (this.classname == "droppedweapon")
remove (this);
float autocvar_g_vehicles_tag_damagerate = 5;
float autocvar_g_vehicles_weapon_damagerate = 1;
+.float vehicle_last_trace;
+
// flags:
.int vehicle_flags;
bool autocvar_g_vehicle_racer = true;
+float autocvar_g_vehicle_racer_thinkrate = 0.05; // TODO: any higher causes it to sink in liquids
+
float autocvar_g_vehicle_racer_speed_afterburn = 3000;
// energy consumed per second
float autocvar_g_vehicle_racer_afterburn_cost = 100;
vehicles_frame(vehic, this);
- if(pointcontents(vehic.origin) != CONTENT_WATER)
+ traceline(vehic.origin, vehic.origin + '0 0 1', MOVE_NOMONSTERS, this);
+ int cont = trace_dpstartcontents;
+ if(cont & DPCONTENTS_WATER)
vehic.air_finished = time + autocvar_g_vehicle_racer_water_time;
if(IS_DEAD(vehic))
PHYS_INPUT_BUTTON_ZOOM(this) = PHYS_INPUT_BUTTON_CROUCH(this) = false;
- crosshair_trace(this);
+ if(time >= vehic.vehicle_last_trace)
+ {
+ crosshair_trace(this);
+ vehic.vehicle_last_trace = time + autocvar_g_vehicle_racer_thinkrate;
+ }
vehic.angles_x *= -1;
vector df = vehic.velocity * -autocvar_g_vehicle_racer_friction;
//vehic.velocity_z = ftmp;
- int cont = pointcontents(vehic.origin);
if(this.movement)
{
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ if(cont & DPCONTENTS_LIQUIDSMASK)
{
if(this.movement_x) { df += v_forward * ((this.movement_x > 0) ? autocvar_g_vehicle_racer_water_speed_forward : -autocvar_g_vehicle_racer_water_speed_forward); }
if(this.movement_y) { df += v_right * ((this.movement_y > 0) ? autocvar_g_vehicle_racer_water_speed_strafe : -autocvar_g_vehicle_racer_water_speed_strafe); }
vehic.wait = time;
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ if(cont & DPCONTENTS_LIQUIDSMASK)
{
vehic.vehicle_energy -= autocvar_g_vehicle_racer_waterburn_cost * PHYS_INPUT_TIMELENGTH;
df += (v_forward * autocvar_g_vehicle_racer_waterburn_speed);
sound (vehic.tur_head, CH_TRIGGER_SINGLE, SND_Null, VOL_VEHICLEENGINE, ATTEN_NORM);
}
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ if(cont & DPCONTENTS_LIQUIDSMASK)
vehic.racer_watertime = time;
float dforce = autocvar_g_vehicle_racer_downforce;
if(autocvar_g_vehicle_racer_rocket_locktarget)
{
+ if(vehic.vehicle_last_trace == time + autocvar_g_vehicle_racer_thinkrate)
vehicles_locktarget(vehic, (1 / autocvar_g_vehicle_racer_rocket_locking_time) * frametime,
(1 / autocvar_g_vehicle_racer_rocket_locking_releasetime) * frametime,
autocvar_g_vehicle_racer_rocket_locked_time);
void racer_think()
{SELFPARAM();
- self.nextthink = time;
-
- float pushdeltatime = time - self.lastpushtime;
- if (pushdeltatime > 0.15) pushdeltatime = 0;
- self.lastpushtime = time;
- if(!pushdeltatime) return;
+ this.nextthink = time + autocvar_g_vehicle_racer_thinkrate;
- tracebox(self.origin, self.mins, self.maxs, self.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, self);
+ tracebox(this.origin, this.mins, this.maxs, this.origin - ('0 0 1' * autocvar_g_vehicle_racer_springlength), MOVE_NOMONSTERS, this);
- vector df = self.velocity * -autocvar_g_vehicle_racer_friction;
+ vector df = this.velocity * -autocvar_g_vehicle_racer_friction;
df_z += (1 - trace_fraction) * autocvar_g_vehicle_racer_hoverpower + sin(time * 2) * (autocvar_g_vehicle_racer_springlength * 2);
float forced = autocvar_g_vehicle_racer_upforcedamper;
- int cont = pointcontents(self.origin - '0 0 64');
- if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ //int cont = pointcontents(self.origin - '0 0 64');
+ traceline(this.origin - '0 0 64', this.origin - '0 0 64', MOVE_NOMONSTERS, this);
+ //if(cont == CONTENT_WATER || cont == CONTENT_LAVA || cont == CONTENT_SLIME)
+ if(trace_dpstartcontents & DPCONTENTS_LIQUIDSMASK)
{
forced = autocvar_g_vehicle_racer_water_upforcedamper;
- self.velocity_z += 200;
+ this.velocity_z += 200;
}
- self.velocity += df * pushdeltatime;
- if(self.velocity_z > 0)
- self.velocity_z *= 1 - forced * pushdeltatime;
+ this.velocity += df * autocvar_g_vehicle_racer_thinkrate;
+ if(this.velocity_z > 0)
+ this.velocity_z *= 1 - forced * autocvar_g_vehicle_racer_thinkrate;
- self.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
- self.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * pushdeltatime);
+ this.angles_x *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * autocvar_g_vehicle_racer_thinkrate);
+ this.angles_z *= 1 - (autocvar_g_vehicle_racer_anglestabilizer * autocvar_g_vehicle_racer_thinkrate);
- CSQCMODEL_AUTOUPDATE(self);
+ CSQCMODEL_AUTOUPDATE(this);
}
void racer_exit(float eject)
#include "urllib.qc"
#include "vector.qh"
#include "yenc.qh"
+
+#include "matrix/_mod.inc"
// generated file; do not modify
#include "angle.qc"
+#include "json.qc"
#include "p2mathlib.qc"
#include "random.qc"
#include "sortlist.qc"
int it = bufstr_add(_json_buffer, key, 0);
bool ret = false; WITH(string, _json_ns, key, ret = _json_parse_value());
if (!ret) {
- bufstr_set(_json_buffer, it, string_null);
+ bufstr_free(_json_buffer, it);
if (required) JSON_FAIL("expected value"); else break;
}
bufstr_set(_json_buffer, len, ftos(n + 1));
case 'n': esc = "\n"; break;
case 't': esc = "\t"; break;
case 'u': esc = "\\u"; break; // TODO
+ case '/': esc = "/"; break;
}
s = strcat(s, esc);
} else {
buf_del(buf);
}
+void json_dump(int buf)
+{
+ for (int i = 0, n = buf_getsize(buf); i < n; ++i) {
+ print(bufstr_get(buf, i), "\n");
+ }
+}
+
#undef JSON_BEGIN
#undef JSON_FAIL
#undef JSON_END
print(s, "\n");
int buf = json_parse(s, _json_parse_object);
EXPECT_NE(-1, buf);
- for (int i = 0, n = buf_getsize(buf); i < n; ++i) {
- print(bufstr_get(buf, i), "\n");
- }
+ json_dump(buf);
SUCCEED();
}
--- /dev/null
+// generated file; do not modify
+#include "command.qc"
+#include "matrix.qc"
--- /dev/null
+#include "command.qh"
+
+#include <common/command/all.qh>
+
+GENERIC_COMMAND(mx, "Send a matrix command") {
+ switch (argv(1)) {
+ case "user":
+ if (matrix_user) strunzone(matrix_user);
+ matrix_user = strzone(substring(command, argv_start_index(2), -1));
+ break;
+ case "token":
+ if (matrix_access_token) strunzone(matrix_access_token);
+ matrix_access_token = strzone(substring(command, argv_start_index(2), -1));
+ break;
+ case "messages":
+ MX_Messages(string_null);
+ break;
+ case "nick":
+ MX_Nick(substring(command, argv_start_index(2), -1));
+ break;
+ case "join":
+ string s = substring(command, argv_start_index(2), -1);
+ if (s != matrix_room && matrix_room != "") {
+ MX_Leave(matrix_room);
+ strunzone(matrix_room);
+ }
+ matrix_room = strzone(s);
+ MX_Join(matrix_room);
+ break;
+ case "sync":
+ MX_Sync(string_null);
+ break;
+ case "typing":
+ MX_Typing(true);
+ break;
+ case "say":
+ MX_Say(substring(command, argv_start_index(2), -1));
+ break;
+ case "leave":
+ MX_Leave(matrix_room);
+ matrix_room = string_null;
+ break;
+ case "forget":
+ MX_Forget(matrix_room);
+ matrix_room = "";
+ break;
+ }
+}
--- /dev/null
+#pragma once
+
+#include "matrix.qh"
--- /dev/null
+#include "matrix.qh"
+
+.string message;
+
+void MX_Nick_(entity fh, entity pass, int status);
+void MX_Nick(string name)
+{
+ entity pass = new_pure(mx);
+ pass.message = name;
+ url_single_fopen(
+ sprintf("%s/_matrix/client/r0/profile/%s/displayname?access_token=%s", autocvar_matrix_server, matrix_user, matrix_access_token),
+ FILE_WRITE,
+ MX_Nick_,
+ pass
+ );
+}
+void MX_Nick_(entity fh, entity pass, int status)
+{
+ switch (status) {
+ case URL_READY_CANWRITE: {
+ fh.url_verb = "PUT";
+ fh.url_content_type = "application/json";
+ url_fputs(fh, sprintf("{\"displayname\": \"%s\"}", pass.message));
+ remove(pass);
+ url_fclose(fh);
+ break;
+ }
+ }
+}
+
+
+void MX_Messages_(entity fh, entity pass, int status);
+void MX_Messages(string from)
+{
+ string s = sprintf("%s/_matrix/client/r0/events?room_id=%s&limit=50&timeout=30000&from=%s&access_token=%s", autocvar_matrix_server, matrix_room, from, matrix_access_token);
+ url_single_fopen(
+ s,
+ FILE_READ,
+ MX_Messages_,
+ NULL
+ );
+}
+void MX_Messages_(entity fh, entity pass, int status)
+{
+ switch (status) {
+ default: {
+ LOG_WARNINGF("status: %d", status);
+ break;
+ }
+ case URL_READY_CLOSED: break;
+ case URL_READY_CANREAD: {
+ string json = "";
+ for (string s; (s = url_fgets(fh)); ) { json = strcat(json, s, "\n"); }
+ url_fclose(fh);
+ int buf = json_parse(json, _json_parse_object);
+ EXPECT_NE(-1, buf);
+ for (int i = 0, n = stof(json_get(buf, "chunk.length")); i < n; ++i) {
+ MX_Handle(buf, sprintf("chunk.%d", i));
+ }
+ MX_Messages(json_get(buf, "end"));
+ break;
+ }
+ }
+}
+
+
+void MX_Sync_(entity fh, entity pass, int status);
+void MX_Sync(string since)
+{
+ string s = strcat(autocvar_matrix_server, "/_matrix/client/r0/sync?");
+ if (since) {
+ s = strcat(s,
+ "since=", since, "&",
+ "timeout=30000&",
+ sprintf("filter={\"account_data\":{\"types\":[]},\"presence\":{\"types\":[]},\"room\":{\"rooms\":[\"%s\"]}}&", matrix_room)
+ );
+ } else {
+ s = strcat(s,
+ "timeout=0&",
+ "filter={\"account_data\":{\"types\":[]},\"presence\":{\"types\":[]},\"room\":{\"rooms\":[]}}&"
+ );
+ }
+ s = strcat(s, "access_token=", matrix_access_token);
+ url_single_fopen(s, FILE_READ, MX_Sync_, NULL);
+}
+void MX_Sync_(entity fh, entity pass, int status)
+{
+ switch (status) {
+ default: {
+ LOG_WARNINGF("status: %d", status);
+ break;
+ }
+ case URL_READY_CLOSED: break;
+ case URL_READY_CANREAD: {
+ string json = "";
+ for (string s; (s = url_fgets(fh)); ) { json = strcat(json, s, "\n"); }
+ url_fclose(fh);
+ int buf = json_parse(json, _json_parse_object);
+ EXPECT_NE(-1, buf);
+ string arr = sprintf("rooms.join.%s.timeline.events", matrix_room);
+ for (int i = 0, n = stof(json_get(buf, sprintf("%s.length", arr))); i < n; ++i) {
+ MX_Handle(buf, sprintf("%s.%d", arr, i));
+ }
+ MX_Sync(json_get(buf, "next_batch"));
+ break;
+ }
+ }
+}
+
+
+void MX_JLF_(entity fh, entity pass, int status);
+void MX_Join(string room)
+{
+ url_single_fopen(
+ sprintf("%s/_matrix/client/r0/rooms/%s/join?access_token=%s", autocvar_matrix_server, matrix_room, matrix_access_token),
+ FILE_WRITE,
+ MX_JLF_,
+ NULL
+ );
+}
+void MX_Leave(string room)
+{
+ url_single_fopen(
+ sprintf("%s/_matrix/client/r0/rooms/%s/leave?access_token=%s", autocvar_matrix_server, matrix_room, matrix_access_token),
+ FILE_WRITE,
+ MX_JLF_,
+ NULL
+ );
+}
+void MX_Forget(string room)
+{
+ url_single_fopen(
+ sprintf("%s/_matrix/client/r0/rooms/%s/forget?access_token=%s", autocvar_matrix_server, matrix_room, matrix_access_token),
+ FILE_WRITE,
+ MX_JLF_,
+ NULL
+ );
+}
+void MX_JLF_(entity fh, entity pass, int status)
+{
+ switch (status) {
+ case URL_READY_CANWRITE: {
+ fh.url_content_type = "application/json";
+ url_fputs(fh, sprintf("{}", pass.message));
+ url_fclose(fh);
+ break;
+ }
+ }
+}
+
+
+void MX_Typing_(entity fh, entity pass, int status);
+void MX_Typing(bool state)
+{
+ entity pass = new_pure(mx);
+ pass.message = state ? "true" : "false";
+ url_single_fopen(
+ sprintf("%s/_matrix/client/r0/rooms/%s/typing/%s?access_token=%s", autocvar_matrix_server, matrix_room, matrix_user, matrix_access_token),
+ FILE_WRITE,
+ MX_Typing_,
+ pass
+ );
+}
+void MX_Typing_(entity fh, entity pass, int status)
+{
+ switch (status) {
+ case URL_READY_CANWRITE: {
+ fh.url_verb = "PUT";
+ fh.url_content_type = "application/json";
+ url_fputs(fh, sprintf("{\"typing\": %s, \"timeout\": 30000}", pass.message));
+ remove(pass);
+ url_fclose(fh);
+ break;
+ }
+ }
+}
+
+
+void MX_Say_(entity fh, entity pass, int status);
+void MX_Say(string body)
+{
+ static int txnid;
+ entity pass = new_pure(mx);
+ pass.message = strzone(body);
+ url_single_fopen(
+ sprintf("%s/_matrix/client/r0/rooms/%s/send/m.room.message/%d?access_token=%s", autocvar_matrix_server, matrix_room, ++txnid, matrix_access_token),
+ FILE_WRITE,
+ MX_Say_,
+ pass
+ );
+}
+void MX_Say_(entity fh, entity pass, int status)
+{
+ switch (status) {
+ case URL_READY_CANWRITE: {
+ fh.url_verb = "PUT";
+ fh.url_content_type = "application/json";
+ url_fputs(fh, sprintf("{\"msgtype\": \"m.text\", \"body\": \"%s\"}", pass.message));
+ strunzone(pass.message); remove(pass);
+ url_fclose(fh);
+ break;
+ }
+ }
+}
--- /dev/null
+#pragma once
+
+string autocvar_matrix_server = "http://matrix.org";
+string matrix_user;
+string matrix_access_token;
+string matrix_room;
+
+void MX_Messages(string from);
+void MX_Nick(string name);
+void MX_Join(string room);
+void MX_Sync(string since);
+void MX_Typing(bool state);
+void MX_Say(string body);
+void MX_Leave(string room);
+void MX_Forget(string room);
+
+var void(int buf, string ancestor) MX_Handle;
if (pure) {
make_pure(this);
#ifdef CSQC
- setorigin(this, world.mins + '0 0 20');
+ setorigin(this, (world.mins + world.maxs) * 0.5);
#endif
#ifdef SVQC
- setorigin(this, world.maxs - '0 0 20');
+ setorigin(this, (world.mins + world.maxs) * 0.5);
#endif
}
return this;
#define EXPECT_FALSE(condition) EXPECT_EQ(false, condition)
#define ASSERT_FALSE(condition) ASSERT_EQ(false, condition)
-#define EXPECT_NE(val1, val2) EXPECT_TRUE(val1 != val2)
+#define EXPECT_NE(val1, val2) EXPECT_TRUE((val1) != (val2))
#define ASSERT_NE(val1, val2) _TEST_ASSERT(EXPECT_NE(val1, val2))
-#define EXPECT_LT(val1, val2) EXPECT_TRUE(val1 < val2)
+#define EXPECT_LT(val1, val2) EXPECT_TRUE((val1) < (val2))
#define ASSERT_LT(val1, val2) _TEST_ASSERT(EXPECT_LT(val1, val2))
-#define EXPECT_LE(val1, val2) EXPECT_TRUE(val1 <= val2)
+#define EXPECT_LE(val1, val2) EXPECT_TRUE((val1) <= (val2))
#define ASSERT_LE(val1, val2) _TEST_ASSERT(EXPECT_LE(val1, val2))
-#define EXPECT_GT(val1, val2) EXPECT_TRUE(val1 > val2)
+#define EXPECT_GT(val1, val2) EXPECT_TRUE((val1) > (val2))
#define ASSERT_GT(val1, val2) _TEST_ASSERT(EXPECT_GT(val1, val2))
-#define EXPECT_GE(val1, val2) EXPECT_TRUE(val1 >= val2)
+#define EXPECT_GE(val1, val2) EXPECT_TRUE((val1) >= (val2))
#define ASSERT_GE(val1, val2) _TEST_ASSERT(EXPECT_GE(val1, val2))
#define EXPECT_NO_FATAL_FAILURE(statement) EXPECT_NO_FATAL_FAILURE_(statement, { })
// URLs
.string url_url;
+.string url_content_type;
+.string url_verb;
.float url_wbuf;
.float url_wbufpos;
.float url_rbuf;
// create a writing end that does nothing yet
e = new_pure(url_single_fopen_file);
e.url_url = strzone(url);
+ e.url_content_type = "text/plain";
+ e.url_verb = "";
e.url_fh = URL_FH_CURL;
e.url_wbuf = buf_create();
if (e.url_wbuf < 0)
}
// POST the data
- if (!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, "text/plain", "", e.url_wbuf, 0))
+ if (!crypto_uri_postbuf(e.url_url, i + MIN_URL_ID, e.url_content_type, e.url_verb, e.url_wbuf, 0))
{
LOG_INFO("url_fclose: failure in crypto_uri_postbuf\n");
e.url_ready(e, e.url_ready_pass, URL_READY_ERROR);
// generated file; do not modify
#include "draw.qc"
#include "item.qc"
+#include "matrix.qc"
#include "menu.qc"
--- /dev/null
+var void MX_Handle(int buf, string ancestor)
+{
+ string type = json_get(buf, strcat(ancestor, ".type"));
+ switch (type) {
+ case "m.typing": {
+ string arr = strcat(ancestor, ".content.user_ids");
+ for (int i = 0, n = stof(json_get(buf, sprintf("%s.length", arr))); i < n; ++i) {
+ string s = json_get(buf, sprintf("%s.%d", arr, i));
+ print("\{1}", s, " is typing...\n");
+ }
+ break;
+ }
+ case "m.room.message": {
+ string msgtype = json_get(buf, strcat(ancestor, ".content.msgtype"));
+ switch (msgtype) {
+ case "m.text": {
+ string sender = json_get(buf, strcat(ancestor, ".sender"));
+ string body = json_get(buf, strcat(ancestor, ".content.body"));
+ if (body) print("\{1}", sender, ": ", body, "\n");
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticCheckBox_T(1, "mod_q3bsp_nolightmaps", _("Use lightmaps"),
_("Use high resolution lightmaps, which will look pretty but use up some extra video memory (default: enabled)")));
+ e.applyButton = effectsApplyButton;
me.TD(me, 1, 1, e = makeXonoticCheckBox_T(0, "r_glsl_deluxemapping", _("Deluxe mapping"),
_("Use per-pixel lighting effects (default: enabled)")));
setDependentAND(e, "vid_gl20", 1, 1, "mod_q3bsp_nolightmaps", 0, 0);
e.addValue(e, _("4x"), "4");
e.configureXonoticTextSliderValues(e);
setDependent(e, "r_viewfbo", 0, 0);
+ e.applyButton = videoApplyButton;
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBoxEx(2, 0, "r_viewfbo", _("High-quality frame buffer")));
setDependent(e, "vid_samples", 1, 1);
_("Make the CPU wait for the GPU to finish each frame, can help with some strange input or video lag on some machines (default: disabled)")));
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "vid_gl20", _("Use OpenGL 2.0 shaders (GLSL)")));
+ e.applyButton = videoApplyButton;
me.TR(me);
me.TDempty(me, 0.2);
me.TD(me, 1, 2.8, e = makeXonoticCheckBox_T(0, "v_glslgamma", _("Use GLSL to handle color control"),
#include "ipban.qc"
#include "item_key.qc"
#include "mapvoting.qc"
+#include "matrix.qc"
#include "miscfunctions.qc"
#include "playerdemo.qc"
#include "portals.qc"
w = new(waypoint);
w.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
w.wpflags = f;
+ w.solid = SOLID_TRIGGER;
setorigin(w, (m1 + m2) * 0.5);
setsize(w, m1 - w.origin, m2 - w.origin);
if (vlen(w.size) > 0)
this.oldorigin = this.origin;
this.prevorigin = this.origin;
this.lastteleporttime = time; // prevent insane speeds due to changing origin
- this.hud = HUD_NORMAL;
+ this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
+ this.hud = HUD_NORMAL;
this.event_damage = PlayerDamage;
* 0 = reject
* -1 = fake accept
*/
-int Say(entity source, float teamsay, entity privatesay, string msgin, bool floodcontrol)
+int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol)
{
- string msgstr, colorstr, cmsgstr, namestr, fullmsgstr, sourcemsgstr, fullcmsgstr, sourcecmsgstr, colorprefix;
- float flood;
- var .float flood_field;
- float ret;
- string privatemsgprefix = string_null; float privatemsgprefixlen = 0;
-
- if(!teamsay && !privatesay)
- if(substring(msgin, 0, 1) == " ")
- msgin = substring(msgin, 1, strlen(msgin) - 1); // work around DP say bug (say_team does not have this!)
+ if (!teamsay && !privatesay) if (substring(msgin, 0, 1) == " ")
+ msgin = substring(msgin, 1, -1); // work around DP say bug (say_team does not have this!)
msgin = formatmessage(msgin);
+ string colorstr;
if (!IS_PLAYER(source))
colorstr = "^0"; // black for spectators
else if(teamplay)
if(intermission_running)
teamsay = false;
+ if (!source) {
+ colorstr = "";
+ teamsay = false;
+ }
+
if(msgin != "")
msgin = trigger_magicear_processmessage_forallears(source, teamsay, privatesay, msgin);
}
*/
- if(autocvar_g_chat_teamcolors)
- namestr = playername(source);
- else
- namestr = source.netname;
+ string namestr = "";
+ if (source)
+ namestr = autocvar_g_chat_teamcolors ? playername(source) : source.netname;
- if(strdecolorize(namestr) == namestr)
- colorprefix = "^3";
- else
- colorprefix = "^7";
+ string colorprefix = (strdecolorize(namestr) == namestr) ? "^3" : "^7";
- if(msgin != "")
- {
+ string msgstr, cmsgstr;
+ string privatemsgprefix = string_null;
+ int privatemsgprefixlen = 0;
+ if (msgin == "") {
+ msgstr = cmsgstr = "";
+ } else {
if(privatesay)
{
msgstr = strcat("\{1}\{13}* ", colorprefix, namestr, "^3 tells you: ^7");
msgin = strreplace("/me", strcat(colorprefix, namestr), msgin);
msgstr = strcat("\{1}^4* ", "^7", msgin);
}
- else
- msgstr = strcat("\{1}", colorprefix, namestr, "^7: ", msgin);
+ else {
+ msgstr = "\{1}";
+ msgstr = strcat(msgstr, (namestr != "") ? strcat(colorprefix, namestr, "^7: ") : "^7");
+ msgstr = strcat(msgstr, msgin);
+ }
cmsgstr = "";
}
msgstr = strcat(strreplace("\n", " ", msgstr), "\n"); // newlines only are good for centerprint
}
- else
- {
- msgstr = cmsgstr = "";
- }
- fullmsgstr = msgstr;
- fullcmsgstr = cmsgstr;
+ string fullmsgstr = msgstr;
+ string fullcmsgstr = cmsgstr;
// FLOOD CONTROL
- flood = 0;
- flood_field = floodcontrol_chat;
+ int flood = 0;
+ var .float flood_field = floodcontrol_chat;
if(floodcontrol)
{
float flood_spl;
source.(flood_field) = flood = 0;
}
+ string sourcemsgstr, sourcecmsgstr;
if(flood == 2) // cannot happen for empty msgstr
{
if(autocvar_g_chat_flood_notify_flooder)
if(privatesay)
sourcemsgstr = strcat(privatemsgprefix, substring(sourcemsgstr, privatemsgprefixlen, -1));
+ int ret;
if(source.muted)
{
// always fake the message
{
sprint(source, sourcemsgstr);
dedicated_print(msgstr); // send to server console too
- FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && it.active_minigame == source.active_minigame, LAMBDA(sprint(it, msgstr)));
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source && it.active_minigame == source.active_minigame, sprint(it, msgstr));
}
else if(teamsay > 0) // team message, only sent to team mates
{
dedicated_print(msgstr); // send to server console too
if(sourcecmsgstr != "")
centerprint(source, sourcecmsgstr);
- FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source && it.team == source.team, LAMBDA(
+ FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source && it.team == source.team, {
sprint(it, msgstr);
if(cmsgstr != "")
centerprint(it, cmsgstr);
- ));
+ });
}
else if(teamsay < 0) // spectator message, only sent to spectators
{
sprint(source, sourcemsgstr);
dedicated_print(msgstr); // send to server console too
- FOREACH_CLIENT(!IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source, LAMBDA(sprint(it, msgstr)));
+ FOREACH_CLIENT(!IS_PLAYER(it) && IS_REAL_CLIENT(it) && it != source, sprint(it, msgstr));
}
- else if(sourcemsgstr != msgstr) // trimmed/server fixed message, sent to all players
- {
- sprint(source, sourcemsgstr);
- dedicated_print(msgstr); // send to server console too
- FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source, LAMBDA(sprint(it, msgstr)));
- }
- else
- bprint(msgstr); // entirely normal message, sent to all players -- bprint sends to server console too.
+ else {
+ if (sourcemsgstr != msgstr) { // trimmed/server fixed message, sent to all players
+ sprint(source, sourcemsgstr);
+ dedicated_print(msgstr); // send to server console too
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != source, sprint(it, msgstr));
+ } else { // entirely normal message, sent to all players -- bprint sends to server console too.
+ bprint(msgstr);
+ }
+ if (source) MX_Say(strcat(playername(source), "^7: ", msgin));
+ }
}
return ret;
--- /dev/null
+#include "matrix.qh"
+
+#include "cl_player.qh"
+
+var void MX_Handle(int buf, string ancestor)
+{
+ string type = json_get(buf, strcat(ancestor, ".type"));
+ switch (type) {
+ case "m.room.message": {
+ string msgtype = json_get(buf, strcat(ancestor, ".content.msgtype"));
+ switch (msgtype) {
+ case "m.text": {
+ string sender = json_get(buf, strcat(ancestor, ".sender"));
+ string body = json_get(buf, strcat(ancestor, ".content.body"));
+ if (sender != matrix_user && body) Say(NULL, false, NULL, body, false);
+ break;
+ }
+ }
+ break;
+ }
+ }
+}
--- /dev/null
+#pragma once
sv_logscores_bots 1
g_weaponarena all
g_weaponarena_random 2
+g_playerstats_gamereport_uri ""
// Start!