- 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=0a9ea83e32e148da989cbbadc7421ea0
+ - EXPECT=93decd0a82cf911f02fb5572197db7f3
- HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
| tee /dev/stderr
| grep '^:'
seta cl_damagetext_velocity "0 0 20" "Damage text move direction"
seta cl_damagetext_offset "0 -40 0" "Damage text offset"
seta cl_damagetext_accumulate_range "30" "Damage text spawned within this range is accumulated"
+seta cl_damagetext_accumulate_alpha_rel "0.65" "Only update existing damage text when it's above this much percentage (0 to 1) of the starting alpha"
seta cl_damagetext_friendlyfire "1" "Show damage text for friendlyfire too"
seta cl_damagetext_friendlyfire_color "1 0 0" "Damage text color for friendlyfire"
// {{{ Misc
set g_monsters 1
set g_monsters_edit 0
-set g_monsters_think_delay 0.1
+set g_monsters_think_delay 0.03333
set g_monsters_skill 1 "Monster skill (affecting some of their attributes). 1 - easy, 2 - medium, 3 - hard, 4 - insane, 5 - nightmare"
set g_monsters_miniboss_chance 5
set g_monsters_miniboss_healthboost 100
set g_spawn_near_teammate 0 "if set, players prefer spawns near a team mate"
set g_spawn_near_teammate_distance 640 "max distance to consider a spawn to be near a team mate"
set g_spawn_near_teammate_ignore_spawnpoint 0 "ignore spawnpoints and spawn right at team mates, if 2, clients can ignore this option"
+set g_spawn_near_teammate_ignore_spawnpoint_max 10 "if set, test at most this many of the available teammates"
set g_spawn_near_teammate_ignore_spawnpoint_delay 2.5 "how long to wait before its OK to spawn at a player after someone just spawned at this player"
-set g_spawn_near_teammate_ignore_spawnpoint_delay_death 0 "how long to wait before its OK to spawn at a player after death"
+set g_spawn_near_teammate_ignore_spawnpoint_delay_death 3 "how long to wait before its OK to spawn at a player after death"
set g_spawn_near_teammate_ignore_spawnpoint_check_health 1 "only allow spawn at this player if their health is full"
set g_spawn_near_teammate_ignore_spawnpoint_closetodeath 1 "spawn as close to death location as possible"
set g_walljump_delay 1 "Minimum delay between wall jumps"
set g_walljump_force 300 "How far to bounce/jump off the wall"
set g_walljump_velocity_xy_factor 1.15 "How much to slow down along horizontal axis, higher value = higher deceleration, if factor is < 1, you accelerate by wall jumping"
-set g_walljump_velocity_z_factor 0.5 "Upwards velocity factor, multiplied by normal jump velocity"
\ No newline at end of file
+set g_walljump_velocity_z_factor 0.5 "Upwards velocity factor, multiplied by normal jump velocity"
.int team;
.int team_size;
-float vid_conwidth, vid_conheight;
+float vid_conheight;
int binddb;
// QUALIFYING
float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
#endif
-float servertime, serverprevtime, serverdeltatime;
+float serverprevtime, serverdeltatime;
float ticrate;
#include "quickmenu.qh"
#include <common/ent_cs.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/mapinfo.qh>
#include <common/minigames/cl_minigames.qh>
#include <common/stats.qh>
int weapon_stats = weapon_accuracy[i - WEP_FIRST];
WepSet set = it.m_wepset;
- if (weapon_stats < 0)
+ if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
{
- if (!(weapons_stat & set) && (it.spawnflags & WEP_FLAG_HIDDEN || it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
- nHidden += 1;
- else if (!(weapons_stat & set || weapons_inmap & set))
+ if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)))
+ ++nHidden;
+ else
++disownedcnt;
}
});
int weapon_stats = weapon_accuracy[i - WEP_FIRST];
WepSet set = it.m_wepset;
- if (weapon_stats < 0 && !(weapons_stat & set || weapons_inmap & set))
+ if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
continue;
float weapon_alpha;
#include <common/mapinfo.qh>
#include <common/minigames/cl_minigames.qh>
#include <common/minigames/cl_minigames_hud.qh>
+#include <common/net_linked.qh>
#include <common/net_notice.qh>
#include <common/triggers/include.qh>
#include <common/vehicles/all.qh>
#if XONOTIC
#include <client/_all.inc>
-#endif
#include <ecs/_mod.inc>
+#endif
#ifdef BUILD_MOD
#include <mod/client/progs.inc>
#include <common/ent_cs.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/mapinfo.qh>
#include <common/teams.qh>
#include <common/ent_cs.qh>
#include <common/anim.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/debug.qh>
#include <common/mapinfo.qh>
#include <common/gamemodes/_mod.qh>
#include <common/triggers/target/music.qh>
#include <common/teams.qh>
+#include <common/weapons/weapon/tuba.qh>
+
#include <common/vehicles/all.qh>
#include <common/weapons/_all.qh>
#include <common/viewloc.qh>
{
static string name_last;
string name = wep.mdl;
+ if(wep == WEP_TUBA)
+ {
+ name = (this.tuba_instrument == 0) ? "tuba" :
+ (this.tuba_instrument == 1) ? "akordeon" :
+ "kleinbottle";
+ }
bool swap = name != name_last;
// if (swap)
{
#include "../mutators/events.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/physics/movetypes/movetypes.qh>
#include <lib/csqcmodel/interpolate.qh>
#pragma once
-REGISTER_NET_TEMP(TE_CSQC_PICTURE)
-REGISTER_NET_TEMP(TE_CSQC_RACE)
-REGISTER_NET_TEMP(TE_CSQC_TEAMNAGGER)
-REGISTER_NET_TEMP(TE_CSQC_PINGPLREPORT)
-REGISTER_NET_TEMP(TE_CSQC_WEAPONCOMPLAIN)
-REGISTER_NET_TEMP(TE_CSQC_VEHICLESETUP)
-
-const int RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
-const int RACE_NET_CHECKPOINT_CLEAR = 1;
-const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING = 2; // byte nextcheckpoint, short recordtime, string recordholder
-const int RACE_NET_CHECKPOINT_HIT_RACE = 3; // byte checkpoint, short delta, byte lapsdelta, string opponent
-const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT = 4; // byte checkpoint, short delta, byte lapsdelta, string opponent
-const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING = 5; // byte nextcheckpoint, float laptime, short recordtime, string recordholder
-const int RACE_NET_PENALTY_RACE = 6; // byte penaltytime, string reason
-const int RACE_NET_PENALTY_QUALIFYING = 7; // byte penaltytime, string reason
-const int RACE_NET_SERVER_RECORD = 8; // server record, sent to client
-const int RACE_NET_SPEED_AWARD = 9; // speed award, sent to client
-const int RACE_NET_SPEED_AWARD_BEST = 10; // all time best speed award, sent to client
-const int RACE_NET_SERVER_RANKINGS = 11;
-const int RACE_NET_SERVER_STATUS = 12;
const int RANKINGS_CNT = 15;
-REGISTER_NET_LINKED(_ENT_CLIENT_INIT)
-#ifdef CSQC
-NET_HANDLE(_ENT_CLIENT_INIT, bool isnew) { make_pure(this); return true; }
-#endif
-/** Sent as a temp entity from a persistent linked entity */
-REGISTER_NET_TEMP(ENT_CLIENT_INIT)
-
-REGISTER_NET_LINKED(ENT_CLIENT_SCORES_INFO)
-REGISTER_NET_LINKED(ENT_CLIENT_SCORES)
-REGISTER_NET_LINKED(ENT_CLIENT_TEAMSCORES)
-REGISTER_NET_LINKED(ENT_CLIENT_NAGGER) // flags [votecalledvote]
-REGISTER_NET_LINKED(ENT_CLIENT_RADARLINK) // flags [startorigin] [endorigin] [startcolor+16*endcolor]
-REGISTER_NET_LINKED(ENT_CLIENT_PROJECTILE)
-REGISTER_NET_LINKED(ENT_CLIENT_MAPVOTE)
-REGISTER_NET_LINKED(ENT_CLIENT_CLIENTDATA)
-REGISTER_NET_LINKED(ENT_CLIENT_RANDOMSEED)
-REGISTER_NET_LINKED(ENT_CLIENT_ACCURACY)
-REGISTER_NET_LINKED(ENT_CLIENT_ELIMINATEDPLAYERS)
-
-REGISTER_NET_LINKED(ENT_CLIENT_MODEL)
-
-REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE)
-REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_CAMERA)
-REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_TELEPORTED)
-
-REGISTER_NET_LINKED(ENT_CLIENT_ARC_BEAM)
-REGISTER_NET_LINKED(ENT_CLIENT_HOOK)
-REGISTER_NET_LINKED(ENT_CLIENT_TUBANOTE)
-
-REGISTER_NET_LINKED(ENT_CLIENT_SPAWNPOINT)
-REGISTER_NET_LINKED(ENT_CLIENT_SPAWNEVENT)
-REGISTER_NET_LINKED(ENT_CLIENT_WALL)
-
const int SPRITERULE_DEFAULT = 0;
const int SPRITERULE_TEAMPLAY = 1;
const int SPRITERULE_SPECTATOR = 2;
gren.damageforcescale = 0;
gren.event_damage = M_Shambler_Attack_Lightning_Damage;
gren.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, gren);
gren.missile_flags = MIF_SPLASH | MIF_ARC;
W_SetupProjVelocity_Explicit(gren, v_forward, v_up, (autocvar_g_monster_shambler_attack_lightning_speed), (autocvar_g_monster_shambler_attack_lightning_speed_up), 0, 0, false);
IL_PUSH(g_projectiles, proj);
IL_PUSH(g_bot_dodge, proj);
proj.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, proj);
proj.bouncefactor = 0.3;
proj.bouncestop = 0.05;
this.bot_attack = true;
this.iscreature = true;
this.teleportable = true;
+ if(!this.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, this);
this.damagedbycontents = true;
this.monsterid = mon_id;
this.event_damage = Monster_Damage;
#define X(OFFSET) \
tracebox(this.origin, this.mins, this.maxs, this.origin + OFFSET, true, this); \
- if(trace_fraction < 1 && vdist(this.origin - trace_endpos, <, threshold)) \
+ if(trace_fraction < 1 && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) && vdist(this.origin - trace_endpos, <, threshold)) \
return true;
X(1000*v_right);
X(-1000*v_right);
start_items |= IT_UNLIMITED_SUPERWEAPONS;
}
+MUTATOR_HOOKFUNCTION(mutator_instagib, SetWeaponArena)
+{
+ // turn weapon arena off
+ M_ARGV(0, string) = "off";
+}
+
void replace_with_insta_cells(entity item)
{
entity e = spawn();
start_weapons = warmup_start_weapons = WEPSET(SHOTGUN);
}
+MUTATOR_HOOKFUNCTION(melee_only, SetWeaponArena)
+{
+ // turn weapon arena off
+ M_ARGV(0, string) = "off";
+}
+
MUTATOR_HOOKFUNCTION(melee_only, ForbidThrowCurrentWeapon)
{
return true;
_nade.gravity = 1;
_nade.missile_flags = MIF_SPLASH | MIF_ARC;
_nade.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, _nade);
_nade.angles = vectoangles(_nade.velocity);
_nade.flags = FL_PROJECTILE;
IL_PUSH(g_projectiles, _nade);
METHOD(NadeOffhand, offhand_think, void(NadeOffhand this, entity player, bool key_pressed))
{
entity held_nade = player.nade;
- if (held_nade)
- {
- player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
- // LOG_TRACEF("%d %d", player.nade_timer, time - held_nade.nade_time_primed);
- makevectors(player.angles);
- held_nade.velocity = player.velocity;
- setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
- held_nade.angles_y = player.angles.y;
-
- if (time + 0.1 >= held_nade.wait)
- toss_nade(player, false, '0 0 0', time + 0.05);
- }
if (!CanThrowNade(player)) return;
if (!(time > player.nade_refire)) return;
if (player.nade && (player.offhand != OFFHAND_NADE || (player.weapons & WEPSET(HOOK)))) OFFHAND_NADE.offhand_think(OFFHAND_NADE, player, player.nade_altbutton);
+ entity held_nade = player.nade;
+ if (held_nade)
+ {
+ player.nade_timer = bound(0, (time - held_nade.nade_time_primed) / autocvar_g_nades_nade_lifetime, 1);
+ // LOG_TRACEF("%d %d", player.nade_timer, time - held_nade.nade_time_primed);
+ makevectors(player.angles);
+ held_nade.velocity = player.velocity;
+ setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
+ held_nade.angles_y = player.angles.y;
+
+ if (time + 0.1 >= held_nade.wait)
+ toss_nade(player, false, '0 0 0', time + 0.05);
+ }
+
if(IS_PLAYER(player))
{
if ( autocvar_g_nades_bonus && autocvar_g_nades )
missile.health = WEP_CVAR(rpc, health);
missile.event_damage = W_RocketPropelledChainsaw_Damage;
missile.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, missile);
set_movetype(missile, MOVETYPE_FLY);
missile.projectiledeathtype = WEP_RPC.m_id;
start_weapons = warmup_start_weapons = ok_start_items;
}
+MUTATOR_HOOKFUNCTION(ok, SetWeaponArena)
+{
+ // turn weapon arena off
+ M_ARGV(0, string) = "off";
+}
+
MUTATOR_HOOKFUNCTION(ok, BuildMutatorsString)
{
M_ARGV(0, string) = strcat(M_ARGV(0, string), ":OK");
#include "sv_spawn_near_teammate.qh"
+const float FLOAT_MAX = 340282346638528859811704183484516925440.0f;
+
float autocvar_g_spawn_near_teammate_distance;
int autocvar_g_spawn_near_teammate_ignore_spawnpoint;
+int autocvar_g_spawn_near_teammate_ignore_spawnpoint_max;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
float autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
-int autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
+bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health;
bool autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath;
REGISTER_MUTATOR(spawn_near_teammate, cvar("g_spawn_near_teammate"));
.entity msnt_lookat;
.float msnt_timer;
-.vector msnt_deathloc;
.float cvar_cl_spawn_near_teammate;
player.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay_death;
entity best_mate = NULL;
- vector best_spot = '0 0 0';
- float pc = 0, best_dist = 0, dist = 0;
- FOREACH_CLIENT(IS_PLAYER(it), LAMBDA(
- if((autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health >= 0 && it.health >= autocvar_g_balance_health_regenstable) || autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health == 0)
- if(!IS_DEAD(it))
- if(it.msnt_timer < time)
- if(SAME_TEAM(player, it))
- if(time > it.spawnshieldtime) // spawn shielding
- if(!forbidWeaponUse(it))
- if(STAT(FROZEN, it) == 0)
- if(it != player)
+ vector best_pos = '0 0 0';
+ float best_dist2 = FLOAT_MAX;
+ int tested = 0;
+ FOREACH_CLIENT_RANDOM(IS_PLAYER(it), LAMBDA(
+ if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_max && tested >= autocvar_g_spawn_near_teammate_ignore_spawnpoint_max) break;
+ if (!SAME_TEAM(player, it)) continue;
+ if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_check_health && it.health < autocvar_g_balance_health_regenstable) continue;
+ if (IS_DEAD(it)) continue;
+ if (time < it.msnt_timer) continue;
+ if (time < it.spawnshieldtime) continue;
+ if (forbidWeaponUse(it)) continue;
+ if (it == player) continue;
+
+ tested++; // i consider a teammate to be available when he passes the checks above
+
+ vector horiz_vel = vec2(it.velocity);
+ // when walking slowly sideways, we assume the player wants a clear shot ahead - spawn behind him according to where he's looking
+ // when running fast, spawn behind him according to his direction of movement to prevent colliding with the newly spawned player
+ if (vdist(horiz_vel, >, autocvar_sv_maxspeed + 50))
+ fixedmakevectors(vectoangles(horiz_vel));
+ else
+ fixedmakevectors(it.angles); // .angles is the angle of the model - usually/always 0 pitch
+
+ // test different spots close to mate - trace upwards so it works on uneven surfaces
+ // don't spawn in front of player or directly behind to avoid players shooting each other
+ // test the potential spots in pairs (first pair is better than second and so on) but don't prefer one side
+ RandomSelection_Init();
+ for(int i = 0; i < 6; ++i)
{
- tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - '0 0 100', MOVE_NOMONSTERS, it);
- if(trace_fraction != 1.0)
- if(!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY))
+ switch(i)
{
- pc = pointcontents(trace_endpos + '0 0 1');
- if(pc == CONTENT_EMPTY)
+ case 0:
+ tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 64 + v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+ break;
+ case 1:
+ tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 64 - v_right * 128 + v_up * 64, MOVE_NOMONSTERS, it);
+ break;
+ case 2:
+ tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+ break;
+ case 3:
+ tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 192 + v_up * 64, MOVE_NOMONSTERS, it);
+ break;
+ case 4:
+ tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128 + v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+ break;
+ case 5:
+ tracebox(it.origin, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128 - v_right * 64 + v_up * 64, MOVE_NOMONSTERS, it);
+ break;
+ }
+
+ vector horizontal_trace_endpos = trace_endpos;
+ //te_lightning1(NULL, it.origin, horizontal_trace_endpos);
+ if (trace_fraction != 1.0) goto skip;
+
+ // 400 is about the height of a typical laser jump (in overkill)
+ // not traceline because we need space for the whole player, not just his origin
+ tracebox(horizontal_trace_endpos, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), horizontal_trace_endpos - '0 0 400', MOVE_NORMAL, it);
+ vector vectical_trace_endpos = trace_endpos;
+ //te_lightning1(NULL, horizontal_trace_endpos, vectical_trace_endpos);
+ if (trace_startsolid) goto skip; // inside another player
+ if (trace_fraction == 1.0) goto skip; // above void or too high
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) goto skip;
+ if (pointcontents(vectical_trace_endpos) != CONTENT_EMPTY) goto skip; // no lava or slime (or water which i assume would be annoying anyway)
+ if (tracebox_hits_trigger_hurt(horizontal_trace_endpos, STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), vectical_trace_endpos)) goto skip;
+
+ // make sure the spawned player will have floor ahead (or at least a wall - he shouldn't fall as soon as he starts moving)
+ vector floor_test_start = vectical_trace_endpos + v_up * STAT(PL_MAX, NULL).z + v_forward * STAT(PL_MAX, NULL).x; // top front of player's bbox - highest point we know is not inside solid
+ traceline(floor_test_start, floor_test_start + v_forward * 100 - v_up * 128, MOVE_NOMONSTERS, it);
+ //te_beam(NULL, floor_test_start, trace_endpos);
+ if (trace_fraction == 1.0) goto skip;
+
+ if (autocvar_g_nades) {
+ bool nade_in_range = false;
+ IL_EACH(g_projectiles, it.classname == "nade",
{
- if(vdist(it.velocity, >, 5))
- fixedmakevectors(vectoangles(it.velocity));
- else
- fixedmakevectors(it.angles);
+ if (vdist(it.origin - vectical_trace_endpos, <, autocvar_g_nades_nade_radius)) {
+ nade_in_range = true;
+ goto skip;
+ }
+ });
+ if (nade_in_range) goto skip;
+ }
+
+ // here, we know we found a good spot
+ RandomSelection_Add(it, 0, string_null, vectical_trace_endpos, 1, 1);
+ //te_lightning1(NULL, vectical_trace_endpos, vectical_trace_endpos + v_forward * 10);
- for(pc = 0; pc < 4; ++pc) // test 4 diffrent spots close to mate
+LABEL(skip)
+ if (i % 2 == 1 && RandomSelection_chosen_ent)
+ {
+ if (autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
+ {
+ float dist2 = vlen2(RandomSelection_chosen_ent.origin - player.death_origin);
+ if (dist2 < best_dist2)
{
- switch(pc)
- {
- case 0:
- tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 128, MOVE_NOMONSTERS, it);
- break;
- case 1:
- tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 128 , MOVE_NOMONSTERS, it);
- break;
- case 2:
- tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin + v_right * 128 - v_forward * 64, MOVE_NOMONSTERS, it);
- break;
- case 3:
- tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_right * 128 - v_forward * 64, MOVE_NOMONSTERS, it);
- break;
- //case 4:
- //tracebox(it.origin , STAT(PL_MIN, NULL), STAT(PL_MAX, NULL), it.origin - v_forward * 128, MOVE_NOMONSTERS, it);
- //break;
- }
-
- if(trace_fraction == 1.0)
- {
- traceline(trace_endpos + '0 0 4', trace_endpos - '0 0 100', MOVE_NOMONSTERS, it);
- if(trace_fraction != 1.0)
- {
- if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
- {
- dist = vlen(trace_endpos - player.msnt_deathloc);
- if(dist < best_dist || best_dist == 0)
- {
- best_dist = dist;
- best_spot = trace_endpos;
- best_mate = it;
- }
- }
- else
- {
- setorigin(player, trace_endpos);
- player.angles = it.angles;
- player.angles_z = 0; // never spawn tilted even if the spot says to
- it.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
- return;
- }
- }
- }
+ best_dist2 = dist2;
+ best_pos = RandomSelection_chosen_vec;
+ best_mate = RandomSelection_chosen_ent;
}
}
+ else
+ {
+ setorigin(player, RandomSelection_chosen_vec);
+ player.angles = RandomSelection_chosen_ent.angles;
+ player.angles_z = 0; // never spawn tilted even if the spot says to
+ RandomSelection_chosen_ent.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
+ return;
+ }
+ break; // don't test the other spots near this teammate, go to the next one
}
}
));
if(autocvar_g_spawn_near_teammate_ignore_spawnpoint_closetodeath)
- if(best_dist)
+ if(best_mate)
{
- setorigin(player, best_spot);
+ setorigin(player, best_pos);
player.angles = best_mate.angles;
player.angles_z = 0; // never spawn tilted even if the spot says to
best_mate.msnt_timer = time + autocvar_g_spawn_near_teammate_ignore_spawnpoint_delay;
}
}
-MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerDies)
-{
- entity frag_target = M_ARGV(0, entity);
-
- frag_target.msnt_deathloc = frag_target.origin;
-}
-
REPLICATE(cvar_cl_spawn_near_teammate, bool, "cl_spawn_near_teammate");
--- /dev/null
+#pragma once
+
+REGISTER_NET_TEMP(TE_CSQC_PICTURE)
+REGISTER_NET_TEMP(TE_CSQC_RACE)
+REGISTER_NET_TEMP(TE_CSQC_TEAMNAGGER)
+REGISTER_NET_TEMP(TE_CSQC_PINGPLREPORT)
+REGISTER_NET_TEMP(TE_CSQC_WEAPONCOMPLAIN)
+REGISTER_NET_TEMP(TE_CSQC_VEHICLESETUP)
+
+const int RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
+const int RACE_NET_CHECKPOINT_CLEAR = 1;
+const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING = 2; // byte nextcheckpoint, short recordtime, string recordholder
+const int RACE_NET_CHECKPOINT_HIT_RACE = 3; // byte checkpoint, short delta, byte lapsdelta, string opponent
+const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT = 4; // byte checkpoint, short delta, byte lapsdelta, string opponent
+const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING = 5; // byte nextcheckpoint, float laptime, short recordtime, string recordholder
+const int RACE_NET_PENALTY_RACE = 6; // byte penaltytime, string reason
+const int RACE_NET_PENALTY_QUALIFYING = 7; // byte penaltytime, string reason
+const int RACE_NET_SERVER_RECORD = 8; // server record, sent to client
+const int RACE_NET_SPEED_AWARD = 9; // speed award, sent to client
+const int RACE_NET_SPEED_AWARD_BEST = 10; // all time best speed award, sent to client
+const int RACE_NET_SERVER_RANKINGS = 11;
+const int RACE_NET_SERVER_STATUS = 12;
+
+REGISTER_NET_LINKED(_ENT_CLIENT_INIT)
+#ifdef CSQC
+NET_HANDLE(_ENT_CLIENT_INIT, bool isnew) { make_pure(this); return true; }
+#endif
+/** Sent as a temp entity from a persistent linked entity */
+REGISTER_NET_TEMP(ENT_CLIENT_INIT)
+
+REGISTER_NET_LINKED(ENT_CLIENT_SCORES_INFO)
+REGISTER_NET_LINKED(ENT_CLIENT_SCORES)
+REGISTER_NET_LINKED(ENT_CLIENT_TEAMSCORES)
+REGISTER_NET_LINKED(ENT_CLIENT_NAGGER) // flags [votecalledvote]
+REGISTER_NET_LINKED(ENT_CLIENT_RADARLINK) // flags [startorigin] [endorigin] [startcolor+16*endcolor]
+REGISTER_NET_LINKED(ENT_CLIENT_PROJECTILE)
+REGISTER_NET_LINKED(ENT_CLIENT_MAPVOTE)
+REGISTER_NET_LINKED(ENT_CLIENT_CLIENTDATA)
+REGISTER_NET_LINKED(ENT_CLIENT_RANDOMSEED)
+REGISTER_NET_LINKED(ENT_CLIENT_ACCURACY)
+REGISTER_NET_LINKED(ENT_CLIENT_ELIMINATEDPLAYERS)
+
+REGISTER_NET_LINKED(ENT_CLIENT_MODEL)
+
+REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE)
+REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_CAMERA)
+REGISTER_NET_LINKED(ENT_CLIENT_WARPZONE_TELEPORTED)
+
+REGISTER_NET_LINKED(ENT_CLIENT_ARC_BEAM)
+REGISTER_NET_LINKED(ENT_CLIENT_HOOK)
+REGISTER_NET_LINKED(ENT_CLIENT_TUBANOTE)
+
+REGISTER_NET_LINKED(ENT_CLIENT_SPAWNPOINT)
+REGISTER_NET_LINKED(ENT_CLIENT_SPAWNEVENT)
+REGISTER_NET_LINKED(ENT_CLIENT_WALL)
#elif defined(MENUQC)
#elif defined(SVQC)
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <common/teams.qh>
#include <server/autocvars.qh>
#include <server/constants.qh>
this.colormod = '1 0 0' + '0 1 0' * (2 * h - 0.5);
else
this.colormod = '1 1 1';
-
- CSQCMODEL_AUTOUPDATE(this);
}
void func_breakable_look_destroyed(entity this)
this.effects &= ~EF_NODRAW;
}
- CSQCMODEL_AUTOUPDATE(this);
-
this.solid = SOLID_NOT;
}
if(this.mdl_dead != "") // only do this if we use mdl_dead, to behave better with misc_follow
setorigin(this, this.dropped_origin);
- CSQCMODEL_AUTOUPDATE(this);
-
this.solid = SOLID_BSP;
}
stopsound (this, CH_TRIGGER_SINGLE);
}
+void func_breakable_think(entity this)
+{
+ this.nextthink = time;
+ CSQCMODEL_AUTOUPDATE(this);
+}
+
void func_breakable_destroy(entity this, entity actor, entity trigger);
void func_breakable_behave_restore(entity this)
{
if(this.spawnflags & 4)
this.use = func_breakable_destroy; // don't need to set it usually, as .use isn't reset
this.state = 0;
- this.nextthink = 0; // cancel auto respawn
+ //this.nextthink = 0; // cancel auto respawn
+ setthink(this, func_breakable_think);
+ this.nextthink = time + 0.1;
func_breakable_colormod(this);
if (this.noise1)
_sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
{
func_breakable_look_destroyed(this);
func_breakable_behave_destroyed(this);
-
- CSQCMODEL_AUTOUPDATE(this);
}
void func_breakable_restore(entity this, entity actor, entity trigger)
{
func_breakable_look_restore(this);
func_breakable_behave_restore(this);
-
- CSQCMODEL_AUTOUPDATE(this);
}
void func_breakable_restore_self(entity this)
if(this.respawntime)
{
+ CSQCMODEL_AUTOUPDATE(this);
setthink(this, func_breakable_restore_self);
this.nextthink = time + this.respawntime + crandom() * this.respawntimejitter;
}
// do not explode NOW but in the NEXT FRAME!
// because recursive calls to RadiusDamage are not allowed
this.nextthink = time;
+ CSQCMODEL_AUTOUPDATE(this);
setthink(this, func_breakable_destroy_self);
}
}
func_breakable_behave_destroyed(this);
else
func_breakable_behave_restore(this);
-
- CSQCMODEL_AUTOUPDATE(this);
}
// destructible walls that can be used to trigger target_objective_decrease
#include "train.qh"
.float train_wait_turning;
+.entity future_target;
void train_next(entity this);
#ifdef SVQC
void train_use(entity this, entity actor, entity trigger);
{
entity targ, cp;
vector ang;
- targ = find(NULL, targetname, this.target);
+ targ = this.future_target;
if((this.spawnflags & 1) && targ.curvetarget)
cp = find(NULL, targetname, targ.curvetarget);
else
#endif
#ifdef SVQC
- entity tg = find(NULL, targetname, this.target);
+ entity tg = this.future_target;
if(tg.spawnflags & 4)
{
this.use = train_use;
}
}
+entity train_next_find(entity this)
+{
+ if(this.target_random)
+ {
+ RandomSelection_Init();
+ for(entity t = NULL; (t = find(t, targetname, this.target));)
+ {
+ RandomSelection_AddEnt(t, 1, 0);
+ }
+ return RandomSelection_chosen_ent;
+ }
+ else
+ {
+ return find(NULL, targetname, this.target);
+ }
+}
+
void train_next(entity this)
{
- entity targ, cp = NULL;
+ entity targ = NULL, cp = NULL;
vector cp_org = '0 0 0';
- targ = find(NULL, targetname, this.target);
+ targ = this.future_target;
+
this.target = targ.target;
+ this.target_random = targ.target_random;
+ this.future_target = train_next_find(targ);
+
if (this.spawnflags & 1)
{
if(targ.curvetarget)
void func_train_find(entity this)
{
- entity targ;
- targ = find(NULL, targetname, this.target);
+ entity targ = train_next_find(this);
this.target = targ.target;
+ this.target_random = targ.target_random;
+ // save the future target for later
+ this.future_target = train_next_find(targ);
if (this.target == "")
objerror(this, "func_train_find: no next target");
SUB_SETORIGIN(this, targ.origin - this.view_ofs);
#elif defined(MENUQC)
#elif defined(SVQC)
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <server/constants.qh>
#include <server/defs.qh>
#endif
it.iscreature = true;
it.teleportable = TELEPORT_NORMAL;
it.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, it);
set_movetype(it, MOVETYPE_WALK);
it.solid = SOLID_SLIDEBOX;
it.takedamage = DAMAGE_AIM;
it.iscreature = true;
it.teleportable = TELEPORT_NORMAL;
it.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, it);
it.solid = SOLID_SLIDEBOX;
it.takedamage = DAMAGE_AIM;
if(it.move_movetype != MOVETYPE_WALK)
void vehicles_enter(entity pl, entity veh)
{
- // Remove this when bots know how to use vehicles
+ // Remove this when bots know how to use vehicles
if((IS_BOT_CLIENT(pl) && !autocvar_g_vehicles_allow_bots))
return;
this.iscreature = true;
this.teleportable = false; // no teleporting for vehicles, too buggy
this.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, this);
this.vehicleid = info.vehicleid;
this.PlayerPhysplug = info.PlayerPhysplug;
this.event_damage = func_null;
else
this.nextthink = time + game_starttime;
- if(!MUTATOR_CALLHOOK(VehicleInit, this))
+ if(MUTATOR_CALLHOOK(VehicleInit, this))
return false;
return true;
missile.damageforcescale = WEP_CVAR(arc, bolt_damageforcescale);
missile.event_damage = W_Arc_Bolt_Damage;
missile.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, missile);
settouch(missile, W_Arc_Bolt_Touch);
missile.use = W_Arc_Bolt_Explode_use;
missile.health = WEP_CVAR(devastator, health);
missile.event_damage = W_Devastator_Damage;
missile.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, missile);
set_movetype(missile, MOVETYPE_FLY);
PROJECTILE_MAKETRIGGER(missile);
newproj.event_damage = this.event_damage;
newproj.spawnshieldtime = this.spawnshieldtime;
newproj.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, newproj);
set_movetype(newproj, MOVETYPE_NONE); // lock the orb in place
newproj.projectiledeathtype = this.projectiledeathtype;
IL_PUSH(g_projectiles, proj);
IL_PUSH(g_bot_dodge, proj);
proj.damagedbycontents = (WEP_CVAR_SEC(electro, damagedbycontents));
+ if(proj.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, proj);
proj.bouncefactor = WEP_CVAR_SEC(electro, bouncefactor);
proj.bouncestop = WEP_CVAR_SEC(electro, bouncestop);
missile.damageforcescale = WEP_CVAR_PRI(hagar, damageforcescale);
missile.event_damage = W_Hagar_Damage;
missile.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, missile);
settouch(missile, W_Hagar_Touch);
missile.use = W_Hagar_Explode_use;
missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
missile.event_damage = W_Hagar_Damage;
missile.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, missile);
settouch(missile, W_Hagar_Touch2);
missile.cnt = 0;
missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
missile.event_damage = W_Hagar_Damage;
missile.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, missile);
settouch(missile, W_Hagar_Touch); // not bouncy
missile.use = W_Hagar_Explode2_use;
{
// loadable hagar secondary attack, must always run each frame
- if(time < game_starttime || PS(actor).m_switchweapon != WEP_HAGAR)
+ if(time < game_starttime)
return;
bool loaded = actor.hagar_load >= WEP_CVAR_SEC(hagar, load_max);
gren.damageforcescale = WEP_CVAR_SEC(hook, damageforcescale);
gren.event_damage = W_Hook_Damage;
gren.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, gren);
gren.missile_flags = MIF_SPLASH | MIF_ARC;
gren.velocity = '0 0 1' * WEP_CVAR_SEC(hook, speed);
newmine.event_damage = this.event_damage;
newmine.spawnshieldtime = this.spawnshieldtime;
newmine.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, newmine);
set_movetype(newmine, MOVETYPE_NONE); // lock the mine in place
newmine.projectiledeathtype = this.projectiledeathtype;
mine.health = WEP_CVAR(minelayer, health);
mine.event_damage = W_MineLayer_Damage;
mine.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, mine);
set_movetype(mine, MOVETYPE_TOSS);
PROJECTILE_MAKETRIGGER(mine);
gren.damageforcescale = WEP_CVAR_PRI(mortar, damageforcescale);
gren.event_damage = W_Mortar_Grenade_Damage;
gren.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, gren);
gren.missile_flags = MIF_SPLASH | MIF_ARC;
W_SetupProjVelocity_UP_PRI(gren, mortar);
gren.damageforcescale = WEP_CVAR_SEC(mortar, damageforcescale);
gren.event_damage = W_Mortar_Grenade_Damage;
gren.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, gren);
gren.missile_flags = MIF_SPLASH | MIF_ARC;
W_SetupProjVelocity_UP_SEC(gren, mortar);
missile.health = WEP_CVAR(seeker, missile_health);
missile.damageforcescale = WEP_CVAR(seeker, missile_damageforcescale);
missile.damagedbycontents = true;
+ IL_PUSH(g_damagedbycontents, missile);
//missile.think = W_Seeker_Missile_Animate; // csqc projectiles.
if(missile.enemy != NULL)
}
}
+void tuba_instrument_send(entity this, int instr);
METHOD(Tuba, wr_setup, void(Tuba this, entity actor))
{
actor.ammo_field = ammo_none;
actor.tuba_instrument = 0;
+ tuba_instrument_send(actor, actor.tuba_instrument);
}
#endif
string s = (i == 0) ? "tuba" :
(i == 1) ? "akordeon" :
"kleinbottle" ;
+ viewmodel.tuba_instrument = i;
CL_WeaponEntity_SetModel(viewmodel, s, true);
}
#endif
const int TUBA_MAX = 27;
const int TUBA_INSTRUMENTS = 3;
-entityclass(Tuba);
-class(Tuba) .int note;
-class(Tuba) .bool tuba_attenuate;
-class(Tuba) .float tuba_volume;
-class(Tuba) .float tuba_volume_initial;
-class(Tuba) .int tuba_instrument;
-
int Tuba_PitchStep;
void tubasound(entity e, bool restart)
#pragma once
+
+#ifdef CSQC
+entityclass(Tuba);
+class(Tuba) .int note;
+class(Tuba) .bool tuba_attenuate;
+class(Tuba) .float tuba_volume;
+class(Tuba) .float tuba_volume_initial;
+class(Tuba) .int tuba_instrument;
+#endif
#endif
#undef ENGINE_EVENT
+#if XONOTIC
#ifdef GAMEQC
#include <ecs/_mod.qh>
#endif
+#endif
#include <client/defs.qh>
#include <client/main.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/physics/player.qh>
#include <common/stats.qh>
#include <common/triggers/trigger/viewloc.qh>
#include "common.qh"
#include <common/animdecide.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/util.qh>
#include <server/constants.qh>
#include <server/defs.qh>
#include "i18n.qh"
#include "vector.qh"
- #include <client/defs.qh>
+ float vid_conwidth;
void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
{
// generated file; do not modify
-#include <lib/matrix/command.qc>
+#if XONOTIC
+ #include <lib/matrix/command.qc>
+#endif
#include <lib/matrix/matrix.qc>
// generated file; do not modify
-#include <lib/matrix/command.qh>
+#if XONOTIC
+ #include <lib/matrix/command.qh>
+#endif
#include <lib/matrix/matrix.qh>
#define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
#ifdef CSQC
+ float servertime;
entity ReadCSQCEntity()
{
int f = ReadShort();
#define ReadInt48_t() vec3(ReadInt24_t(), ReadInt24_t(), 0)
#define ReadInt72_t() vec3(ReadInt24_t(), ReadInt24_t(), ReadInt24_t())
- int _ReadSByte;
+ noref int _ReadSByte;
#define ReadSByte() (_ReadSByte = ReadByte(), (_ReadSByte & BIT(7) ? -128 : 0) + (_ReadSByte & BITS(7)))
#define ReadFloat() ReadCoord()
#define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat())
}
this.classname = "trigger_warpzone";
+ if(isnew)
+ IL_PUSH(g_warpzones, this);
+
int f = ReadByte();
this.warpzone_isboxy = (f & 1);
if(f & 4)
entity WarpZone_Find(vector mi, vector ma)
{
// if we are near any warpzone planes - MOVE AWAY (work around nearclip)
- entity e;
if(!warpzone_warpzones_exist)
return NULL;
- for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
- if(WarpZoneLib_BoxTouchesBrush(mi, ma, e, NULL))
- return e;
+ IL_EACH(g_warpzones, WarpZoneLib_BoxTouchesBrush(mi, ma, it, NULL),
+ {
+ return it;
+ });
return NULL;
}
void WarpZone_MakeAllSolid()
{
- entity e;
if(!warpzone_warpzones_exist)
return;
- for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
- e.solid = SOLID_BSP;
+ IL_EACH(g_warpzones, true,
+ {
+ it.solid = SOLID_BSP;
+ });
}
void WarpZone_MakeAllOther()
{
- entity e;
if(!warpzone_warpzones_exist)
return;
- for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
- e.solid = SOLID_TRIGGER;
+ IL_EACH(g_warpzones, true,
+ {
+ it.solid = SOLID_TRIGGER;
+ });
}
void WarpZone_Trace_InitTransform()
// uncomment this if your mod uses the roll angle in fixangle
// #define KEEP_ROLL
+IntrusiveList g_warpzones;
+STATIC_INIT(g_warpzones) { g_warpzones = IL_NEW(); }
+
float warpzone_warpzones_exist;
float warpzone_cameras_exist;
#elif defined(MENUQC)
#elif defined(SVQC)
#include <common/constants.qh>
+ #include <common/net_linked.qh>
#include <common/triggers/subs.qh>
#include <common/util.qh>
- #include <server/command/_mod.qh>
#include <server/constants.qh>
#include <server/defs.qh>
#endif
this.enemy = NULL;
}
-entity warpzone_first; .entity warpzone_next;
void WarpZone_InitStep_FindTarget(entity this)
{
float i;
BITSET_ASSIGN(this.effects, EF_NODEPTHTEST);
this.warpzone_next = warpzone_first;
warpzone_first = this;
+
+ IL_PUSH(g_warpzones, this);
}
spawnfunc(func_camera)
{
WarpZone_PostInitialize_Callback();
}
- FOREACH_ENTITY_FLOAT(pure_data, false,
+ if(warpzone_warpzones_exist)
{
- if(warpzone_warpzones_exist)
+ IL_EACH(g_projectiles, true,
+ {
WarpZone_StoreProjectileData(it);
+ });
+ }
+
+
+ FOREACH_CLIENT(true,
+ {
+ if(warpzone_warpzones_exist)
+ WarpZone_StoreProjectileData(it); // TODO: not actually needed
if(IS_OBSERVER(it) || it.solid == SOLID_NOT)
if(IS_CLIENT(it)) // we don't care about it being a bot
#pragma once
#ifdef SVQC
+entity warpzone_first; .entity warpzone_next;
+
void WarpZone_StartFrame();
float WarpZone_Projectile_Touch(entity this, entity toucher);
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayermodels", _("Force player models to mine")));
me.TR(me);
- me.TD(me, 1, 3, e = makeXonoticCheckBox(0, "cl_forceplayercolors", _("Force player colors to mine")));
+ me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Force player colors to mine")));
+ me.TD(me, 1, 2, e = makeXonoticTextSlider("cl_forceplayercolors"));
+ e.addValue(e, _("Never"), "0");
+ e.addValue(e, _("In non teamplay modes only"), "1");
+ e.addValue(e, _("Always"), "2");
+ e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Body fading:")));
me.TD(me, 1, 2, e = makeXonoticSlider(0, 2, 0.2, "cl_deathglow"));
#include "rootdialog.qh"
CLASS(XonoticUid2NameDialog, XonoticRootDialog)
METHOD(XonoticUid2NameDialog, fill, void(entity));
- ATTRIB(XonoticUid2NameDialog, title, string);
+ ATTRIB(XonoticUid2NameDialog, title, string, "");
ATTRIB(XonoticUid2NameDialog, color, vector, SKINCOLOR_DIALOG_TEAMSELECT);
ATTRIB(XonoticUid2NameDialog, intendedWidth, float, 0.5);
ATTRIB(XonoticUid2NameDialog, rows, float, 4);
SLIST_CATEGORY(CAT_SERVERS, "CAT_NORMAL", "CAT_SERVERS", CTX(_("SLCAT^Servers"))) \
SLIST_CATEGORY(CAT_XPM, "CAT_NORMAL", "CAT_SERVERS", CTX(_("SLCAT^Competitive Mode"))) \
SLIST_CATEGORY(CAT_MODIFIED, "", "CAT_SERVERS", CTX(_("SLCAT^Modified Servers"))) \
- SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", CTX(_("SLCAT^Overkill Mode"))) \
- SLIST_CATEGORY(CAT_INSTAGIB, "", "CAT_SERVERS", CTX(_("SLCAT^InstaGib Mode"))) \
+ SLIST_CATEGORY(CAT_OVERKILL, "", "CAT_SERVERS", CTX(_("SLCAT^Overkill"))) \
+ SLIST_CATEGORY(CAT_INSTAGIB, "", "CAT_SERVERS", CTX(_("SLCAT^InstaGib"))) \
SLIST_CATEGORY(CAT_DEFRAG, "", "CAT_SERVERS", CTX(_("SLCAT^Defrag Mode")))
#define SLIST_CATEGORY_AUTOCVAR(name) autocvar_menu_slist_categories_##name##_override
#define FOREACH_CLIENT(cond, body) FOREACH_CLIENTSLOT(IS_CLIENT(it) && (cond), body)
+// using the "inside out" version of knuth-fisher-yates shuffle
+// https://en.wikipedia.org/wiki/Fisher–Yates_shuffle
+entity _FCR_clients[255];
+bool _FCR_entered = false;
+#define FOREACH_CLIENT_RANDOM(cond, body) \
+ MACRO_BEGIN { \
+ if (_FCR_entered) LOG_FATAL("FOREACH_CLIENT_RANDOM must not be nested"); \
+ _FCR_entered = true; \
+ int _cnt = 0; \
+ FOREACH_CLIENT(cond, LAMBDA( \
+ int _j = floor(random() * (_cnt + 1)); \
+ if (_j == _cnt) \
+ { \
+ _FCR_clients[_cnt] = it; \
+ } \
+ else \
+ { \
+ _FCR_clients[_cnt] = _FCR_clients[_j]; \
+ _FCR_clients[_j] = it; \
+ } \
+ _cnt++; \
+ )); \
+ for (int _i = 0; _i < _cnt; ++_i) \
+ { \
+ const noref int i = _i; \
+ ITER_CONST noref entity it = _FCR_clients[i]; \
+ if (cond) { LAMBDA(body) } \
+ } \
+ _FCR_entered = false; \
+ } MACRO_END
+
// NOTE: FOR_EACH_MONSTER deprecated! Use the following instead: IL_EACH(g_monsters, true, { code; });
#include <common/effects/all.qh>
#include <common/physics/player.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/mapinfo.qh>
#include <common/teams.qh>
#include <common/util.qh>
#include "../waypoints.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/physics/player.qh>
#include <common/state.qh>
#include <common/items/_mod.qh>
#include <common/items/_mod.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/triggers/trigger/jumppads.qh>
.float speed;
#include "../../antilag.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <lib/warpzone/common.qh>
#include <lib/warpzone/util_server.qh>
#include "weapons/weaponsystem.qh"
#include "../common/net_notice.qh"
+#include "../common/net_linked.qh"
#include "../common/physics/player.qh"
#include "../common/items/_mod.qh"
TRANSMUTE(Observer, this);
this.iscreature = false;
this.teleportable = TELEPORT_SIMPLE;
+ if(this.damagedbycontents)
+ IL_REMOVE(g_damagedbycontents, this);
this.damagedbycontents = false;
this.health = FRAGS_SPECTATOR;
SetSpectatee_status(this, etof(this));
this.wasplayer = true;
this.iscreature = true;
this.teleportable = TELEPORT_NORMAL;
+ if(!this.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, this);
this.damagedbycontents = true;
set_movetype(this, MOVETYPE_WALK);
this.solid = SOLID_SLIDEBOX;
this.playerid = 0;
ReadyCount();
if (vote_called && IS_REAL_CLIENT(this)) VoteCount(false);
+
+ ONREMOVE(this);
}
void ChatBubbleThink(entity this)
#include "../race.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/mapinfo.qh>
#include <common/util.qh>
#include "../mutators/_mod.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/mapinfo.qh>
#include <common/notifications/all.qh>
#include <common/teams.qh>
#include "../mutators/_mod.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/mapinfo.qh>
#include <common/notifications/all.qh>
#include <common/playerstats.qh>
IntrusiveList g_bot_dodge;
STATIC_INIT(g_bot_dodge) { g_bot_dodge = IL_NEW(); }
+
+IntrusiveList g_damagedbycontents;
+STATIC_INIT(g_damagedbycontents) { g_damagedbycontents = IL_NEW(); }
#include "../common/vehicles/all.qh"
#include "../common/constants.qh"
#include "../common/util.qh"
+#include <common/net_linked.qh>
#include <common/weapons/_all.qh>
#include "../lib/warpzone/common.qh"
#include "../lib/warpzone/server.qh"
missile.takedamage = DAMAGE_AIM;
missile.damageforcescale = 0;
missile.damagedbycontents = (autocvar_g_balance_grapplehook_damagedbycontents);
+ if(missile.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, missile);
missile.hook_start = missile.hook_end = missile.origin;
#include "g_models.qh"
#include "g_subs.qh"
+#include <common/net_linked.qh>
#include "../common/triggers/subs.qh"
#include "../common/triggers/triggers.qh"
#include "teamplay.qh"
#include "weapons/weaponstats.qh"
#include "../common/constants.qh"
+#include <common/net_linked.qh>
#include "../common/deathtypes/all.qh"
#include "../common/mapinfo.qh"
#include "../common/monsters/_mod.qh"
#include "command/cmd.qh"
#include "command/getreplies.qh"
#include "../common/constants.qh"
+#include <common/net_linked.qh>
#include "../common/mapinfo.qh"
#include "../common/playerstats.qh"
#include "../common/util.qh"
#include "weapons/selection.qh"
#include "../common/command/_mod.qh"
#include "../common/constants.qh"
+#include <common/net_linked.qh>
#include "../common/deathtypes/all.qh"
#include "../common/mapinfo.qh"
#include "../common/notifications/all.qh"
/**
* called when a vehicle initializes
- * return false to remove the vehicle
+ * return true to remove the vehicle
*/
#define EV_VehicleInit(i, o) \
/** vehicle */ i(entity, MUTATOR_ARGV_0_entity) \
// trigger new round
// reset objectives, toggle spawnpoints, reset triggers, ...
-void vehicles_clearreturn(entity veh);
-void vehicles_spawn(entity this);
void assault_new_round(entity this)
{
//bprint("ASSAULT: new round\n");
{
entity veh = M_ARGV(0, entity);
- if(veh.active != ACTIVE_NOT)
- veh.nextthink = time + 0.5;
- return true;
+ veh.nextthink = time + 0.5;
}
MUTATOR_HOOKFUNCTION(as, HavocBot_ChooseRole)
flag.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP;
flag.damagedbytriggers = autocvar_g_ctf_flag_return_when_unreachable;
flag.damagedbycontents = autocvar_g_ctf_flag_return_when_unreachable;
+ if(flag.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, flag);
flag.velocity = '0 0 0';
flag.mangle = flag.angles;
flag.reset = ctf_Reset;
clone.iscreature = this.iscreature;
clone.teleportable = this.teleportable;
clone.damagedbycontents = this.damagedbycontents;
+ if(clone.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, clone);
clone.angles = this.angles;
clone.v_angle = this.v_angle;
clone.avelocity = this.avelocity;
this.alpha = -1;
this.solid = SOLID_NOT; // restore later
this.takedamage = DAMAGE_NO; // restore later
+ if(this.damagedbycontents)
+ IL_REMOVE(g_damagedbycontents, this);
this.damagedbycontents = false;
}
}
#if XONOTIC
#include <server/_all.inc>
-#endif
#include <ecs/_mod.inc>
+#endif
#ifdef BUILD_MOD
#include <mod/server/progs.inc>
#include "../common/deathtypes/all.qh"
#include "../common/notifications/all.qh"
#include "../common/mapinfo.qh"
+#include <common/net_linked.qh>
#include "../common/triggers/subs.qh"
#include "../lib/warpzone/util_server.qh"
#include "../lib/warpzone/common.qh"
#include "command/common.qh"
#include "mutators/_mod.qh"
+#include <common/net_linked.qh>
#include "../common/playerstats.qh"
#include "../common/teams.qh"
#include "g_world.qh"
#include "race.qh"
#include "../common/constants.qh"
+#include <common/net_linked.qh>
#include "../common/teams.qh"
#include "../common/triggers/subs.qh"
#include "../common/util.qh"
void CreatureFrame_All()
{
- FOREACH_ENTITY_FLOAT(damagedbycontents, true, {
+ IL_EACH(g_damagedbycontents, it.damagedbycontents,
+ {
if (it.move_movetype == MOVETYPE_NOCLIP) continue;
CreatureFrame_Liquids(it);
CreatureFrame_FallDamage(it);
void WarpZone_PostInitialize_Callback()
{
// create waypoint links for warpzones
- entity e;
- for(e = NULL; (e = find(e, classname, "trigger_warpzone")); )
+ //for(entity e = warpzone_first; e; e = e.warpzone_next)
+ for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); )
{
vector src, dst;
src = (e.absmin + e.absmax) * 0.5;
#include "../mutators/_mod.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/teams.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
#include <common/t_items.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/deathtypes/all.qh>
#include <common/notifications/all.qh>
#include <common/util.qh>
#include "../command/common.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/weapons/_all.qh>
.float csqcprojectile_type;
#include "weaponsystem.qh"
#include <common/t_items.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/util.qh>
#include <common/items/item.qh>
#include <common/weapons/_all.qh>
#include "../antilag.qh"
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
#include <common/t_items.qh>
#include <common/animdecide.qh>
#include <common/constants.qh>
+#include <common/net_linked.qh>
#include <common/monsters/_mod.qh>
#include <common/notifications/all.qh>
#include <common/util.qh>