- wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
- wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
- make
- - EXPECT=6e591fe90a6b90e62fdfd531636dd6eb
+ - EXPECT=ce60a57e67f899e8b748c1b644082c74
- HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
| tee /dev/stderr
| grep '^:'
.bool ready;
.bool eliminated;
-.void(entity) draw;
IntrusiveList g_drawables;
-STATIC_INIT(g_drawables) { g_drawables = IL_NEW(); }
-.void(entity) draw2d;
IntrusiveList g_drawables_2d;
-STATIC_INIT(g_drawables_2d) { g_drawables_2d = IL_NEW(); }
+IntrusiveList g_radarlinks;
+IntrusiveList g_radaricons;
+STATIC_INIT(main)
+{
+ g_drawables = IL_NEW();
+ g_drawables_2d = IL_NEW();
+ g_radarlinks = IL_NEW();
+ g_radaricons = IL_NEW();
+}
+
+.void(entity) draw;
+.void(entity) draw2d;
.void(entity) entremove;
float drawframetime;
vector view_origin, view_forward, view_right, view_up;
-IntrusiveList g_radarlinks;
-STATIC_INIT(g_radarlinks) { g_radarlinks = IL_NEW(); }
-IntrusiveList g_radaricons;
-STATIC_INIT(g_radaricons) { g_radaricons = IL_NEW(); }
bool button_zoom;
bool spectatorbutton_zoom;
showfps_prevfps_time = currentTime; // we must initialize it to avoid an instant low frame sending
}
-STATIC_INIT(Porto)
-{
- entity e = new_pure(porto);
- e.draw = Porto_Draw;
- IL_PUSH(g_drawables, e);
- e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
-}
-
-const int polyline_length = 16;
-.vector polyline[polyline_length];
-void Porto_Draw(entity this)
-{
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- entity wepent = viewmodels[slot];
-
- if (wepent.activeweapon != WEP_PORTO) continue;
- if (spectatee_status) continue;
- if (WEP_CVAR(porto, secondary)) continue;
- if (intermission == 1) continue;
- if (intermission == 2) continue;
- if (STAT(HEALTH) <= 0) continue;
-
- vector pos = view_origin;
- vector dir = view_forward;
- makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles));
- pos += v_right * -wepent.movedir.y
- + v_up * wepent.movedir.z;
-
- if (wepent.angles_held_status)
- {
- makevectors(wepent.angles_held);
- dir = v_forward;
- }
-
- wepent.polyline[0] = pos;
-
- int portal_number = 0, portal1_idx = 1, portal_max = 2;
- int n = 1 + 2; // 2 lines == 3 points
- for (int idx = 0; idx < n && idx < polyline_length - 1; )
- {
- traceline(pos, pos + 65536 * dir, true, this);
- dir = reflect(dir, trace_plane_normal);
- pos = trace_endpos;
- wepent.polyline[++idx] = pos;
- if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
- {
- n += 1;
- continue;
- }
- if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
- {
- n = max(2, idx);
- break;
- }
- // check size
- {
- vector ang = vectoangles2(trace_plane_normal, dir);
- ang.x = -ang.x;
- makevectors(ang);
- if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
- {
- n = max(2, idx);
- break;
- }
- }
- portal_number += 1;
- if (portal_number >= portal_max) break;
- if (portal_number == 1) portal1_idx = idx;
- }
- for (int idx = 0; idx < n - 1; ++idx)
- {
- vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1];
- if (idx == 0) p -= view_up * 16; // line from player
- vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
- Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
- }
- }
-}
-
float drawtime;
float avgspeed;
vector GetCurrentFov(float fov)
float TrueAimCheck(entity wepent)
{
+ if(wepent.activeweapon.spawnflags & WEP_FLAG_NOTRUEAIM)
+ return SHOTTYPE_HITWORLD;
+
float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
vector vecs, trueaimpoint, w_shotorg;
vector mi, ma, dv;
switch(wepent.activeweapon) // WEAPONTODO
{
- case WEP_TUBA: // no aim
- case WEP_PORTO: // shoots from eye
- case WEP_NEXBALL: // shoots from eye
- case WEP_HOOK: // no trueaim
- case WEP_MORTAR: // toss curve
- return SHOTTYPE_HITWORLD;
case WEP_VORTEX:
case WEP_OVERKILL_NEX:
case WEP_VAPORIZER:
void calc_followmodel_ofs(entity view);
-void Porto_Draw(entity this);
-
void CSQC_Demo_Camera();
void TrueAim_Init();
const int HITTYPE_SPLASH = BITS(1) << 9;
const int HITTYPE_BOUNCE = BITS(1) << 10;
const int HITTYPE_ARMORPIERCE = BITS(1) << 11;
-// unused yet
-const int HITTYPE_RESERVED = BITS(1) << 12;
-const int DEATH_HITTYPEMASK = HITTYPE_SECONDARY | HITTYPE_SPLASH | HITTYPE_BOUNCE | HITTYPE_ARMORPIERCE | HITTYPE_RESERVED;
+const int HITTYPE_SOUND = BITS(1) << 12;
+const int DEATH_HITTYPEMASK = HITTYPE_SECONDARY | HITTYPE_SPLASH | HITTYPE_BOUNCE | HITTYPE_ARMORPIERCE | HITTYPE_SOUND;
// normal deaths begin
const int DT_FIRST = BIT(13);
NET_HANDLE(ENT_CLIENT_DAMAGEINFO, bool isNew)
{
- const float ATTEN_LOW = 0.2;
float thedamage, rad, edge, thisdmg;
bool hitplayer = false;
int species, forcemul;
w_random = prandom();
traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, NULL);
- if(trace_fraction < 1 && hitwep != WEP_VORTEX && hitwep != WEP_VAPORIZER)
+ if(trace_fraction < 1 && !(hitwep.spawnflags & WEP_TYPE_HITSCAN))
w_backoff = trace_plane_normal;
else
w_backoff = -1 * normalize(force);
ATTRIB(Flag, m_mins, vector, (PL_MIN_CONST + '0 0 -13') * 1.4); // scaling be damned
ATTRIB(Flag, m_maxs, vector, (PL_MAX_CONST + '0 0 -13') * 1.4);
ENDCLASS(Flag)
-Flag CTF_FLAG; STATIC_INIT(Flag) { CTF_FLAG = NEW(Flag); }
+Flag CTF_FLAG;
+STATIC_INIT(Flag) { CTF_FLAG = NEW(Flag); }
void ctf_FlagTouch(entity this, entity toucher) { ITEM_HANDLE(Pickup, CTF_FLAG, this, toucher); }
// flag constants // for most of these, there is just one question to be asked: WHYYYYY?
#pragma once
CLASS(BallStealer, PortoLaunch)
-/* flags */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_NOTRUEAIM);
/* impulse */ ATTRIB(BallStealer, impulse, int, 0);
/* refname */ ATTRIB(BallStealer, netname, string, "ballstealer");
/* wepname */ ATTRIB(BallStealer, m_name, string, _("Ball Stealer"));
{
case "activate":
{
- minigame.message = bd_turn_to_string(minigame.minigame_flags);
+ strcpy(minigame.message, bd_turn_to_string(minigame.minigame_flags));
bd_set_curr_pos("");
bd_curr_tile = BD_TILE_BRICK1;
return false;
}
+ case "deactivate":
+ {
+ strfree(minigame.message);
+ return false;
+ }
case "key_pressed":
{
if(minigame.minigame_flags & BD_TURN_MOVE)
{
if ( sf & MINIG_SF_UPDATE )
{
- sent.message = bd_turn_to_string(sent.minigame_flags);
+ strcpy(sent.message, bd_turn_to_string(sent.minigame_flags));
//if ( sent.minigame_flags & minigame_self.team )
//minigame_prompt();
}
case "activate":
{
c4_set_curr_pos("");
- minigame.message = c4_turn_to_string(minigame.minigame_flags);
+ strcpy(minigame.message, c4_turn_to_string(minigame.minigame_flags));
+ return false;
+ }
+ case "deactivate":
+ {
+ strfree(minigame.message);
return false;
}
case "key_pressed":
{
if ( sf & MINIG_SF_UPDATE )
{
- sent.message = c4_turn_to_string(sent.minigame_flags);
+ strcpy(sent.message, c4_turn_to_string(sent.minigame_flags));
if ( sent.minigame_flags & minigame_self.team )
minigame_prompt();
}
{
nmm_fromtile = NULL;
nmm_init_tiles(minigame);
- minigame.message = nmm_turn_to_string(minigame.minigame_flags);
+ strcpy(minigame.message, nmm_turn_to_string(minigame.minigame_flags));
}
else if ( event == "deactivate" )
{
nmm_fromtile = NULL;
nmm_kill_tiles(minigame);
+ strfree(minigame.message);
}
else if ( event == "key_pressed" && (minigame.minigame_flags&NMM_TURN_TEAM) == minigame_self.team )
{
}
else if ( sent.classname == "minigame" && ( ...(1,int) & MINIG_SF_UPDATE ) )
{
- sent.message = nmm_turn_to_string(sent.minigame_flags);
+ strcpy(sent.message, nmm_turn_to_string(sent.minigame_flags));
if ( sent.minigame_flags & minigame_self.team )
minigame_prompt();
}
{
case "activate":
return false;
+ case "deactivate":
+ {
+ strfree(minigame.message);
+ return false;
+ }
case "key_pressed":
switch ( ...(0,int) )
{
{
if ( sf & MINIG_SF_UPDATE )
{
- sent.message = pong_message(sent.minigame_flags);
+ strcpy(sent.message, pong_message(sent.minigame_flags));
}
}
return false;
if ( turnflags & PP_TURN_WIN )
{
+ // translator-friendly messages composed of 2 existing messages
if ( (turnflags&PP_TURN_TEAM) != minigame_self.team )
- //return _("You lost the game!\nSelect \"^1Next Match^7\" on the menu for a rematch!");
- return _("You lost the game!");
- //return _("You win!\nSelect \"^1Next Match^7\" on the menu to start a new match!");
- return _("You win!");
+ return strcat(_("You lost the game!"), "\n", _("Select \"^1Next Match^7\" on the menu for a rematch!"));
+ return strcat(_("You win!"), "\n", _("Select \"^1Next Match^7\" on the menu to start a new match!"));
}
if ( turnflags & PP_TURN_NEXT )
case "activate":
{
pp_set_curr_pos("");
- minigame.message = pp_turn_to_string(minigame.minigame_flags);
+ strcpy(minigame.message, pp_turn_to_string(minigame.minigame_flags));
+ return false;
+ }
+ case "deactivate":
+ {
+ strfree(minigame.message);
return false;
}
case "key_pressed":
{
if ( sf & MINIG_SF_UPDATE )
{
- sent.message = pp_turn_to_string(sent.minigame_flags);
+ strcpy(sent.message, pp_turn_to_string(sent.minigame_flags));
if ( sent.minigame_flags & minigame_self.team )
minigame_prompt();
sent.pp_team1_score = ReadByte();
{
ps_set_curr_pos("");
ps_curr_piece = NULL;
- minigame.message = ps_turn_to_string(minigame.minigame_flags);
+ strcpy(minigame.message, ps_turn_to_string(minigame.minigame_flags));
+ return false;
+ }
+ case "deactivate":
+ {
+ strfree(minigame.message);
return false;
}
case "key_pressed":
{
if ( sf & MINIG_SF_UPDATE )
{
- sent.message = ps_turn_to_string(sent.minigame_flags);
+ strcpy(sent.message, ps_turn_to_string(sent.minigame_flags));
//if ( sent.minigame_flags & minigame_self.team )
//minigame_prompt();
}
if ( turnflags & TTT_TURN_WIN )
{
+ // translator-friendly messages composed of 2 existing messages
+ // TODO: proper "you win" banner instead of hijacking the help message
if ( (turnflags&TTT_TURN_TEAM) != minigame_self.team )
- //return _("You lost the game!\nSelect \"^1Next Match^7\" on the menu for a rematch!"); // TODO: proper "you win" banner instead of hijacking the help message
- return _("You lost the game!"); // TODO: proper "you win" banner instead of hijacking the help message
- //return _("You win!\nSelect \"^1Next Match^7\" on the menu to start a new match!");
- return _("You win!");
+ strcat(_("You lost the game!"), "\n", _("Select \"^1Next Match^7\" on the menu for a rematch!"));
+ return strcat(_("You win!"), "\n", _("Select \"^1Next Match^7\" on the menu to start a new match!"));
}
if ( turnflags & TTT_TURN_NEXT )
else
ttt_move(minigame,aiplayer,pos);
}
- minigame.message = ttt_turn_to_string(minigame.minigame_flags);
+ strcpy(minigame.message, ttt_turn_to_string(minigame.minigame_flags));
}
// Make the correct move
case "activate":
{
ttt_set_curr_pos("");
- minigame.message = ttt_turn_to_string(minigame.minigame_flags);
+ strcpy(minigame.message, ttt_turn_to_string(minigame.minigame_flags));
+ return false;
+ }
+ case "deactivate":
+ {
+ strfree(minigame.message);
return false;
}
case "key_pressed":
{
if ( sf & MINIG_SF_UPDATE )
{
- sent.message = ttt_turn_to_string(sent.minigame_flags);
+ strcpy(sent.message, ttt_turn_to_string(sent.minigame_flags));
if ( sent.minigame_flags & minigame_self.team )
minigame_prompt();
}
player.OffhandMageTeleport_key_pressed = key_pressed;
}
ENDCLASS(OffhandMageTeleport)
-OffhandMageTeleport OFFHAND_MAGE_TELEPORT; STATIC_INIT(OFFHAND_MAGE_TELEPORT) { OFFHAND_MAGE_TELEPORT = NEW(OffhandMageTeleport); }
+OffhandMageTeleport OFFHAND_MAGE_TELEPORT;
+STATIC_INIT(OFFHAND_MAGE_TELEPORT) { OFFHAND_MAGE_TELEPORT = NEW(OffhandMageTeleport); }
float autocvar_g_monster_mage_health;
float autocvar_g_monster_mage_damageforcescale = 0.5;
float autocvar_g_instagib_speed_highspeed;
IntrusiveList g_instagib_items;
-STATIC_INIT()
+STATIC_INIT(instagib)
{
g_instagib_items = IL_NEW();
IL_PUSH(g_instagib_items, ITEM_VaporizerCells);
#endif
#ifdef CSQC
-void Item_ItemsTime_Init()
-{
- FOREACH(Items, true, {
- ItemsTime_time[it.m_id] = -1;
- });
- ItemsTime_time[Items_MAX] = -1;
-}
STATIC_INIT(ItemsTime_Init) {
- Item_ItemsTime_Init();
+ FOREACH(Items, true, {
+ ItemsTime_time[it.m_id] = -1;
+ });
+ ItemsTime_time[Items_MAX] = -1;
}
int autocvar_hud_panel_itemstime = 2;
// reserve one more spot for superweapons time
float it_times[Items_MAX + 1];
-void Item_ItemsTime_Init()
-{
- FOREACH(Items, Item_ItemsTime_Allow(it), {
- it_times[it.m_id] = -1;
- });
- it_times[Items_MAX] = -1;
-}
-
STATIC_INIT(ItemsTime_Init) {
- // items time
- Item_ItemsTime_Init();
+ FOREACH(Items, Item_ItemsTime_Allow(it), {
+ it_times[it.m_id] = -1;
+ });
+ it_times[Items_MAX] = -1;
}
void Item_ItemsTime_ResetTimes()
damage = this.max_health * 0.1;
else if(DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) // WEAPONTODO
{
- if(deathtype & HITTYPE_SECONDARY)
- {
- damage = this.max_health * 0.1;
- force *= 10;
- }
- else
+ if(!(deathtype & HITTYPE_SECONDARY))
damage = this.max_health * 1.15;
}
+ // melee slaps
+ entity death_weapon = DEATH_WEAPONOF(deathtype);
+ if(((deathtype & HITTYPE_SECONDARY) ? (death_weapon.spawnflags & WEP_TYPE_MELEE_SEC) : (death_weapon.spawnflags & WEP_TYPE_MELEE_PRI)))
+ {
+ damage = this.max_health * 0.1;
+ force *= 10;
+ }
+
this.velocity += force;
UpdateCSQCProjectile(this);
}
}
ENDCLASS(NadeOffhand)
-NadeOffhand OFFHAND_NADE; STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
+NadeOffhand OFFHAND_NADE;
+STATIC_INIT(OFFHAND_NADE) { OFFHAND_NADE = NEW(NadeOffhand); }
MUTATOR_HOOKFUNCTION(nades, ForbidThrowCurrentWeapon, CBC_ORDER_LAST)
{
if(IS_PLAYER(frag_attacker))
{
- float killcount_bonus = ((CS(frag_attacker).killcount >= 1) ? bound(0, autocvar_g_nades_bonus_score_minor * CS(frag_attacker).killcount, autocvar_g_nades_bonus_score_medium) : autocvar_g_nades_bonus_score_minor);
+ float killcount_bonus = ((CS(frag_attacker).killcount >= 1) ? bound(0, autocvar_g_nades_bonus_score_minor * CS(frag_attacker).killcount, autocvar_g_nades_bonus_score_medium)
+ : autocvar_g_nades_bonus_score_minor);
if (SAME_TEAM(frag_attacker, frag_target) || frag_attacker == frag_target)
nades_RemoveBonus(frag_attacker);
.Weapon ok_lastwep[MAX_WEAPONSLOTS];
IntrusiveList g_overkill_items;
-STATIC_INIT()
+STATIC_INIT(overkill)
{
g_overkill_items = IL_NEW();
IL_PUSH(g_overkill_items, ITEM_HealthMega);
const float ATTEN_NONE = 0;
const float ATTEN_MIN = 0.015625;
+const float ATTEN_LOW = 0.2;
const float ATTEN_NORM = 0.5;
const float ATTEN_LARGE = 1;
const float ATTEN_IDLE = 2;
const int WEP_FLAG_NODUAL = BIT(12); // weapon doesn't work well with dual wielding (fireball etc just explode on fire), doesn't currently prevent anything
const int WEP_FLAG_PENETRATEWALLS = BIT(13); // weapon has high calibur bullets that can penetrate thick walls (WEAPONTODO)
const int WEP_FLAG_BLEED = BIT(14); // weapon pierces and causes bleeding (used for damage effects)
+const int WEP_FLAG_NOTRUEAIM = BIT(15); // weapon doesn't aim directly at targets
// variables:
string weaponorder_byid;
CLASS(OffhandBlaster, OffhandWeapon)
ENDCLASS(OffhandBlaster)
-OffhandBlaster OFFHAND_BLASTER; STATIC_INIT(OFFHAND_BLASTER) { OFFHAND_BLASTER = NEW(OffhandBlaster); }
+OffhandBlaster OFFHAND_BLASTER;
+STATIC_INIT(OFFHAND_BLASTER) { OFFHAND_BLASTER = NEW(OffhandBlaster); }
#ifdef SVQC
.float blaster_damage;
/* spawnfunc */ ATTRIB(Hook, m_canonical_spawnfunc, string, "weapon_hook");
/* ammotype */ ATTRIB(Hook, ammo_type, int, RES_FUEL);
/* impulse */ ATTRIB(Hook, impulse, int, 0);
-/* flags */ ATTRIB(Hook, spawnflags, int, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* flags */ ATTRIB(Hook, spawnflags, int, WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH | WEP_FLAG_NOTRUEAIM);
/* rating */ ATTRIB(Hook, bot_pickupbasevalue, float, 0);
/* color */ ATTRIB(Hook, wpcolor, vector, '0 0.5 0');
/* modelname */ ATTRIB(Hook, mdl, string, "hookgun");
}
#endif
ENDCLASS(OffhandHook)
-OffhandHook OFFHAND_HOOK; STATIC_INIT(OFFHAND_HOOK) { OFFHAND_HOOK = NEW(OffhandHook); }
+OffhandHook OFFHAND_HOOK;
+STATIC_INIT(OFFHAND_HOOK) { OFFHAND_HOOK = NEW(OffhandHook); }
#ifdef SVQC
/* spawnfunc */ ATTRIB(Mortar, m_canonical_spawnfunc, string, "weapon_mortar");
/* ammotype */ ATTRIB(Mortar, ammo_type, int, RES_ROCKETS);
/* impulse */ ATTRIB(Mortar, impulse, int, 4);
-/* flags */ ATTRIB(Mortar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
+/* flags */ ATTRIB(Mortar, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH | WEP_FLAG_NOTRUEAIM);
/* rating */ ATTRIB(Mortar, bot_pickupbasevalue, float, 7000);
/* color */ ATTRIB(Mortar, wpcolor, vector, '1 0 0');
/* modelname */ ATTRIB(Mortar, mdl, string, "gl");
#include "porto.qh"
+#ifdef CSQC
+STATIC_INIT(Porto)
+{
+ entity e = new_pure(porto);
+ e.draw = Porto_Draw;
+ IL_PUSH(g_drawables, e);
+ e.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+}
+
+const int polyline_length = 16;
+.vector polyline[polyline_length];
+void Porto_Draw(entity this)
+{
+ if (spectatee_status || intermission == 1 || intermission == 2 || STAT(HEALTH) <= 0 || WEP_CVAR(porto, secondary)) return;
+
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ entity wepent = viewmodels[slot];
+
+ if (wepent.activeweapon != WEP_PORTO) continue;
+
+ vector pos = view_origin;
+ vector dir = view_forward;
+ makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles));
+ pos += v_right * -wepent.movedir.y
+ + v_up * wepent.movedir.z;
+
+ if (wepent.angles_held_status)
+ {
+ makevectors(wepent.angles_held);
+ dir = v_forward;
+ }
+
+ wepent.polyline[0] = pos;
+
+ int portal_number = 0, portal1_idx = 1, portal_max = 2;
+ int n = 1 + 2; // 2 lines == 3 points
+ for (int idx = 0; idx < n && idx < polyline_length - 1; )
+ {
+ traceline(pos, pos + 65536 * dir, true, this);
+ dir = reflect(dir, trace_plane_normal);
+ pos = trace_endpos;
+ wepent.polyline[++idx] = pos;
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+ {
+ n += 1;
+ continue;
+ }
+ if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+ {
+ n = max(2, idx);
+ break;
+ }
+ // check size
+ {
+ vector ang = vectoangles2(trace_plane_normal, dir);
+ ang.x = -ang.x;
+ makevectors(ang);
+ if (!CheckWireframeBox(this, pos - 48 * v_right - 48 * v_up + 16 * v_forward, 96 * v_right, 96 * v_up, 96 * v_forward))
+ {
+ n = max(2, idx);
+ break;
+ }
+ }
+ portal_number += 1;
+ if (portal_number >= portal_max) break;
+ if (portal_number == 1) portal1_idx = idx;
+ }
+ for (int idx = 0; idx < n - 1; ++idx)
+ {
+ vector p = wepent.polyline[idx], q = wepent.polyline[idx + 1];
+ if (idx == 0) p -= view_up * 16; // line from player
+ vector rgb = (idx < portal1_idx) ? '1 0 0' : '0 0 1';
+ Draw_CylindricLine(p, q, 4, "", 1, 0, rgb, 0.5, DRAWFLAG_NORMAL, view_origin);
+ }
+ }
+}
+#endif
+
#ifdef SVQC
#include <common/mapobjects/trigger/jumppads.qh>
#include <server/weapons/throwing.qh>
/* spawnfunc */ ATTRIB(PortoLaunch, m_canonical_spawnfunc, string, "weapon_porto");
/* ammotype */ ATTRIB(PortoLaunch, ammo_type, int, RES_NONE);
/* impulse */ ATTRIB(PortoLaunch, impulse, int, 0);
-/* flags */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON | WEP_FLAG_NODUAL);
+/* flags */ ATTRIB(PortoLaunch, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON | WEP_FLAG_NODUAL | WEP_FLAG_NOTRUEAIM);
/* rating */ ATTRIB(PortoLaunch, bot_pickupbasevalue, float, 0);
/* color */ ATTRIB(PortoLaunch, wpcolor, vector, '0.5 0.5 0.5');
/* modelname */ ATTRIB(PortoLaunch, mdl, string, "porto");
SPAWNFUNC_WEAPON(weapon_porto, WEP_PORTO)
+#ifdef CSQC
+void Porto_Draw(entity this);
+#endif
+
#ifdef SVQC
.entity porto_current;
.vector porto_v_angle; // holds "held" view angles
vector o;
float n = W_Tuba_GetNote(actor, hittype);
- hittype = 0;
+ hittype = HITTYPE_SOUND;
if(actor.(weaponentity).tuba_instrument & 1)
hittype |= HITTYPE_SECONDARY;
if(actor.(weaponentity).tuba_instrument & 2)
CLASS(Tuba, Weapon)
/* spawnfunc */ ATTRIB(Tuba, m_canonical_spawnfunc, string, "weapon_tuba");
/* impulse */ ATTRIB(Tuba, impulse, int, 1);
-/* flags */ ATTRIB(Tuba, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH | WEP_FLAG_NODUAL);
+/* flags */ ATTRIB(Tuba, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH | WEP_FLAG_NODUAL | WEP_FLAG_NOTRUEAIM);
/* rating */ ATTRIB(Tuba, bot_pickupbasevalue, float, 2000);
/* color */ ATTRIB(Tuba, wpcolor, vector, '0 1 0');
/* modelname */ ATTRIB(Tuba, mdl, string, "tuba");
\
PROP(false, porto_v_angle_held, WEPENT_SET_NORMAL, \
{ WriteByte(chan, this.porto_v_angle_held); if(this.porto_v_angle_held) { \
- WriteAngle(chan, this.porto_v_angle.x); WriteAngle(chan, this.porto_v_angle.y); \
+ WriteAngle(chan, this.owner.porto_v_angle.x); WriteAngle(chan, this.owner.porto_v_angle.y); \
} }, \
{ (viewmodels[this.m_wepent_slot]).angles_held_status = ReadByte(); if((viewmodels[this.m_wepent_slot]).angles_held_status) { \
- (viewmodels[this.m_wepent_slot]).angles_held_x = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_y = ReadAngle(); (viewmodels[this.m_wepent_slot]).angles_held_z = 0; } \
+ (viewmodels[this.m_wepent_slot]).angles_held = vec2(ReadAngle(), ReadAngle()); } \
else { (viewmodels[this.m_wepent_slot]).angles_held = '0 0 0'; } }) \
\
PROP(false, tuba_instrument, WEPENT_SET_NORMAL, \
#define REGISTRY_HASH(id) Registry_hash_##id
ERASEABLE
-ACCUMULATE void Registry_check(string r, string server) { }
+ACCUMULATE void Registry_check(string r, string sv) { }
ERASEABLE
ACCUMULATE void Registry_send_all() { }
STATIC_INIT(Registry_check_##id) \
{ \
/* Note: SHA256 isn't always available, use MD4 instead */ \
- string s = "", join = ":"; \
- FOREACH(id, true, s = strcat(s, join, it.registered_id)); \
- s = substring(s, strlen(join), -1); \
+ string s = ""; \
+ FOREACH(id, true, s = strcat(s, ":", it.registered_id)); \
+ s = substring(s, 1, -1); /* remove initial ":" */ \
string h = REGISTRY_HASH(id) = strzone(digest_hex("MD4", s)); \
LOG_DEBUGF(#id ": %s\n[%s]", h, s); \
} \
bool autocvar_g_maplist_votable_suggestions;
bool autocvar_g_maplist_votable_suggestions_override_mostrecent;
float autocvar_g_maplist_votable_timeout;
+bool autocvar_g_maplist_ignore_sizes;
int autocvar_g_maxplayers;
float autocvar_g_maxplayers_spectator_blocktime;
float autocvar_g_maxpushtime;
}
// automatically create missing waypoints
-.entity botframe_autowaypoints_lastwp0, botframe_autowaypoints_lastwp1;
void botframe_autowaypoints_fix(entity p, float walkfromwp, .entity fld)
{
float r = botframe_autowaypoints_fix_from(p, walkfromwp, p.(fld), fld);
});
}
+//.entity botframe_autowaypoints_lastwp0;
+.entity botframe_autowaypoints_lastwp1;
void botframe_autowaypoints()
{
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && !IS_DEAD(it), {
string versionmessage = GetClientVersionMessage(this);
string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n");
- s = strcat(s, "^8\nCurrent map: ^2", GetMapname(), "^8\n");
if(modifications != "")
s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
LOG_TRACE(checkwp_msg, ": has waypoints");
}
+ if(autocvar_g_maplist_ignore_sizes)
+ return true;
+
// open map size restriction file
string opensize_msg = strcat("opensize ", map);
float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
}
- WepSet precache_weapons = start_weapons;
- if (g_warmup_allguns != 1)
- precache_weapons |= warmup_start_weapons;
- FOREACH(Weapons, it != WEP_Null, {
- if(precache_weapons & (it.m_wepset))
- it.wr_init(it);
- });
-
start_ammo_shells = max(0, start_ammo_shells);
start_ammo_nails = max(0, start_ammo_nails);
start_ammo_rockets = max(0, start_ammo_rockets);
if (time < this.spawnshieldtime && autocvar_g_spawnshield_blockdamage < 1)
damage *= 1 - max(0, autocvar_g_spawnshield_blockdamage);
- if(DEATH_ISWEAPON(deathtype, WEP_TUBA))
+ if(deathtype & HITTYPE_SOUND) // sound based attacks cause bleeding from the ears
{
- // tuba causes blood to come out of the ears
vector ear1, ear2;
vector d;
float f;
#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
IntrusiveList g_race_targets;
-STATIC_INIT(g_race_targets) { g_race_targets = IL_NEW(); }
+IntrusiveList g_racecheckpoints;
+STATIC_INIT(g_race)
+{
+ g_race_targets = IL_NEW();
+ g_racecheckpoints = IL_NEW();
+}
void race_InitSpectator()
{
.float race_respawn_checkpoint;
.entity race_respawn_spotref; // try THIS spawn in case you respawn
-IntrusiveList g_racecheckpoints;
-STATIC_INIT(g_racecheckpoints) { g_racecheckpoints = IL_NEW(); }
-
// definitions for functions used outside race.qc
float race_PreviousCheckpoint(float f);
float race_NextCheckpoint(float f);
entity pseudoprojectile = NULL;
vector dir = normalize(end - start);
- float length = vlen(end - start);
+ //float max_length = vlen(end - start);
vector force = dir * bforce;
// go a little bit into the wall because we need to hit this wall later
//explosion = spawn();
// Find all non-hit players the beam passed close by
+ float length = vlen(trace_endpos - start);
if(deathtype == WEP_VAPORIZER.m_id || deathtype == WEP_VORTEX.m_id) // WEAPONTODO
{
FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != this, {
- if(!it.railgunhit)
- if(!(IS_SPEC(it) && it.enemy == this))
+ if (!it.railgunhit && !(IS_SPEC(it) && it.enemy == this))
{
- msg_entity = it;
// nearest point on the beam
- vector beampos = start + dir * bound(0, (msg_entity.origin - start) * dir, length);
+ vector beampos = start + dir * bound(0, (it.origin - start) * dir, length);
- float f = bound(0, 1 - vlen(beampos - msg_entity.origin) / 512, 1);
+ float f = bound(0, 1 - vlen(beampos - it.origin) / 512, 1);
if(f <= 0)
continue;
if(!pseudoprojectile)
pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
+ msg_entity = it;
soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, SND(NEXWHOOSH_RANDOM()), VOL_BASE * f, ATTEN_NONE);
}
});
set g_maplist_selectrandom 0 "if 1, a random map will be chosen as next map - DEPRECATED in favor of g_maplist_shuffle"
set g_maplist_shuffle 1 "new randomization method: like selectrandom, but avoid playing the same maps in short succession. This works by taking out the first element and inserting it into g_maplist with a bias to the end of the list"
set g_maplist_check_waypoints 0 "when 1, maps are skipped if there currently are bots, but the map has no waypoints"
+set g_maplist_ignore_sizes 0 "when 1, all maps are shown in the map list regardless of player count"
set g_items_mindist 4000 "starting distance for the fading of items"
set g_items_maxdist 4500 "maximum distance at which an item can be viewed, after which it will be invisible"