set g_balance_hagar_secondary 1
set g_balance_hagar_secondary_load 0
set g_balance_hagar_secondary_load_speed 0.6
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
set g_balance_hagar_secondary_load_max 4
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_tuba_edgedamage 0
set g_balance_tuba_radius 200
set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
// }}}
// {{{ fireball
set g_balance_fireball_primary_ammo 40
set g_balance_hagar_secondary 1
set g_balance_hagar_secondary_load 0
set g_balance_hagar_secondary_load_speed 0.6
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
set g_balance_hagar_secondary_load_max 4
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_tuba_edgedamage 0
set g_balance_tuba_radius 200
set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
// }}}
// {{{ fireball
set g_balance_fireball_primary_ammo 40
set g_balance_hagar_secondary 1
set g_balance_hagar_secondary_load 0
set g_balance_hagar_secondary_load_speed 0.6
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
set g_balance_hagar_secondary_load_max 4
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_tuba_edgedamage 0
set g_balance_tuba_radius 200
set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
// }}}
// {{{ fireball
set g_balance_fireball_primary_ammo 5
// }}}
// {{{ misc
-set g_balance_selfdamagepercent 0.75
+set g_balance_selfdamagepercent 0.65
set g_balance_weaponswitchdelay 0.15
set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
set g_weaponratefactor 1 "weapon fire rate multiplier"
set g_balance_uzi_burst_ammo 3
set g_balance_uzi_first 1
-set g_balance_uzi_first_damage 16
+set g_balance_uzi_first_damage 14
set g_balance_uzi_first_force 5
set g_balance_uzi_first_spread 0.03
-set g_balance_uzi_first_refire 0.2
+set g_balance_uzi_first_refire 0.4
set g_balance_uzi_first_ammo 1
-set g_balance_uzi_sustained_damage 14
+set g_balance_uzi_sustained_damage 12
set g_balance_uzi_sustained_force 5
set g_balance_uzi_sustained_spread 0.04
set g_balance_uzi_sustained_refire 0.1
// {{{ nex
set g_balance_nex_primary_damage 90
set g_balance_nex_primary_force 400
-set g_balance_nex_primary_refire 1.25
-set g_balance_nex_primary_animtime 0.3
+set g_balance_nex_primary_refire 1.5
+set g_balance_nex_primary_animtime 0.4
set g_balance_nex_primary_ammo 6
set g_balance_nex_primary_damagefalloff_mindist 0 // 1000 For tZork ;3
set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000
set g_balance_minstanex_reload_time 2
// }}}
// {{{ hagar
-set g_balance_hagar_primary_damage 30
-set g_balance_hagar_primary_edgedamage 15
+set g_balance_hagar_primary_damage 25
+set g_balance_hagar_primary_edgedamage 12.5
set g_balance_hagar_primary_force 50
-set g_balance_hagar_primary_radius 70
-set g_balance_hagar_primary_spread 0.05
+set g_balance_hagar_primary_radius 60
+set g_balance_hagar_primary_spread 0.04
set g_balance_hagar_primary_speed 2000
set g_balance_hagar_primary_lifetime 5
set g_balance_hagar_primary_refire 0.15
set g_balance_hagar_secondary 1
set g_balance_hagar_secondary_load 1
set g_balance_hagar_secondary_load_speed 0.5
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
set g_balance_hagar_secondary_load_max 4
set g_balance_hagar_secondary_load_hold 1
set g_balance_hagar_secondary_load_releasedeath 0
set g_balance_hagar_secondary_edgedamage 20
set g_balance_hagar_secondary_force 50
set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_spread 0.05
+set g_balance_hagar_secondary_spread 0.06
set g_balance_hagar_secondary_speed 2000
set g_balance_hagar_secondary_lifetime_min 10
set g_balance_hagar_secondary_lifetime_rand 0
set g_balance_rocketlauncher_damage 80
set g_balance_rocketlauncher_edgedamage 40
set g_balance_rocketlauncher_force 400
-set g_balance_rocketlauncher_radius 100
+set g_balance_rocketlauncher_radius 110
set g_balance_rocketlauncher_speed 1500
set g_balance_rocketlauncher_speedaccel 1500
set g_balance_rocketlauncher_speedstart 800
set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
set g_balance_rocketlauncher_remote_damage 70
set g_balance_rocketlauncher_remote_edgedamage 35
-set g_balance_rocketlauncher_remote_radius 100
+set g_balance_rocketlauncher_remote_radius 110
set g_balance_rocketlauncher_remote_force 400
set g_balance_rocketlauncher_reload_ammo 0 //default: 25
set g_balance_rocketlauncher_reload_time 2
set g_balance_tuba_edgedamage 0
set g_balance_tuba_radius 200
set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
// }}}
// {{{ fireball // this is a superweapon -- lets make it behave as one.
set g_balance_fireball_primary_ammo 20
set g_balance_hagar_secondary 1
set g_balance_hagar_secondary_load 0
set g_balance_hagar_secondary_load_speed 0.6
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
set g_balance_hagar_secondary_load_max 4
set g_balance_hagar_secondary_load_hold 0
set g_balance_hagar_secondary_load_releasedeath 1
set g_balance_tuba_edgedamage 0
set g_balance_tuba_radius 200
set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
// }}}
// {{{ fireball
set g_balance_fireball_primary_ammo 40
set _campaign_index ""
set _campaign_name ""
+// debug
+set _independent_players 0 "DO NOT TOUCH"
+
// define some engine cvars that we need even on dedicated server
set r_showbboxes 0
float autocvar_g_balance_tuba_attenuation;
float autocvar_g_balance_tuba_fadetime;
float autocvar_g_balance_tuba_volume;
+float autocvar_g_balance_tuba_pitchstep;
float autocvar_g_warmup_limit;
var float autocvar_g_waypointsprite_uppercase = 1;
var float autocvar_g_waypointsprite_alpha = 1;
-#define TUBA_STARTNOTE(n) strcat((checkextension("DP_SND_SETPARAMS") ? "weapons/tuba_loopnote" : "weapons/tuba_note"), ftos(n), ".wav")
-.float cnt; // note
+#define TUBA_MIN -18
+#define TUBA_MAX 27
+
+#define TUBA_STARTNOTE(n) strcat("weapons/tuba_loopnote", ftos(n), ".wav")
+.float note; // note
.float attenuate; // if set, attenuate it
+.float cnt; // current volume
+.float count; // initial volume
+
+float Tuba_PitchStep;
+
+void tubasound(entity e, float restart)
+{
+ string snd1;
+
+ snd1 = string_null;
+
+ if(Tuba_PitchStep)
+ {
+ string snd2;
+ float f1, f2;
+ float p1, p2;
+ float m;
+
+ f1 = 1;
+ p1 = 1;
+ snd2 = string_null;
+ f2 = 0;
+ p2 = 1;
+
+ m = mod(e.note, Tuba_PitchStep);
+ if(m)
+ {
+ if(e.note - m < TUBA_MIN)
+ {
+ if(restart)
+ snd1 = TUBA_STARTNOTE(e.note - m + Tuba_PitchStep);
+ p1 = pow(2.0, (m - Tuba_PitchStep) / 12.0);
+ }
+ else if(e.note - m + Tuba_PitchStep > TUBA_MAX)
+ {
+ if(restart)
+ snd1 = TUBA_STARTNOTE(e.note - m);
+ p1 = pow(2.0, m / 12.0);
+ }
+ else
+ {
+ if(restart)
+ snd1 = TUBA_STARTNOTE(e.note - m);
+ f1 = 1 - m / Tuba_PitchStep;
+ p1 = pow(2.0, m / 12.0);
+ if(restart)
+ snd2 = TUBA_STARTNOTE(e.note - m + Tuba_PitchStep);
+ f2 = m / Tuba_PitchStep;
+ p2 = pow(2.0, (m - Tuba_PitchStep) / 12.0);
+ }
+ }
+ else
+ {
+ if(restart)
+ snd1 = TUBA_STARTNOTE(e.note);
+ }
+
+ sound7(e, CH_TUBA, snd1, e.cnt * f1, e.attenuate * autocvar_g_balance_tuba_attenuation, 100 * p1, 0);
+ if(f2)
+ sound7(e.enemy, CH_TUBA, snd2, e.cnt * f2, e.attenuate * autocvar_g_balance_tuba_attenuation, 100 * p2, 0);
+ }
+ else
+ {
+ if(restart)
+ snd1 = TUBA_STARTNOTE(e.note);
+ sound(e, CH_TUBA, snd1, e.cnt, e.attenuate * autocvar_g_balance_tuba_attenuation);
+ }
+}
void Ent_TubaNote_Think()
{
self.nextthink = time;
if(self.cnt <= 0)
{
- sound(self, CH_SHOTS_SINGLE, "misc/null.wav", 0, 0);
+ sound(self, CH_TUBA, "misc/null.wav", 0, 0);
+ if(self.enemy)
+ {
+ sound(self.enemy, CH_TUBA, "misc/null.wav", 0, 0);
+ remove(self.enemy);
+ }
remove(self);
}
else
- sound(self, CH_SHOTS_SINGLE, "", self.cnt, self.attenuate * autocvar_g_balance_tuba_attenuation);
+ {
+ tubasound(self, 0);
+ }
}
void Ent_TubaNote_UpdateSound()
{
self.enemy.cnt = bound(0, VOL_BASE * autocvar_g_balance_tuba_volume, 1);
self.enemy.count = self.enemy.cnt;
-#ifdef PITCHSHIFT
- sound7(self.enemy, CH_SHOTS_SINGLE, TUBA_STARTNOTE(0), self.enemy.cnt, self.enemy.attenuate * autocvar_g_balance_tuba_attenuation, 100 * pow(2.0, self.cnt / 12.0), 0);
-#else
- sound(self.enemy, CH_SHOTS_SINGLE, TUBA_STARTNOTE(self.cnt), self.enemy.cnt, self.enemy.attenuate * autocvar_g_balance_tuba_attenuation);
-#endif
+ self.enemy.note = self.note;
+ tubasound(self.enemy, 1);
}
void Ent_TubaNote_StopSound()
float f, n;
f = ReadByte();
n = floor(f / 2) - 42;
- if(n != self.cnt || bIsNew)
+ if(n != self.note || bIsNew)
if(self.enemy)
Ent_TubaNote_StopSound();
if(!self.enemy)
{
self.enemy = spawn();
self.enemy.classname = "tuba_note";
+ if(Tuba_PitchStep)
+ {
+ self.enemy.enemy = spawn();
+ self.enemy.enemy.classname = "tuba_note_2";
+ }
bIsNew = TRUE;
}
if(f & 1)
self.enemy.origin_z = ReadCoord();
setorigin(self.enemy, self.enemy.origin);
self.enemy.attenuate = ReadByte();
+ if(self.enemy.enemy)
+ setorigin(self.enemy.enemy, self.enemy.origin);
}
self.think = Ent_TubaNote_StopSound;
self.entremove = Ent_TubaNote_StopSound;
self.enemy.nextthink = time + 10;
if(bIsNew)
{
- self.cnt = n;
+ self.note = n;
Ent_TubaNote_UpdateSound();
}
}
void Tuba_Precache()
{
float i;
-#ifdef PITCHSHIFT
- precache_sound(TUBA_STARTNOTE(0));
-#else
- for(i = -18; i <= +27; ++i)
+ Tuba_PitchStep = autocvar_g_balance_tuba_pitchstep;
+ if(Tuba_PitchStep)
+ {
+ if(!checkextension("DP_SND_SOUND7_WIP2") && !checkextension("DP_SND_SOUND7"))
+ {
+ print("^1NOTE:^7 requested pitch shifting, but not supported by this engine build\n");
+ Tuba_PitchStep = 0;
+ }
+ }
+ for(i = TUBA_MIN; i <= TUBA_MAX; ++i)
{
- precache_sound(TUBA_STARTNOTE(i));
+ if(!Tuba_PitchStep || (mod(i, Tuba_PitchStep) == 0))
+ precache_sound(TUBA_STARTNOTE(i));
}
-#endif
- //precache_sound(""); // we want to change volume of existing sounds
}
float CH_PAIN = 6; // only on players and csqc
float CH_PAIN_SINGLE = 6; // only on players and csqc
float CH_PLAYER = 7; // only on players and entities
+float CH_TUBA = 5; // only on csqc
#else
float CH_INFO = 0;
float CH_TRIGGER = -3;
float CH_PAIN = -6;
float CH_PAIN_SINGLE = 6;
float CH_PLAYER = -7;
+float CH_TUBA = 5;
#endif
float ATTN_NONE = 0;
#pragma flag enable lo
#ifndef NOCOMPAT
-# define WORKAROUND_XON010
-# define COMPAT_XON010_CHANNELS
+//# define WORKAROUND_XON010
+//# define COMPAT_XON010_CHANNELS
#endif
me.TR(me);
me.TDempty(me, 0.2);
s = makeXonoticDecibelsSlider(-20, 0, 0.5, "snd_channel1volume");
- makeMulti(s, "snd_channel5volume"); // legacy
+ makeMulti(s, "snd_channel5volume"); // @!#%'n Tuba
me.TD(me, 1, 0.8, e = makeXonoticSliderCheckBox(-1000000, 1, s, _("Weapons:")));
me.TD(me, 1, 2, s);
setDependentStringNotEqual(e, "mastervolume", "0");
me.TR(me);
me.TD(me, 1, 3, e = makeXonoticTextLabel(0, _("Key bindings:")));
me.TR(me);
- me.TD(me, me.rows - 2, 3.3, kb = makeXonoticKeyBinder());
- me.gotoRC(me, me.rows - 1, 0);
+ me.TD(me, me.rows - 4, 3.3, kb = makeXonoticKeyBinder());
+ me.gotoRC(me, me.rows - 3, 0);
me.TR(me);
me.TD(me, 1, 1.1, e = makeXonoticButton(_("Change key..."), '0 0 0'));
e.onClick = KeyBinder_Bind_Change;
+float autocvar__independent_players;
float autocvar__campaign_index;
string autocvar__campaign_name;
float autocvar__sv_init;
float autocvar_g_balance_hagar_secondary;
float autocvar_g_balance_hagar_secondary_load;
float autocvar_g_balance_hagar_secondary_load_speed;
+float autocvar_g_balance_hagar_secondary_load_spread;
+float autocvar_g_balance_hagar_secondary_load_spread_bias;
float autocvar_g_balance_hagar_secondary_load_max;
float autocvar_g_balance_hagar_secondary_load_hold;
float autocvar_g_balance_hagar_secondary_load_releasedeath;
float autocvar_g_balance_hagar_secondary_lifetime_rand;
float autocvar_g_balance_hagar_secondary_radius;
float autocvar_g_balance_hagar_secondary_refire;
+float autocvar_g_balance_hagar_secondary_speed;
+float autocvar_g_balance_hagar_secondary_spread;
float autocvar_g_balance_hagar_reload_ammo;
float autocvar_g_balance_hagar_reload_time;
float autocvar_g_balance_health_limit;
}
bufstr_set(bot.bot_cmdqueuebuf, bot.bot_cmdqueuebuf_end, cmdstring);
+
+ // if the command was a "sound" command, precache the sound NOW
+ // this prevents lagging!
+ {
+ float sp;
+ string parm;
+ string cmdstr;
+
+ sp = strstrofs(cmdstr, " ", 0);
+ if(sp < 0)
+ {
+ parm = "";
+ }
+ else
+ {
+ parm = substring(cmdstr, sp + 1, -1);
+ cmdstr = substring(cmdstr, 0, sp);
+ }
+ if(cmdstr == "sound")
+ precache_sound(cmdstr);
+ }
+
bot.bot_cmdqueuebuf_end += 1;
}
#define BOT_CMD_BARRIER 20
#define BOT_CMD_CONSOLE 21
#define BOT_CMD_SOUND 22
-#define BOT_CMD_WHILE 23 // TODO: Not implemented yet
-#define BOT_CMD_WEND 24 // TODO: Not implemented yet
-#define BOT_CMD_CHASE 25 // TODO: Not implemented yet
+#define BOT_CMD_DEBUG_ASSERT_CANFIRE 23
+#define BOT_CMD_WHILE 24 // TODO: Not implemented yet
+#define BOT_CMD_WEND 25 // TODO: Not implemented yet
+#define BOT_CMD_CHASE 26 // TODO: Not implemented yet
-#define BOT_CMD_COUNTER 23 // Update this value if you add/remove a command
+#define BOT_CMD_COUNTER 24 // Update this value if you add/remove a command
// NOTE: Following commands should be implemented on the bot ai
// If a new command should be handled by the target ai(s) please declare it here
bot_cmd_string[BOT_CMD_SOUND] = "sound";
bot_cmd_parm_type[BOT_CMD_SOUND] = BOT_CMD_PARAMETER_STRING;
+ bot_cmd_string[BOT_CMD_DEBUG_ASSERT_CANFIRE] = "debug_assert_canfire";
+ bot_cmd_parm_type[BOT_CMD_DEBUG_ASSERT_CANFIRE] = BOT_CMD_PARAMETER_FLOAT;
+
bot_cmds_initialized = TRUE;
}
case BOT_CMD_SOUND:
print("play sound file at bot location");
break;
+ case BOT_CMD_DEBUG_ASSERT_CANFIRE:
+ print("verify the state of the weapon entity");
+ break;
default:
print("This command has no description yet.");
break;
return CMD_STATUS_FINISHED;
}
+.entity tuba_note;
+float bot_cmd_debug_assert_canfire()
+{
+ float f;
+ f = bot_cmd.bot_cmd_parm_float;
+
+ if(self.weaponentity.state != WS_READY)
+ {
+ if(f)
+ {
+ self.colormod = '0 8 8';
+ print("Bot wants to fire, inhibited by weaponentity state\n");
+ }
+ }
+ else if(ATTACK_FINISHED(self) > time)
+ {
+ if(f)
+ {
+ self.colormod = '8 0 8';
+ print("Bot wants to fire, inhibited by ATTACK_FINISHED\n");
+ }
+ }
+ else if(self.tuba_note)
+ {
+ if(f)
+ {
+ self.colormod = '8 0 0';
+ print("Bot wants to fire, bot still has an active tuba note\n");
+ }
+ }
+ else
+ {
+ if(!f)
+ {
+ self.colormod = '8 8 0';
+ print("Bot thinks it has fired, but apparently did not\n");
+ }
+ }
+
+ return CMD_STATUS_FINISHED;
+}
+
//
void bot_command_executed(float rm)
{
local float status, ispressingkey;
- if(self.deadflag!=DEAD_NO)
- return 0;
-
// Find command
bot_setcurrentcommand();
+ // if we have no bot command, better return
+ // old logic kept pressing previously pressed keys, but that has problems
+ // (namely, it means you cannot make a bot "normal" ever again)
+ // to keep a bot walking for a while, use the "wait" bot command
+ if(bot_cmd == world)
+ return FALSE;
+
// Ignore all commands except continue when the bot is paused
if(self.bot_exec_status & BOT_EXEC_STATUS_PAUSED)
if(bot_cmd.bot_cmd_type!=BOT_CMD_CONTINUE)
// Keep pressing keys raised by the "presskey" command
ispressingkey = !!bot_presskeys();
- if(bot_cmd==world)
- return ispressingkey;
-
// Handle conditions
if not(bot_cmd.bot_cmd_type==BOT_CMD_FI||bot_cmd.bot_cmd_type==BOT_CMD_ELSE)
if(self.bot_cmd_condition_status & CMD_CONDITION_TRUE && self.bot_cmd_condition_status & CMD_CONDITION_FALSE_BLOCK)
case BOT_CMD_SOUND:
status = bot_cmd_sound();
break;
+ case BOT_CMD_DEBUG_ASSERT_CANFIRE:
+ status = bot_cmd_debug_assert_canfire();
+ break;
default:
print(strcat("ERROR: Invalid command on queue with id '",ftos(bot_cmd.bot_cmd_type),"'\n"));
return 0;
self.model = "";
self.modelindex = 0;
self.weapon = 0;
+ self.weaponname = "";
self.switchingweapon = 0;
self.weaponmodel = "";
self.weaponentity = world;
if(clienttype(self) == CLIENTTYPE_BOT && autocvar_g_botclip_collisions)
self.dphitcontentsmask |= DPCONTENTS_BOTCLIP;
self.frags = FRAGS_PLAYER;
- if(independent_players)
+ if(INDEPENDENT_PLAYERS)
MAKE_INDEPENDENT_PLAYER(self);
self.flags = FL_CLIENT;
self.takedamage = DAMAGE_AIM;
self.killcount = 0;
}
- self.cnt = WEP_LASER;
-
CL_SpawnWeaponentity();
self.alpha = default_player_alpha;
self.colormod = '1 1 1' * autocvar_g_player_brightness;
MUTATOR_CALLHOOK(PlayerSpawn);
self.switchweapon = w_getbestweapon(self);
- self.cnt = self.switchweapon;
+ self.cnt = -1; // W_LastWeapon will not complain
self.weapon = 0;
+ self.weaponname = "";
self.switchingweapon = 0;
if(!self.alivetime)
}
}
+float clientkilltime;
void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 = spec
{
float killtime;
+ float starttime;
entity e;
if (gameover)
}
else
{
+ starttime = max(time, clientkilltime);
+
self.killindicator = spawn();
self.killindicator.owner = self;
self.killindicator.scale = 0.5;
setattachment(self.killindicator, self, "");
setorigin(self.killindicator, '0 0 52');
self.killindicator.think = KillIndicator_Think;
- self.killindicator.nextthink = time + (self.lip) * 0.05;
+ self.killindicator.nextthink = starttime + (self.lip) * 0.05;
+ clientkilltime = max(clientkilltime, self.killindicator.nextthink + 0.05);
self.killindicator.cnt = ceil(killtime);
self.killindicator.count = bound(0, ceil(killtime), 10);
//sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n"));
setattachment(e.killindicator, e, "");
setorigin(e.killindicator, '0 0 52');
e.killindicator.think = KillIndicator_Think;
- e.killindicator.nextthink = time + (e.lip) * 0.05;
+ e.killindicator.nextthink = starttime + (e.lip) * 0.05;
+ clientkilltime = max(clientkilltime, e.killindicator.nextthink + 0.05);
e.killindicator.cnt = ceil(killtime);
}
self.lip = 0;
W_NextWeapon (0);
break;
case 11:
- W_SwitchWeapon (self.cnt); // previously used
+ W_LastWeapon();
break;
case 12:
W_PreviousWeapon (0);
W_CycleWeapon(self.cvar_cl_weaponpriority, +1);
}
+// previously used if exists and has ammo, (second) best otherwise
+void W_LastWeapon()
+{
+ if(client_hasweapon(self, self.cnt, TRUE, FALSE))
+ W_SwitchWeapon(self.cnt);
+ else
+ W_SwitchToOtherWeapon(self);
+}
+
float w_getbestweapon(entity e)
{
return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE);
c = c + 1;
if(wb && ((self.weapons & wb) == 0))
{
- W_SwitchWeapon_Force(self, w_getbestweapon(self));
+ if(self.weapon == self.switchweapon)
+ W_SwitchWeapon_Force(self, w_getbestweapon(self));
wb = 0;
}
.vector weapon_morph4origin;
.vector weapon_morph4angles;
.float weapon_morph4time;
-.string weaponname;
#define QCWEAPONANIMATION_ORIGIN(e) ((weapon_offset_x + e.view_ofs_x) * v_forward - (weapon_offset_y + e.view_ofs_y) * v_right + (weapon_offset_z + e.view_ofs_z) * v_up + weapon_adjust)
/*
self.weaponentity.model = "";
return;
}
- if (self.cnt != self.owner.weapon || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
+ if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
{
- self.cnt = self.owner.weapon;
+ self.weaponname = self.owner.weaponname;
self.dmg = self.owner.modelindex;
self.deadflag = self.owner.deadflag;
self.model = "";
return;
}
- if (self.cnt != self.owner.weapon || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
+ if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
{
- self.cnt = self.owner.weapon;
+ self.weaponname = self.owner.weaponname;
self.dmg = self.owner.modelindex;
self.deadflag = self.owner.deadflag;
if (self.owner.weaponname != "")
//.float weapon; // current weapon
.float switchweapon; // weapon requested to switch to
.float switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible)
+.string weaponname; // name of .weapon
.float autoswitch;
float weapon_action(float wpn, float wrequest);
.float version_mismatch;
float independent_players;
+#define INDEPENDENT_PLAYERS (autocvar__independent_players ? (autocvar__independent_players > 0) : independent_players)
#define IS_INDEPENDENT_PLAYER(e) ((e).solid == SOLID_TRIGGER)
#define MAKE_INDEPENDENT_PLAYER(e) (((e).solid = SOLID_TRIGGER) + ((e).frags = FRAGS_PLAYER_NONSOLID))
// we're using + here instead of , because fteqcc sucks
}
else
{
+ /*
+ skill based bot damage? gtfo. (tZork)
if (targ.classname == "player")
if (attacker.classname == "player")
if (!targ.isbot)
if (attacker.isbot)
damage = damage * bound(0.1, (skill + 5) * 0.1, 1);
-
+ */
+
// nullify damage if teamplay is on
if(deathtype != DEATH_TELEFRAG)
if(attacker.classname == "player")
if((arena_roundbased && time < warmup) || (time < game_starttime))
return;
- if(self.freezetag_frozen)
- return;
+ if(self.freezetag_frozen)
+ return;
+
+ if(self.vehicle)
+ return;
makevectors(self.v_angle);
if(score_enabled)
ScoreInfo_SetLabel_TeamScore (ST_SCORE, "score", stprio);
- if not(independent_players)
+ if not(INDEPENDENT_PLAYERS)
ScoreInfo_SetLabel_PlayerScore(SP_KILLS, "kills", 0);
ScoreInfo_SetLabel_PlayerScore(SP_DEATHS, "deaths", SFL_LOWER_IS_BETTER);
- if not(independent_players)
+ if not(INDEPENDENT_PLAYERS)
ScoreInfo_SetLabel_PlayerScore(SP_SUICIDES, "suicides", SFL_LOWER_IS_BETTER);
if(score_enabled)
if(self.team)
if(self.team != other.team)
return;
+
+ RemoveGrapplingHook(other);
self.vehicle_ammo1 = 0;
self.vehicle_ammo2 = 0;
// time to release the rockets we've loaded
local entity missile;
- local float counter, shots;
+ local float counter, shots, spread_pershot;
local vector s;
vector forward, right, up;
setorigin (missile, w_shotorg);
setsize(missile, '0 0 0', '0 0 0');
missile.movetype = MOVETYPE_FLY;
-
+
+ // per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar)
+ spread_pershot = ((shots - 1) / (autocvar_g_balance_hagar_secondary_load_max - 1));
+ spread_pershot = (1 - (spread_pershot * autocvar_g_balance_hagar_secondary_load_spread_bias));
+ spread_pershot = (autocvar_g_balance_hagar_secondary_spread * spread_pershot * g_weaponspreadfactor);
+
+ // pattern spread calculation
s = '0 0 0';
if (counter == 0)
s = '0 0 0';
s_y = v_forward_x;
s_z = v_forward_y;
}
- s = s * cvar("g_balance_hagar_secondary_spread") * g_weaponspreadfactor;
- W_SetupProjectileVelocityEx(missile, w_shotdir + right * s_y + up * s_z, v_up, cvar("g_balance_hagar_secondary_speed"), 0, 0, 0, FALSE);
+ s = s * autocvar_g_balance_hagar_secondary_load_spread * g_weaponspreadfactor;
+
+ W_SetupProjectileVelocityEx(missile, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_hagar_secondary_speed, 0, 0, spread_pershot, FALSE);
missile.angles = vectoangles (missile.velocity);
missile.flags = FL_PROJECTILE;
#else
#ifdef SVQC
void(float imp) W_SwitchWeapon;
+void() W_LastWeapon;
void W_Laser_Touch (void)
{
else
{
if(self.switchweapon == WEP_LASER) // don't do this if already switching
- W_SwitchWeapon (self.cnt);
+ W_LastWeapon();
}
}
}
vector org2;
entity e;
+ PROJECTILE_TOUCH;
+
dir = normalize (self.realowner.origin - self.origin);
org2 = findbetterlocation (self.origin, 8);
weapon_setup(WEP_TUBA);
self.current_ammo = ammo_none;
}
+ else if (req == WR_RELOAD)
+ {
+ // TODO switch to alternate instruments :)
+ }
else if (req == WR_CHECKAMMO1)
return TRUE; // TODO use fuel?
else if (req == WR_CHECKAMMO2)
#ifdef SVQC
// leilei's fancy muzzleflash stuff
-void UZI_Flash_Go()
-{
+void UZI_Flash_Go()
+{
self.frame = self.frame + 2;
self.scale = self.scale * 0.5;
self.alpha = self.alpha - 0.25;
self.realowner.muzzle_flash = world;
return;
}
-
+
}
void UziFlash()
-{
+{
if (self.muzzle_flash == world)
- self.muzzle_flash = spawn();
-
+ self.muzzle_flash = spawn();
+
// muzzle flash for 1st person view
setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below
-
+
self.muzzle_flash.scale = 0.75;
self.muzzle_flash.think = UZI_Flash_Go;
self.muzzle_flash.nextthink = time + 0.02;
{
float uzi_spread;
- W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo);
-
- if (self.BUTTON_ATCK)
- weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto);
- else
+ if (!self.BUTTON_ATCK)
{
- ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor();
- weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, w_ready);
+ w_ready();
return;
}
w_ready();
return;
}
-
+
+ W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo);
+
W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_balance_uzi_sustained_damage);
if (!g_norecoil)
{
self.punchangle_x = random () - 0.5;
self.punchangle_y = random () - 0.5;
}
-
+
uzi_spread = bound(autocvar_g_balance_uzi_spread_min, autocvar_g_balance_uzi_spread_min + (autocvar_g_balance_uzi_spread_add * self.misc_bulletcounter), autocvar_g_balance_uzi_spread_max);
fireBallisticBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
endFireBallisticBullet();
-
+
self.misc_bulletcounter = self.misc_bulletcounter + 1;
-
+
pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
UziFlash();
W_AttachToShotorg(self.muzzle_flash, '5 0 0');
-
+
if (autocvar_g_casings >= 2) // casing code
SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+
+ ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor();
+ weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto);
}
void uzi_mode1_fire_burst()
self.punchangle_x = random () - 0.5;
self.punchangle_y = random () - 0.5;
}
-
+
fireBallisticBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_speed, 5, autocvar_g_balance_uzi_sustained_damage, 0, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0, 1, autocvar_g_balance_uzi_bulletconstant);
endFireBallisticBullet();
-
-
+
+
pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
UziFlash();
W_AttachToShotorg(self.muzzle_flash, '5 0 0');
-
+
if (autocvar_g_casings >= 2) // casing code
SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
{
weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_refire, uzi_mode1_fire_burst);
}
-
+
}
void spawnfunc_weapon_machinegun(); // defined in t_items.qc
{
if (self.BUTTON_ATCK)
if (weapon_prepareattack(0, 0))
- {
+ {
self.misc_bulletcounter = 0;
uzi_mode1_fire_auto();
}
-
+
if(self.BUTTON_ATCK2)
if(weapon_prepareattack(1, 0))
{
if (!weapon_action(self.weapon, WR_CHECKAMMO2))
+ if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
{
W_SwitchWeapon_Force(self, w_getbestweapon(self));
w_ready();
}
else
{
-
+
if (self.BUTTON_ATCK)
if (weapon_prepareattack(0, 0))
{