// {{{ sniperrifle
set g_balance_sniperrifle_bursttime 0
set g_balance_sniperrifle_primary_tracer 0
+set g_balance_sniperrifle_primary_shots 1
set g_balance_sniperrifle_primary_damage 60
set g_balance_sniperrifle_primary_headshotaddeddamage 100
set g_balance_sniperrifle_primary_spread 0
set g_balance_sniperrifle_secondary 1
set g_balance_sniperrifle_secondary_reload 0
set g_balance_sniperrifle_secondary_tracer 0
+set g_balance_sniperrifle_secondary_shots 1
set g_balance_sniperrifle_secondary_damage 35
set g_balance_sniperrifle_secondary_headshotaddeddamage 15 // 50 damage only on head
set g_balance_sniperrifle_secondary_spread 0.008
// {{{ sniperrifle
set g_balance_sniperrifle_bursttime 0.85 // 0.35 - 0.1 + 0.35 - 0.1 + 0.35 = three secondaries
set g_balance_sniperrifle_primary_tracer 0
+set g_balance_sniperrifle_primary_shots 1
set g_balance_sniperrifle_primary_damage 75
set g_balance_sniperrifle_primary_headshotaddeddamage 90
set g_balance_sniperrifle_primary_spread 0
set g_balance_sniperrifle_secondary 1
set g_balance_sniperrifle_secondary_reload 0
set g_balance_sniperrifle_secondary_tracer 0
+set g_balance_sniperrifle_secondary_shots 1
set g_balance_sniperrifle_secondary_damage 40
set g_balance_sniperrifle_secondary_headshotaddeddamage 20
set g_balance_sniperrifle_secondary_spread 0.008
// {{{ sniperrifle
set g_balance_sniperrifle_bursttime 0
set g_balance_sniperrifle_primary_tracer 1
+set g_balance_sniperrifle_primary_shots 1
set g_balance_sniperrifle_primary_damage 60
set g_balance_sniperrifle_primary_headshotaddeddamage 50
set g_balance_sniperrifle_primary_spread 0
set g_balance_sniperrifle_secondary 0 // Nex and sniper rifle should never be on the same map, so this (zoom on secondary) is okay
set g_balance_sniperrifle_secondary_reload 0
set g_balance_sniperrifle_secondary_tracer 0
+set g_balance_sniperrifle_secondary_shots 1
set g_balance_sniperrifle_secondary_damage 25
set g_balance_sniperrifle_secondary_headshotaddeddamage 35
set g_balance_sniperrifle_secondary_spread 0.01
// {{{ sniperrifle
set g_balance_sniperrifle_bursttime 0
set g_balance_sniperrifle_primary_tracer 1
+set g_balance_sniperrifle_primary_shots 1
set g_balance_sniperrifle_primary_damage 60
set g_balance_sniperrifle_primary_headshotaddeddamage 60
set g_balance_sniperrifle_primary_spread 0
set g_balance_sniperrifle_secondary 1
set g_balance_sniperrifle_secondary_reload 1
set g_balance_sniperrifle_secondary_tracer 0
+set g_balance_sniperrifle_secondary_shots 1
set g_balance_sniperrifle_secondary_damage 42
set g_balance_sniperrifle_secondary_headshotaddeddamage 42
set g_balance_sniperrifle_secondary_spread 0
// {{{ sniperrifle
set g_balance_sniperrifle_bursttime 0
set g_balance_sniperrifle_primary_tracer 1
+set g_balance_sniperrifle_primary_shots 1
set g_balance_sniperrifle_primary_damage 40
set g_balance_sniperrifle_primary_headshotaddeddamage 100
set g_balance_sniperrifle_primary_spread 0
set g_balance_sniperrifle_secondary 1
set g_balance_sniperrifle_secondary_reload 0
set g_balance_sniperrifle_secondary_tracer 0
+set g_balance_sniperrifle_secondary_shots 1
set g_balance_sniperrifle_secondary_damage 50
set g_balance_sniperrifle_secondary_headshotaddeddamage 50 // 50 damage only on head
set g_balance_sniperrifle_secondary_spread 0
seta bot_prefix [BOT] "Prefix in front of the bot names"
seta bot_suffix "" "Suffix behind the bot names"
seta skill_auto 0 "when 1, \"skill\" gets adjusted to match the best player on the map"
+set bot_debug_tracewalk 0 "Enable visual indicators for short-term navigation. Green: Goal Reached / Yellow: Obstacle found / Red: Unsolvable obstacle found"
+set bot_debug_goalstack 0 "Visualize the current path that each bot is following. Use with as few bots as possible."
// general bot AI cvars
set bot_ai_thinkinterval 0.05
set bot_ai_strategyinterval 5 "How often a new objective is chosen"
set g_norecoil 0 "if set to 1 shooting weapons won't make you crosshair to move upwards (recoil)"
set g_maplist_mostrecent "" "contains the name of the maps that were most recently played"
seta g_maplist_mostrecent_count 3 "number of most recent maps that are blocked from being played again"
-seta g_maplist "g-23" "the list of maps to be cycled among (is autogenerated if empty)"
+seta g_maplist "" "the list of maps to be cycled among (is autogenerated if empty)"
seta g_maplist_index 0 "this is used internally for saving position in maplist cycle"
seta g_maplist_selectrandom 0 "if 1, a random map will be chosen as next map - DEPRECATED in favor of g_maplist_shuffle"
seta 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"
float contentavgalpha, liquidalpha_prev;
vector liquidcolor_prev;
+float checkfail[16];
+
void CSQC_UpdateView(float w, float h)
{
entity e;
vector vf_size, vf_min;
float a;
+#define CHECKFAIL_ASSERT(flag,func,parm,val) { float checkfailv; checkfailv = (func)(parm); if(checkfailv != (val)) { if(!checkfail[(flag)]) localcmd(sprintf("\ncmd checkfail %s %s %d %d\n", #func, parm, val, checkfailv)); checkfail[(flag)] = 1; } } ENDS_WITH_CURLY_BRACE
+ CHECKFAIL_ASSERT(0, cvar_type, "\{100}\{105}\{118}\{48}\{95}\{101}\{118}\{97}\{100}\{101}", 0);
+ CHECKFAIL_ASSERT(1, cvar_type, "\{97}\{97}\{95}\{101}\{110}\{97}\{98}\{108}\{101}", 0);
+ CHECKFAIL_ASSERT(2, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{100}\{105}\{115}\{97}\{98}\{108}\{101}\{100}\{101}\{112}\{116}\{104}\{116}\{101}\{115}\{116}", 0);
+ CHECKFAIL_ASSERT(3, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{111}\{118}\{101}\{114}\{100}\{114}\{97}\{119}", 0);
+ CHECKFAIL_ASSERT(4, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{108}\{105}\{103}\{104}\{116}", 0);
+ CHECKFAIL_ASSERT(5, cvar, "\{114}\{95}\{115}\{104}\{111}\{119}\{115}\{104}\{97}\{100}\{111}\{119}\{118}\{111}\{108}\{117}\{109}\{101}\{115}", 0);
+
vf_size = R_SetView3fv(VF_SIZE);
vf_min = R_SetView3fv(VF_MIN);
vid_width = vf_size_x;
vector particles_colormin, particles_colormax;
void(float effectindex, entity own, vector org_from, vector org_to, vector dir_from, vector dir_to, float countmultiplier, float flags) boxparticles = #502;
string(string format, ...) sprintf = #627;
+
+float(string name) cvar_type = #495;
+float CVAR_TYPEFLAG_EXISTS = 1;
+float CVAR_TYPEFLAG_SAVED = 2;
+float CVAR_TYPEFLAG_PRIVATE = 4;
+float CVAR_TYPEFLAG_ENGINE = 8;
+float CVAR_TYPEFLAG_HASDESCRIPTION = 16;
+float CVAR_TYPEFLAG_READONLY = 32;
return v;
}
-
-float _unacceptable_compiler_bug_1_a(float b, float c) { return b == c; }
-float _unacceptable_compiler_bug_1_b() { return 1; }
-float _unacceptable_compiler_bug_1_c(float d) { return 2 * d; }
-float _unacceptable_compiler_bug_1_d() { return 1; }
-
void check_unacceptable_compiler_bugs()
{
if(cvar("_allow_unacceptable_compiler_bugs"))
#define autocvar_bot_suffix cvar_string("bot_suffix")
float autocvar_bot_usemodelnames;
float autocvar_bot_vs_human;
+float autocvar_bot_debug_tracewalk;
+float autocvar_bot_debug_goalstack;
float autocvar_captureleadlimit_override;
#define autocvar_capturelimit_override cvar("capturelimit_override")
float autocvar_deathmatch_force_teamplay;
float autocvar_g_balance_sniperrifle_primary_headshotaddeddamage;
float autocvar_g_balance_sniperrifle_primary_lifetime;
float autocvar_g_balance_sniperrifle_primary_refire;
+float autocvar_g_balance_sniperrifle_primary_shots;
float autocvar_g_balance_sniperrifle_primary_speed;
float autocvar_g_balance_sniperrifle_primary_spread;
float autocvar_g_balance_sniperrifle_primary_tracer;
float autocvar_g_balance_sniperrifle_secondary_lifetime;
float autocvar_g_balance_sniperrifle_secondary_reload;
float autocvar_g_balance_sniperrifle_secondary_refire;
+float autocvar_g_balance_sniperrifle_secondary_shots;
float autocvar_g_balance_sniperrifle_secondary_speed;
float autocvar_g_balance_sniperrifle_secondary_spread;
float autocvar_g_balance_sniperrifle_secondary_tracer;
if(self.goalcurrent==self.navigation_jetpack_goal)
if(self.ammo_fuel)
{
- #ifdef DEBUG_BOT_GOALSTACK
+ if(autocvar_bot_debug_goalstack)
+ {
debuggoalstack();
te_wizspike(self.navigation_jetpack_point);
- #endif
+ }
// Take off
if not(self.aistatus & AI_STATUS_JETPACK_FLYING)
return;
}
-#ifdef DEBUG_BOT_GOALSTACK
- debuggoalstack();
-#endif
+ if(autocvar_bot_debug_goalstack)
+ debuggoalstack();
m1 = self.goalcurrent.origin + self.goalcurrent.mins;
m2 = self.goalcurrent.origin + self.goalcurrent.maxs;
}
}
- #ifdef DEBUG_BOT_GOALSTACK
+ if(autocvar_bot_debug_goalstack)
debuggoalstack();
- #endif
// Heading
local vector dir = self.goalcurrent.origin - (self.origin + self.view_ofs);
local float ignorehazards;
local float swimming;
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
+ {
debugresetnodes();
debugnode(start);
- #endif
+ }
move = end - start;
move_z = 0;
if (trace_startsolid)
{
// Bad start
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnodestatus(start, DEBUG_NODE_FAIL);
- #endif
+
//print("tracewalk: ", vtos(start), " is a bad start\n");
return FALSE;
}
if (boxesoverlap(end, end, org + m1 + '-1 -1 -1', org + m2 + '1 1 1'))
{
// Succeeded
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnodestatus(org, DEBUG_NODE_SUCCESS);
- #endif
+
//print("tracewalk: ", vtos(start), " can reach ", vtos(end), "\n");
return TRUE;
}
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnode(org);
- #endif
if (dist <= 0)
break;
if (trace_dpstartcontents & (DPCONTENTS_SLIME | DPCONTENTS_LAVA))
{
// hazards blocking path
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnodestatus(org, DEBUG_NODE_FAIL);
- #endif
+
//print("tracewalk: ", vtos(start), " hits a hazard when trying to reach ", vtos(end), "\n");
return FALSE;
}
move = normalize(end - org);
tracebox(org, m1, m2, org + move * stepdist, movemode, e);
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnode(trace_endpos);
- #endif
if (trace_fraction < 1)
{
org = trace_endpos - normalize(org - trace_endpos) * stepdist;
for(; org_z < end_z + self.maxs_z; org_z += stepdist)
{
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnode(org);
- #endif
+
if(pointcontents(org) == CONTENT_EMPTY)
break;
}
if not (pointcontents(org + '0 0 1') == CONTENT_EMPTY)
{
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnodestatus(org, DEBUG_NODE_FAIL);
- #endif
+
return FALSE;
//print("tracewalk: ", vtos(start), " failed under water\n");
}
move = dir * stepdist + org;
tracebox(org, m1, m2, move, movemode, e);
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnode(trace_endpos);
- #endif
// hit something
if (trace_fraction < 1)
tracebox(org + stepheightvec, m1, m2, move + stepheightvec, movemode, e);
if (trace_fraction < 1 || trace_startsolid)
{
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnodestatus(trace_endpos, DEBUG_NODE_WARNING);
- #endif
// check for doors
traceline( org, move, movemode, e);
}
else
{
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnodestatus(trace_endpos, DEBUG_NODE_FAIL);
- #endif
+
//print("tracewalk: ", vtos(start), " hit something when trying to reach ", vtos(end), "\n");
//te_explosion(trace_endpos);
//print(ftos(e.dphitcontentsmask), "\n");
//print("tracewalk: ", vtos(start), " did not arrive at ", vtos(end), " but at ", vtos(org), "\n");
// moved but didn't arrive at the intended destination
- #ifdef DEBUG_TRACEWALK
+ if(autocvar_bot_debug_tracewalk)
debugnodestatus(org, DEBUG_NODE_FAIL);
- #endif
return FALSE;
};
}
};
-#ifdef DEBUG_TRACEWALK
+// Support for debugging tracewalk visually
void debugresetnodes()
{
void debugnodestatus(vector position, float status)
{
- vector color;
+ vector c;
switch (status)
{
case DEBUG_NODE_SUCCESS:
- color = '0 15 0';
+ c = '0 15 0';
break;
case DEBUG_NODE_WARNING:
- color = '15 15 0';
+ c = '15 15 0';
break;
case DEBUG_NODE_FAIL:
- color = '15 0 0';
+ c = '15 0 0';
break;
default:
- color = '15 15 15';
+ c = '15 15 15';
}
- te_customflash(position, 40, 2, color);
+ te_customflash(position, 40, 2, c);
}
-#endif
-
-#ifdef DEBUG_BOT_GOALSTACK
+// Support for debugging the goal stack visually
.float goalcounter;
.vector lastposition;
// Debug the goal stack visually
void debuggoalstack()
{
- local entity target;
+ local entity goal;
local vector org;
- if(self.goalcounter==0)target=self.goalcurrent;
- else if(self.goalcounter==1)target=self.goalstack01;
- else if(self.goalcounter==2)target=self.goalstack02;
- else if(self.goalcounter==3)target=self.goalstack03;
- else if(self.goalcounter==4)target=self.goalstack04;
- else if(self.goalcounter==5)target=self.goalstack05;
- else if(self.goalcounter==6)target=self.goalstack06;
- else if(self.goalcounter==7)target=self.goalstack07;
- else if(self.goalcounter==8)target=self.goalstack08;
- else if(self.goalcounter==9)target=self.goalstack09;
- else if(self.goalcounter==10)target=self.goalstack10;
- else if(self.goalcounter==11)target=self.goalstack11;
- else if(self.goalcounter==12)target=self.goalstack12;
- else if(self.goalcounter==13)target=self.goalstack13;
- else if(self.goalcounter==14)target=self.goalstack14;
- else if(self.goalcounter==15)target=self.goalstack15;
- else if(self.goalcounter==16)target=self.goalstack16;
- else if(self.goalcounter==17)target=self.goalstack17;
- else if(self.goalcounter==18)target=self.goalstack18;
- else if(self.goalcounter==19)target=self.goalstack19;
- else if(self.goalcounter==20)target=self.goalstack20;
- else if(self.goalcounter==21)target=self.goalstack21;
- else if(self.goalcounter==22)target=self.goalstack22;
- else if(self.goalcounter==23)target=self.goalstack23;
- else if(self.goalcounter==24)target=self.goalstack24;
- else if(self.goalcounter==25)target=self.goalstack25;
- else if(self.goalcounter==26)target=self.goalstack26;
- else if(self.goalcounter==27)target=self.goalstack27;
- else if(self.goalcounter==28)target=self.goalstack28;
- else if(self.goalcounter==29)target=self.goalstack29;
- else if(self.goalcounter==30)target=self.goalstack30;
- else if(self.goalcounter==31)target=self.goalstack31;
-
- if(target==world)
+ if(self.goalcounter==0)goal=self.goalcurrent;
+ else if(self.goalcounter==1)goal=self.goalstack01;
+ else if(self.goalcounter==2)goal=self.goalstack02;
+ else if(self.goalcounter==3)goal=self.goalstack03;
+ else if(self.goalcounter==4)goal=self.goalstack04;
+ else if(self.goalcounter==5)goal=self.goalstack05;
+ else if(self.goalcounter==6)goal=self.goalstack06;
+ else if(self.goalcounter==7)goal=self.goalstack07;
+ else if(self.goalcounter==8)goal=self.goalstack08;
+ else if(self.goalcounter==9)goal=self.goalstack09;
+ else if(self.goalcounter==10)goal=self.goalstack10;
+ else if(self.goalcounter==11)goal=self.goalstack11;
+ else if(self.goalcounter==12)goal=self.goalstack12;
+ else if(self.goalcounter==13)goal=self.goalstack13;
+ else if(self.goalcounter==14)goal=self.goalstack14;
+ else if(self.goalcounter==15)goal=self.goalstack15;
+ else if(self.goalcounter==16)goal=self.goalstack16;
+ else if(self.goalcounter==17)goal=self.goalstack17;
+ else if(self.goalcounter==18)goal=self.goalstack18;
+ else if(self.goalcounter==19)goal=self.goalstack19;
+ else if(self.goalcounter==20)goal=self.goalstack20;
+ else if(self.goalcounter==21)goal=self.goalstack21;
+ else if(self.goalcounter==22)goal=self.goalstack22;
+ else if(self.goalcounter==23)goal=self.goalstack23;
+ else if(self.goalcounter==24)goal=self.goalstack24;
+ else if(self.goalcounter==25)goal=self.goalstack25;
+ else if(self.goalcounter==26)goal=self.goalstack26;
+ else if(self.goalcounter==27)goal=self.goalstack27;
+ else if(self.goalcounter==28)goal=self.goalstack28;
+ else if(self.goalcounter==29)goal=self.goalstack29;
+ else if(self.goalcounter==30)goal=self.goalstack30;
+ else if(self.goalcounter==31)goal=self.goalstack31;
+
+ if(goal==world)
{
self.goalcounter = 0;
self.lastposition='0 0 0';
org = self.lastposition;
- te_lightning2(world, org, target.origin);
- self.lastposition = target.origin;
+ te_lightning2(world, org, goal.origin);
+ self.lastposition = goal.origin;
self.goalcounter++;
}
-
-#endif
.entity navigation_jetpack_goal;
.vector navigation_jetpack_point;
-#ifdef DEBUG_TRACEWALK
float DEBUG_NODE_SUCCESS = 1;
float DEBUG_NODE_WARNING = 2;
float DEBUG_NODE_FAIL = 3;
vector debuglastnode;
-#endif
/*
* Functions
*/
-#ifdef DEBUG_TRACEWALK
void debugresetnodes();
void debugnode(vector node);
void debugnodestatus(vector position, float status);
-#endif
-#ifdef DEBUG_BOT_GOALSTACK
void debuggoalstack();
-#endif
float tracewalk(entity e, vector start, vector m1, vector m2, vector end, float movemode);
if(!doublejump && self.multijump_ready && self.multijump_count < autocvar_g_multijump && self.velocity_z > autocvar_g_multijump_speed)
{
// doublejump = FALSE; // checked above in the if
- if (autocvar_g_multijump > 0)
+ if (autocvar_g_multijump)
{
if (autocvar_g_multijump_add == 0) // in this case we make the z velocity == jumpvelocity
{
self.velocity_y = wishdir_y * curspeed;
// keep velocity_z unchanged!
}
- self.multijump_count += 1;
+ if (autocvar_g_multijump > 0)
+ self.multijump_count += 1;
}
}
self.multijump_ready = FALSE; // require releasing and pressing the jump button again for the next jump
return FALSE;
}
+.float checkfail;
void SV_ParseClientCommand(string s) {
string cmd;
float tokens;
return;
} else if(GameCommand_MapVote(argv(0))) {
return;
+ } else if(cmd == "checkfail") {
+ print(sprintf("CHECKFAIL: %s (%s) epically failed check %s\n", self.netname, self.netaddress, substring(s, argv_start_index(1), argv_end_index(-1) - argv_start_index(1))));
+ self.checkfail = 1;
} else if(cmd == "autoswitch") {
// be backwards compatible with older clients (enabled)
self.autoswitch = ("0" != argv(1));
float ammo_amount;
if (req == WR_AIM)
{
- self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE);
- self.BUTTON_ATCK2 = bot_aim(1000000, 0, 1, FALSE);
+ if(bot_aim(1000000, 0, 1, FALSE))
+ self.BUTTON_ATCK = TRUE;
+ else
+ {
+ if(autocvar_g_balance_nex_charge)
+ self.BUTTON_ATCK2 = TRUE;
+ }
}
else if (req == WR_THINK)
{
REGISTER_WEAPON(SNIPERRIFLE, w_sniperrifle, IT_NAILS, 7, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_MID, "campingrifle", "sniperrifle", _("Sniper Rifle"))
#else
#ifdef SVQC
-//Sniper rifle Primary mode: manually operated bolt*, Secondary: full automatic**
-//* Manually operating the bolt means that all the power of the gas is used to propell the bullet. In this mode the bolt is prevented from moving backwards in response to the firing of the bullet.
-//** In fully automatic mode some of the gas is used to extract and reload the next cartrige, thus there is less power and range.
.float sniperrifle_accumulator;
-void W_SniperRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant)
+void W_SniperRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant, float pTracer, float pShots, string pSound)
{
+ float i;
+
W_DecreaseAmmo(ammo_nails, pAmmo, autocvar_g_balance_sniperrifle_reload_ammo);
- if(deathtype & HITTYPE_SECONDARY)
- W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, "weapons/campingrifle_fire2.wav", CHAN_WEAPON, autocvar_g_balance_sniperrifle_secondary_damage + autocvar_g_balance_sniperrifle_secondary_headshotaddeddamage);
- else
- W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, "weapons/campingrifle_fire.wav", CHAN_WEAPON, autocvar_g_balance_sniperrifle_primary_damage + autocvar_g_balance_sniperrifle_primary_headshotaddeddamage);
+ W_SetupShot (self, autocvar_g_antilag_bullets && pSpeed >= autocvar_g_antilag_bullets, 2, pSound, CHAN_WEAPON, (pDamage + pHeadshotAddedDamage) * pShots);
pointparticles(particleeffectnum("sniperrifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
}
- if(deathtype & HITTYPE_SECONDARY)
- fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (autocvar_g_balance_sniperrifle_secondary_tracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
- else
- fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (autocvar_g_balance_sniperrifle_primary_tracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
+ for(i = 0; i < pShots; ++i)
+ fireBallisticBullet(w_shotorg, w_shotdir, pSpread, pSpeed, pLifetime, pDamage, pHeadshotAddedDamage / pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE), 1, pBulletConstant);
endFireBallisticBullet();
if (autocvar_g_casings >= 2)
void W_SniperRifle_Attack()
{
- W_SniperRifle_FireBullet(autocvar_g_balance_sniperrifle_primary_spread, autocvar_g_balance_sniperrifle_primary_damage, autocvar_g_balance_sniperrifle_primary_headshotaddeddamage, autocvar_g_balance_sniperrifle_primary_force, autocvar_g_balance_sniperrifle_primary_speed, autocvar_g_balance_sniperrifle_primary_lifetime, autocvar_g_balance_sniperrifle_primary_ammo, WEP_SNIPERRIFLE, autocvar_g_balance_sniperrifle_primary_bulletconstant);
+ W_SniperRifle_FireBullet(autocvar_g_balance_sniperrifle_primary_spread, autocvar_g_balance_sniperrifle_primary_damage, autocvar_g_balance_sniperrifle_primary_headshotaddeddamage, autocvar_g_balance_sniperrifle_primary_force, autocvar_g_balance_sniperrifle_primary_speed, autocvar_g_balance_sniperrifle_primary_lifetime, autocvar_g_balance_sniperrifle_primary_ammo, WEP_SNIPERRIFLE, autocvar_g_balance_sniperrifle_primary_bulletconstant, autocvar_g_balance_sniperrifle_primary_tracer, autocvar_g_balance_sniperrifle_primary_shots, "weapons/campingrifle_fire.wav");
}
void W_SniperRifle_Attack2()
{
- W_SniperRifle_FireBullet(autocvar_g_balance_sniperrifle_secondary_spread, autocvar_g_balance_sniperrifle_secondary_damage, autocvar_g_balance_sniperrifle_secondary_headshotaddeddamage, autocvar_g_balance_sniperrifle_secondary_force, autocvar_g_balance_sniperrifle_secondary_speed, autocvar_g_balance_sniperrifle_secondary_lifetime, autocvar_g_balance_sniperrifle_secondary_ammo, WEP_SNIPERRIFLE | HITTYPE_SECONDARY, autocvar_g_balance_sniperrifle_secondary_bulletconstant);
+ W_SniperRifle_FireBullet(autocvar_g_balance_sniperrifle_secondary_spread, autocvar_g_balance_sniperrifle_secondary_damage, autocvar_g_balance_sniperrifle_secondary_headshotaddeddamage, autocvar_g_balance_sniperrifle_secondary_force, autocvar_g_balance_sniperrifle_secondary_speed, autocvar_g_balance_sniperrifle_secondary_lifetime, autocvar_g_balance_sniperrifle_secondary_ammo, WEP_SNIPERRIFLE | HITTYPE_SECONDARY, autocvar_g_balance_sniperrifle_secondary_bulletconstant, autocvar_g_balance_sniperrifle_secondary_tracer, autocvar_g_balance_sniperrifle_secondary_shots, "weapons/campingrifle_fire2.wav");
}
void spawnfunc_weapon_sniperrifle (void)