]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into mirceakitsune/universal_reload_system
authorMircea Kitsune <sonichedgehog_hyperblast00@yahoo.com>
Sun, 23 Jan 2011 16:01:49 +0000 (18:01 +0200)
committerMircea Kitsune <sonichedgehog_hyperblast00@yahoo.com>
Sun, 23 Jan 2011 16:01:49 +0000 (18:01 +0200)
32 files changed:
balanceXonotic.cfg
qcsrc/client/Defs.qc
qcsrc/client/Main.qc
qcsrc/client/View.qc
qcsrc/common/constants.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/havocbot/havocbot.qc
qcsrc/server/cl_client.qc
qcsrc/server/cl_weapons.qc
qcsrc/server/cl_weaponsystem.qc
qcsrc/server/defs.qh
qcsrc/server/g_world.qc
qcsrc/server/w_crylink.qc
qcsrc/server/w_electro.qc
qcsrc/server/w_fireball.qc
qcsrc/server/w_grenadelauncher.qc
qcsrc/server/w_hagar.qc
qcsrc/server/w_hlac.qc
qcsrc/server/w_hook.qc
qcsrc/server/w_laser.qc
qcsrc/server/w_minelayer.qc
qcsrc/server/w_minstanex.qc
qcsrc/server/w_nex.qc
qcsrc/server/w_porto.qc
qcsrc/server/w_rocketlauncher.qc
qcsrc/server/w_seeker.qc
qcsrc/server/w_shotgun.qc
qcsrc/server/w_sniperrifle.qc
qcsrc/server/w_tuba.qc
qcsrc/server/w_uzi.qc
sound/weapons/campingrifle_reload.ogg [deleted file]
sound/weapons/reload.ogg [new file with mode: 0644]

index 53f98d57b2fa3f717c37e64576c1de379e0d1f1b..03712f87075052f4904d9d474fcbc5e07069b67d 100644 (file)
@@ -243,6 +243,8 @@ set g_balance_laser_secondary_gauntlet 1
 set g_balance_laser_secondary_force_zscale 1.25
 set g_balance_laser_secondary_force_velocitybias 0
 set g_balance_laser_secondary_force_other_scale 0
+set g_balance_laser_reload_ammo 6
+set g_balance_laser_reload_time 2
 // }}}
 // {{{ shotgun
 set g_balance_shotgun_primary_bullets 18
@@ -263,6 +265,8 @@ set g_balance_shotgun_secondary_damage 110
 set g_balance_shotgun_secondary_force 150
 set g_balance_shotgun_secondary_refire 1.1
 set g_balance_shotgun_secondary_animtime 1
+set g_balance_shotgun_reload_ammo 5
+set g_balance_shotgun_reload_time 2
 // }}}
 // {{{ uzi
 set g_balance_uzi_mode 1                               // Activates varible spread for sustained & burst mode secondary
@@ -294,6 +298,9 @@ set g_balance_uzi_sustained_ammo 1
 
 set g_balance_uzi_speed 18000
 set g_balance_uzi_bulletconstant 115 // 13.1qu
+
+set g_balance_uzi_reload_ammo 30
+set g_balance_uzi_reload_time 2
 // }}}
 // {{{ mortar
 set g_balance_grenadelauncher_primary_type 0
@@ -334,6 +341,9 @@ set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
 
 set g_balance_grenadelauncher_bouncefactor 0.5
 set g_balance_grenadelauncher_bouncestop 0.12
+
+set g_balance_grenadelauncher_reload_ammo 12
+set g_balance_grenadelauncher_reload_time 2
 // }}}
 // {{{ minelayer
 set g_balance_minelayer_damage 42
@@ -356,6 +366,8 @@ set g_balance_minelayer_remote_damage 45
 set g_balance_minelayer_remote_edgedamage 40
 set g_balance_minelayer_remote_radius 200
 set g_balance_minelayer_remote_force 300
+set g_balance_minelayer_reload_ammo 15
+set g_balance_minelayer_reload_time 2
 // }}}
 // {{{ electro
 set g_balance_electro_lightning 1
@@ -399,6 +411,8 @@ set g_balance_electro_combo_force 80
 set g_balance_electro_combo_radius 250
 set g_balance_electro_combo_comboradius 0
 set g_balance_electro_combo_speed 400
+set g_balance_electro_reload_ammo 20
+set g_balance_electro_reload_time 2
 // }}}
 // {{{ crylink
 set g_balance_crylink_primary_damage 10
@@ -455,6 +469,9 @@ set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to
 set g_balance_crylink_secondary_middle_fadetime 5
 set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000
 set g_balance_crylink_secondary_line_fadetime 0.25
+
+set g_balance_crylink_reload_ammo 10
+set g_balance_crylink_reload_time 2
 // }}}
 // {{{ nex
 set g_balance_nex_primary_damage 90
@@ -495,11 +512,17 @@ set g_balance_nex_charge_shot_multiplier 0
 set g_balance_nex_charge_velocity_rate 0
 set g_balance_nex_charge_minspeed 600
 set g_balance_nex_charge_maxspeed 1000
+
+set g_balance_nex_reload_ammo 25
+set g_balance_nex_reload_time 2
 // }}}
 // {{{ minstanex
 set g_balance_minstanex_refire 1
 set g_balance_minstanex_animtime 0.50
 set g_balance_minstanex_ammo 10
+set g_balance_minstanex_laser_ammo 5
+set g_balance_minstanex_reload_ammo 50
+set g_balance_minstanex_reload_time 2
 // }}}
 // {{{ hagar
 set g_balance_hagar_primary_damage 14
@@ -522,6 +545,8 @@ set g_balance_hagar_secondary_lifetime_min 5
 set g_balance_hagar_secondary_lifetime_rand 0
 set g_balance_hagar_secondary_refire 0.12
 set g_balance_hagar_secondary_ammo 1
+set g_balance_hagar_reload_ammo 25
+set g_balance_hagar_reload_time 2
 // }}}
 // {{{ rocketlauncher
 set g_balance_rocketlauncher_damage 82
@@ -547,6 +572,8 @@ set g_balance_rocketlauncher_remote_damage 60
 set g_balance_rocketlauncher_remote_edgedamage 20
 set g_balance_rocketlauncher_remote_radius 120
 set g_balance_rocketlauncher_remote_force 350
+set g_balance_rocketlauncher_reload_ammo 25
+set g_balance_rocketlauncher_reload_time 2
 // }}}
 // {{{ porto
 set g_balance_porto_primary_refire 1.5
@@ -608,11 +635,11 @@ set g_balance_hlac_secondary_refire 0.8
 set g_balance_hlac_secondary_animtime 0.4
 set g_balance_hlac_secondary_ammo 4
 set g_balance_hlac_secondary_shots 6
+
+set g_balance_hlac_reload_ammo 20
+set g_balance_hlac_reload_time 2
 // }}}
 // {{{ sniperrifle
-set g_balance_sniperrifle_magazinecapacity 8 // make it pretty much useless in close combat
-set g_balance_sniperrifle_reloadtime 2 // matches reload anim
-set g_balance_sniperrifle_auto_reload_on_switch 0
 set g_balance_sniperrifle_bursttime 0
 set g_balance_sniperrifle_primary_tracer 1
 set g_balance_sniperrifle_primary_damage 60
@@ -642,6 +669,8 @@ set g_balance_sniperrifle_secondary_ammo 10
 set g_balance_sniperrifle_secondary_bulletconstant 110 // 15.5qu
 set g_balance_sniperrifle_secondary_burstcost 0
 set g_balance_sniperrifle_secondary_bullethail 0 // empty magazine on shot
+set g_balance_sniperrifle_reload_ammo 60
+set g_balance_sniperrifle_reload_time 2
 // }}}
 // {{{ tuba
 set g_balance_tuba_refire 0.05
@@ -691,6 +720,8 @@ set g_balance_fireball_secondary_speed 900
 set g_balance_fireball_secondary_speed_up 100
 set g_balance_fireball_secondary_speed_z 0
 set g_balance_fireball_secondary_spread 0
+set g_balance_fireball_reload_ammo 60
+set g_balance_fireball_reload_time 2
 // }}}
 // {{{ seeker
 set g_balance_seeker_flac_ammo 0.5
@@ -741,4 +772,6 @@ set g_balance_seeker_tag_lifetime 15
 set g_balance_seeker_tag_refire 0.7
 set g_balance_seeker_tag_speed 5000
 set g_balance_seeker_tag_spread 0
+set g_balance_seeker_reload_ammo 15
+set g_balance_seeker_reload_time 2
 // End new seeker
index 3d15295942e21b6cefc40c52386f5f7ea3e8d6f0..eef29cdd551bd1fc3a3db1e1f402be9f8929feb3 100644 (file)
@@ -261,8 +261,6 @@ vector w_org, w_backoff;
 float sniperrifle_scope;
 float nex_scope;
 
-float cr_maxbullets;
-
 float bgmtime;
 
 string weaponorder_byimpulse;
index f87538a9eebf76e80d1483d714b88e9a2ca1c378..710c7f7433a7b687a3dab1fa027c675e8795a005 100644 (file)
@@ -1092,8 +1092,6 @@ void Ent_Init()
 
        serverflags = ReadByte();
 
-       cr_maxbullets = ReadByte();
-
        g_trueaim_minrange = ReadCoord();
 
        if(!postinit)
index d3bbf79cb73bd16705cc5697ae6073185079837a..696ec575995fb7d9b3cafa7cd5144fccce627b9f 100644 (file)
@@ -850,7 +850,7 @@ void CSQC_UpdateView(float w, float h)
 
                        // TrueAim check
                        float shottype;
-                       float bullets, ring_scale;
+                       float weapon_clipload, weapon_clipsize, ring_scale;
                        // wcross_origin = '0.5 0 0' * vid_conwidth + '0 0.5 0' * vid_conheight;
                        wcross_origin = project_3d_to_2d(view_origin + MAX_SHOT_DISTANCE * view_forward);
                        wcross_origin_z = 0;
@@ -995,16 +995,17 @@ void CSQC_UpdateView(float w, float h)
                        if(nex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
                                nex_charge_movingavg = nex_charge;
 
-                       // ring around crosshair representing bullets left in camping rifle clip
-                       if (activeweapon == WEP_SNIPERRIFLE && cr_maxbullets)
+                       // ring around crosshair representing bullets left in weapon clip
+                       weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
+                       if (weapon_clipload)
                        {
-                               bullets = getstati(STAT_BULLETS_LOADED);
-                               f = bound(0, bullets / cr_maxbullets, 1);
+                               weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
+                               f = bound(0, weapon_clipload / weapon_clipsize, 1);
 
                                a = autocvar_crosshair_ring_sniperrifle_alpha;
                                DrawCircleClippedPic(wcross_origin, wcross_size_x * ring_scale, "gfx/crosshair_ring.tga", f, wcross_color, wcross_alpha * a, DRAWFLAG_ADDITIVE);
                        }
-                       else if (activeweapon == WEP_NEX && nex_charge) // ring around crosshair representing velocity-dependent damage for the nex
+                       if (activeweapon == WEP_NEX && nex_charge) // ring around crosshair representing velocity-dependent damage for the nex
                        {
                                if(nex_chargepool || use_nex_chargepool)
                                {
index 90376b5b96bf9691c69ed98057e403282e7cec3c..da8cfaac1890db4b7d57dd4f6f548e15ed185248 100644 (file)
@@ -62,7 +62,6 @@ const float TE_CSQC_TARGET_MUSIC = 111;
 const float TE_CSQC_NOTIFY = 112;
 const float TE_CSQC_WEAPONCOMPLAIN = 113;
 const float TE_CSQC_NEX_SCOPE = 116;
-const float TE_CSQC_CR_MAXBULLETS = 117;
 
 const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
 const float RACE_NET_CHECKPOINT_CLEAR = 1;
@@ -308,11 +307,12 @@ const float STAT_FUEL = 44;
 const float STAT_NB_METERSTART = 45;
 const float STAT_SHOTORG = 46; // compressShotOrigin
 const float STAT_LEADLIMIT = 47;
-const float STAT_BULLETS_LOADED = 48;
-const float STAT_NEX_CHARGE = 49;
-const float STAT_LAST_PICKUP = 50;
-const float STAT_HUD = 51;
-const float STAT_NEX_CHARGEPOOL = 52;
+const float STAT_WEAPON_CLIPLOAD = 48;
+const float STAT_WEAPON_CLIPSIZE = 49;
+const float STAT_NEX_CHARGE = 50;
+const float STAT_LAST_PICKUP = 51;
+const float STAT_HUD = 52;
+const float STAT_NEX_CHARGEPOOL = 53;
 
 // see DP source, quakedef.h
 const float STAT_MOVEVARS_AIRSPEEDLIMIT_NONQW = 222;
@@ -621,6 +621,7 @@ float WR_KILLMESSAGE    = 8; // (CSQC) sets w_deathtypestring or leaves it alone
 float WR_RELOAD         = 9; // (SVQC) does not need to do anything
 float WR_RESETPLAYER    = 10; // (SVQC) does not need to do anything
 float WR_IMPACTEFFECT  = 11; // (CSQC) impact effect
+float WR_SWITCHABLE    = 12; // (CSQC) impact effect
 
 
 float HUD_PANEL_WEAPONS                = 0;
index e791e71440ad7e890abb8d57359f7760f1349525..439060433c8c97c77aed3391e5501a67a9f02b08 100644 (file)
@@ -82,9 +82,7 @@ float autocvar_g_balance_armor_rot;
 float autocvar_g_balance_armor_rotlinear;
 float autocvar_g_balance_armor_rotstable;
 float autocvar_g_balance_armor_start;
-float autocvar_g_balance_sniperrifle_auto_reload_on_switch;
 float autocvar_g_balance_sniperrifle_bursttime;
-float autocvar_g_balance_sniperrifle_magazinecapacity;
 float autocvar_g_balance_sniperrifle_primary_ammo;
 float autocvar_g_balance_sniperrifle_primary_animtime;
 float autocvar_g_balance_sniperrifle_primary_bulletconstant;
@@ -98,7 +96,6 @@ float autocvar_g_balance_sniperrifle_primary_refire;
 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_reloadtime;
 float autocvar_g_balance_sniperrifle_secondary;
 float autocvar_g_balance_sniperrifle_secondary_ammo;
 float autocvar_g_balance_sniperrifle_secondary_animtime;
@@ -114,6 +111,8 @@ float autocvar_g_balance_sniperrifle_secondary_refire;
 float autocvar_g_balance_sniperrifle_secondary_speed;
 float autocvar_g_balance_sniperrifle_secondary_spread;
 float autocvar_g_balance_sniperrifle_secondary_tracer;
+float autocvar_g_balance_sniperrifle_reload_ammo;
+float autocvar_g_balance_sniperrifle_reload_time;
 float autocvar_g_balance_cloaked_alpha;
 float autocvar_g_balance_crylink_primary_ammo;
 float autocvar_g_balance_crylink_primary_animtime;
@@ -166,6 +165,8 @@ float autocvar_g_balance_crylink_secondary_refire;
 float autocvar_g_balance_crylink_secondary_shots;
 float autocvar_g_balance_crylink_secondary_speed;
 float autocvar_g_balance_crylink_secondary_spread;
+float autocvar_g_balance_crylink_reload_ammo;
+float autocvar_g_balance_crylink_reload_time;
 float autocvar_g_balance_ctf_damageforcescale;
 float autocvar_g_balance_ctf_delay_collect;
 float autocvar_g_balance_curse_empathy_minhealth;
@@ -215,6 +216,8 @@ float autocvar_g_balance_electro_secondary_radius;
 float autocvar_g_balance_electro_secondary_refire;
 float autocvar_g_balance_electro_secondary_refire2;
 float autocvar_g_balance_electro_secondary_speed;
+float autocvar_g_balance_electro_reload_ammo;
+float autocvar_g_balance_electro_reload_time;
 float autocvar_g_balance_falldamage_deadminspeed;
 float autocvar_g_balance_falldamage_factor;
 float autocvar_g_balance_falldamage_maxdamage;
@@ -251,6 +254,8 @@ float autocvar_g_balance_fireball_secondary_lifetime;
 float autocvar_g_balance_fireball_secondary_refire;
 float autocvar_g_balance_fireball_secondary_speed;
 float autocvar_g_balance_fireball_secondary_speed_up;
+float autocvar_g_balance_fireball_reload_ammo;
+float autocvar_g_balance_fireball_reload_time;
 float autocvar_g_balance_firetransfer_damage;
 float autocvar_g_balance_firetransfer_time;
 float autocvar_g_balance_fuel_limit;
@@ -299,6 +304,8 @@ float autocvar_g_balance_grenadelauncher_secondary_refire;
 float autocvar_g_balance_grenadelauncher_secondary_speed;
 float autocvar_g_balance_grenadelauncher_secondary_speed_up;
 float autocvar_g_balance_grenadelauncher_secondary_type;
+float autocvar_g_balance_grenadelauncher_reload_ammo;
+float autocvar_g_balance_grenadelauncher_reload_time;
 float autocvar_g_balance_hagar_primary_ammo;
 float autocvar_g_balance_hagar_primary_damage;
 float autocvar_g_balance_hagar_primary_edgedamage;
@@ -316,6 +323,8 @@ float autocvar_g_balance_hagar_secondary_lifetime_min;
 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_reload_ammo;
+float autocvar_g_balance_hagar_reload_time;
 float autocvar_g_balance_health_limit;
 float autocvar_g_balance_health_regen;
 float autocvar_g_balance_health_regenlinear;
@@ -350,6 +359,8 @@ float autocvar_g_balance_hlac_secondary_shots;
 float autocvar_g_balance_hlac_secondary_speed;
 float autocvar_g_balance_hlac_secondary_spread;
 float autocvar_g_balance_hlac_secondary_spread_crouchmod;
+float autocvar_g_balance_hlac_reload_ammo;
+float autocvar_g_balance_hlac_reload_time;
 float autocvar_g_balance_hook_primary_animtime;
 float autocvar_g_balance_hook_primary_fuel;
 float autocvar_g_balance_hook_primary_hooked_fuel;
@@ -410,6 +421,8 @@ float autocvar_g_balance_laser_secondary_force_zscale;
 float autocvar_g_balance_laser_secondary_lifetime;
 float autocvar_g_balance_laser_secondary_radius;
 float autocvar_g_balance_laser_secondary_speed;
+float autocvar_g_balance_laser_reload_ammo;
+float autocvar_g_balance_laser_reload_time;
 float autocvar_g_balance_minelayer_ammo;
 float autocvar_g_balance_minelayer_animtime;
 float autocvar_g_balance_minelayer_damage;
@@ -430,9 +443,14 @@ float autocvar_g_balance_minelayer_remote_force;
 float autocvar_g_balance_minelayer_remote_radius;
 float autocvar_g_balance_minelayer_speed;
 float autocvar_g_balance_minelayer_time;
+float autocvar_g_balance_minelayer_reload_ammo;
+float autocvar_g_balance_minelayer_reload_time;
 float autocvar_g_balance_minstanex_ammo;
+float autocvar_g_balance_minstanex_laser_ammo;
 float autocvar_g_balance_minstanex_animtime;
 float autocvar_g_balance_minstanex_refire;
+float autocvar_g_balance_minstanex_reload_ammo;
+float autocvar_g_balance_minstanex_reload_time;
 float autocvar_g_balance_nex_charge;
 float autocvar_g_balance_nex_charge_limit;
 float autocvar_g_balance_nex_charge_maxspeed;
@@ -469,6 +487,8 @@ float autocvar_g_balance_nex_secondary_damagefalloff_maxdist;
 float autocvar_g_balance_nex_secondary_damagefalloff_mindist;
 float autocvar_g_balance_nex_secondary_force;
 float autocvar_g_balance_nex_secondary_refire;
+float autocvar_g_balance_nex_reload_ammo;
+float autocvar_g_balance_nex_reload_time;
 float autocvar_g_balance_nexball_primary_animtime;
 float autocvar_g_balance_nexball_primary_refire;
 float autocvar_g_balance_nexball_primary_speed;
@@ -535,6 +555,8 @@ float autocvar_g_balance_rocketlauncher_remote_radius;
 float autocvar_g_balance_rocketlauncher_speed;
 float autocvar_g_balance_rocketlauncher_speedaccel;
 float autocvar_g_balance_rocketlauncher_speedstart;
+float autocvar_g_balance_rocketlauncher_reload_ammo;
+float autocvar_g_balance_rocketlauncher_reload_time;
 float autocvar_g_balance_rune_defense_combo_takedamage;
 float autocvar_g_balance_rune_defense_takedamage;
 float autocvar_g_balance_rune_regen_combo_hpmod;
@@ -592,6 +614,8 @@ float autocvar_g_balance_seeker_tag_health;
 float autocvar_g_balance_seeker_tag_lifetime;
 float autocvar_g_balance_seeker_tag_refire;
 float autocvar_g_balance_seeker_tag_speed;
+float autocvar_g_balance_seeker_reload_ammo;
+float autocvar_g_balance_seeker_reload_time;
 float autocvar_g_balance_selfdamagepercent;
 float autocvar_g_balance_shotgun_primary_ammo;
 float autocvar_g_balance_shotgun_primary_animtime;
@@ -611,6 +635,8 @@ float autocvar_g_balance_shotgun_secondary_melee_range;
 float autocvar_g_balance_shotgun_secondary_melee_swing;
 float autocvar_g_balance_shotgun_secondary_melee_time;
 float autocvar_g_balance_shotgun_secondary_refire;
+float autocvar_g_balance_shotgun_reload_ammo;
+float autocvar_g_balance_shotgun_reload_time;
 float autocvar_g_balance_teams;
 float autocvar_g_balance_teams_force;
 float autocvar_g_balance_teams_prevent_imbalance;
@@ -644,6 +670,8 @@ float autocvar_g_balance_uzi_sustained_damage;
 float autocvar_g_balance_uzi_sustained_force;
 float autocvar_g_balance_uzi_sustained_refire;
 float autocvar_g_balance_uzi_sustained_spread;
+float autocvar_g_balance_uzi_reload_ammo;
+float autocvar_g_balance_uzi_reload_time;
 float autocvar_g_balance_weaponswitchdelay;
 float autocvar_g_ballistics_density_corpse;
 float autocvar_g_ballistics_density_player;
index b7ee13b3721414edadc473d23dd3090b943ad7a3..f6a5d50a39f793191e0e4f918662fc03f9ff938a 100644 (file)
@@ -946,11 +946,6 @@ void havocbot_chooseweapon()
        if(i < 1)
                return;
 
-       // Workaround for rifle reloading (..)
-       if(self.weapon == WEP_SNIPERRIFLE)
-       if(i < autocvar_g_balance_sniperrifle_reloadtime + 1)
-               return;
-
        local float w;
        local float distance; distance=bound(10,vlen(self.origin-self.enemy.origin)-200,10000);
 
index 36c23473202d47d7f2e094103b0fccda9bfd3e5d..77d00be41913a82f817ef5036178dbb0aceaa254 100644 (file)
@@ -1065,8 +1065,6 @@ void PutClientInServer (void)
                self.cnt = self.switchweapon;
                self.weapon = 0;
 
-        self.wish_reload = 0;
-
                if(!self.alivetime)
                        self.alivetime = time;
        } else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) {
@@ -1109,7 +1107,6 @@ float ClientInit_SendEntity(entity to, float sf)
        WriteByte(MSG_ENTITY, autocvar_g_balance_nex_secondary); // client has to know if it should zoom or not
        WriteByte(MSG_ENTITY, autocvar_g_balance_sniperrifle_secondary); // client has to know if it should zoom or not
        WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not
-       WriteByte(MSG_ENTITY, autocvar_g_balance_sniperrifle_magazinecapacity); // rifle max bullets
        WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange);
        return TRUE;
 }
@@ -2341,6 +2338,8 @@ void SpectateCopy(entity spectatee) {
        self.ammo_nails = spectatee.ammo_nails;
        self.ammo_rockets = spectatee.ammo_rockets;
        self.ammo_fuel = spectatee.ammo_fuel;
+       self.clip_load = spectatee.clip_load;
+       self.clip_size = spectatee.clip_size;
        self.effects = spectatee.effects & EFMASK_CHEAP; // eat performance
        self.health = spectatee.health;
        self.impulse = 0;
@@ -2937,6 +2936,10 @@ void PlayerPreThink (void)
        }
 
        target_voicescript_next(self);
+
+       // if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
+       if(!self.weapon)
+               self.clip_load = self.clip_size = 0;
 }
 
 float isInvisibleString(string s)
index 864dd77fce788cc1696e7bbdee82ac3309748a89..6a28a1154d91ac9769ce54f0ea2f8b92176b5ef5 100644 (file)
@@ -1,6 +1,6 @@
 void W_Reload()
 {
-    self.wish_reload = 1;
+    weapon_action(self.weapon, WR_RELOAD);
 }
 
 // switch between weapons
index 057c5cb1dc767fde25d85b66a61ca8ee519cbf32..91450dd2b1ae6545a5d42471d03a7923dd7fdb5c 100644 (file)
@@ -1611,3 +1611,43 @@ void W_SetupProjectileVelocity(entity missile, float pSpeed, float spread)
 
 #define W_SETUPPROJECTILEVELOCITY_UP(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), cvar(#s "_speed_up"), cvar(#s "_speed_z"), cvar(#s "_spread"), FALSE)
 #define W_SETUPPROJECTILEVELOCITY(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), 0, 0, cvar(#s "_spread"), FALSE)
+
+.float reload_complain;
+float W_ReloadCheck(float ammo_amount, float ammo_shot)
+{
+       entity e;
+       e = get_weaponinfo(self.weapon);
+
+       // our weapon is fully loaded, no need to reload
+       if (self.clip_load >= cvar(strcat("g_balance_", e.netname, "_reload_ammo")))
+               return 0;
+
+       // no ammo, so nothing to load
+       if(!ammo_amount)
+       {
+               if(clienttype(self) == CLIENTTYPE_REAL && self.reload_complain < time)
+               {
+                       play2(self, "weapons/unavailable.wav");
+                       sprint(self, strcat("You don't have enough ammo to reload the ^2", W_Name(self.weapon), "\n"));
+                       self.reload_complain = time + 1;
+               }
+               // switch away if the loaded amount of ammo is not enough to keep using this weapon
+               if(self.clip_load < ammo_shot)
+               {
+                       self.clip_load = -1; // reload later
+                       W_SwitchToOtherWeapon(self);
+               }
+               return 0;
+       }
+
+       if (self.weaponentity)
+       {
+               if (self.weaponentity.wframe == WFRAME_RELOAD)
+                       return 0;
+
+               // allow switching away while reloading, but this will cause a new reload!
+               self.weaponentity.state = WS_READY;
+       }
+
+       return 1;
+}
\ No newline at end of file
index 970c86af429ecf3c4ef267ca4ef62b145e1afcad..ec82bf6530c0618434ed9004e92183112f6c0c64 100644 (file)
@@ -612,8 +612,9 @@ float client_cefc_accumulator;
 float client_cefc_accumulatortime;
 #endif
 
-.float sniperrifle_bulletcounter;
-.float wish_reload;
+.float clip_load;
+.float old_clip_load;
+.float clip_size;
 
 #define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_CORPSE; (e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE
 // when doing this, hagar can go through clones
index 67fb91fc2b91c45a64c57bcbb999c66bfea8c370..9888fa5d52a34ba00365003f32f4134c235542c4 100644 (file)
@@ -818,7 +818,8 @@ void spawnfunc_worldspawn (void)
        addstat(STAT_FUEL, AS_INT, ammo_fuel);
        addstat(STAT_SHOTORG, AS_INT, stat_shotorg);
        addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
-       addstat(STAT_BULLETS_LOADED, AS_INT, sniperrifle_bulletcounter);
+       addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load);
+       addstat(STAT_WEAPON_CLIPSIZE, AS_INT, clip_size);
        addstat(STAT_LAST_PICKUP, AS_FLOAT, last_pickup);
 
        addstat(STAT_NEX_CHARGE, AS_FLOAT, nex_charge);
index 8a3380eae4356b657f00f04e1a936d2eb67c7107..d45edbbed7bc58bc2962eb0cb9af48b186569936 100644 (file)
@@ -9,6 +9,61 @@ REGISTER_WEAPON(CRYLINK, w_crylink, IT_CELLS, 6, WEP_FLAG_NORMAL | WEP_TYPE_SPLA
 .entity queuenext;
 .entity queueprev;
 
+// weapon load persistence, for weapons that support reloading
+.float crylink_load;
+
+void W_Crylink_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_crylink_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.crylink_load;
+               self.clip_size = autocvar_g_balance_crylink_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Crylink_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_crylink_reload_ammo && self.ammo_cells) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_cells -= 1;
+       }
+       self.crylink_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_crylink_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Crylink_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_crylink_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_cells, min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_crylink_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_crylink_reload_time, W_Crylink_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_Crylink_CheckLinks(entity e)
 {
        float i;
@@ -319,8 +374,17 @@ void W_Crylink_Attack (void)
        vector forward, right, up;
        float maxdmg;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_cells = self.ammo_cells - autocvar_g_balance_crylink_primary_ammo;
+       {
+               if(autocvar_g_balance_crylink_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_crylink_primary_ammo;
+                       self.crylink_load = self.clip_load;
+               }
+               else
+                       self.ammo_cells -= autocvar_g_balance_crylink_primary_ammo;
+       }
 
        maxdmg = autocvar_g_balance_crylink_primary_damage*autocvar_g_balance_crylink_primary_shots;
        maxdmg *= 1 + autocvar_g_balance_crylink_primary_bouncedamagefactor * autocvar_g_balance_crylink_primary_bounces;
@@ -422,8 +486,17 @@ void W_Crylink_Attack2 (void)
        local entity proj, prevproj, firstproj;
        float maxdmg;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_cells = self.ammo_cells - autocvar_g_balance_crylink_secondary_ammo;
+       {
+               if(autocvar_g_balance_crylink_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_crylink_secondary_ammo;
+                       self.crylink_load = self.clip_load;
+               }
+               else
+                       self.ammo_cells -= autocvar_g_balance_crylink_secondary_ammo;
+       }
 
        maxdmg = autocvar_g_balance_crylink_secondary_damage*autocvar_g_balance_crylink_secondary_shots;
        maxdmg *= 1 + autocvar_g_balance_crylink_secondary_bouncedamagefactor * autocvar_g_balance_crylink_secondary_bounces;
@@ -511,6 +584,7 @@ void spawnfunc_weapon_crylink (void)
 
 float w_crylink(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
        {
                if (random() < 0.10)
@@ -520,7 +594,9 @@ float w_crylink(float req)
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
+               if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo)) // forced reload
+                       W_Crylink_Reload();
+               else if (self.BUTTON_ATCK)
                {
                        if (!self.crylink_waitrelease)
                        if (weapon_prepareattack(0, autocvar_g_balance_crylink_primary_refire))
@@ -587,22 +663,41 @@ float w_crylink(float req)
                precache_sound ("weapons/crylink_fire.wav");
                precache_sound ("weapons/crylink_fire2.wav");
                precache_sound ("weapons/crylink_linkjoin.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_CRYLINK);
+               W_Crylink_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
        {
                // don't "run out of ammo" and switch weapons while waiting for release
                if(self.crylink_lastgroup && self.crylink_waitrelease)
                        return TRUE;
-               return self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo;
+
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo;
+               ammo_amount += (autocvar_g_balance_crylink_reload_ammo && self.crylink_load >= autocvar_g_balance_crylink_primary_ammo);
+               return ammo_amount;
        }
        else if (req == WR_CHECKAMMO2)
        {
                // don't "run out of ammo" and switch weapons while waiting for release
                if(self.crylink_lastgroup && self.crylink_waitrelease)
                        return TRUE;
-               return self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo;
+
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_crylink_reload_ammo && self.crylink_load >= autocvar_g_balance_crylink_secondary_ammo);
+               return ammo_amount;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.crylink_load = autocvar_g_balance_crylink_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Crylink_Reload();
        }
        return TRUE;
 };
index f5491f39aa1054b2c112e70581731437f631d0f0..154e7275c625b1cf1403727fa26bdc1804e07183 100644 (file)
@@ -5,6 +5,61 @@ REGISTER_WEAPON(ELECTRO, w_electro, IT_CELLS, 5, WEP_FLAG_NORMAL | WEP_TYPE_SPLA
 .float electro_count;
 .float electro_secondarytime;
 
+// weapon load persistence, for weapons that support reloading
+.float electro_load;
+
+void W_Electro_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_electro_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.electro_load;
+               self.clip_size = autocvar_g_balance_electro_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Electro_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_electro_reload_ammo && self.ammo_cells) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_cells -= 1;
+       }
+       self.electro_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_electro_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Electro_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_electro_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_cells, min(autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_secondary_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_electro_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_electro_reload_time, W_Electro_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_Plasma_Explode_Combo (void);
 
 void W_Plasma_TriggerCombo(vector org, float rad, entity own)
@@ -110,6 +165,18 @@ void W_Electro_Attack()
 {
        local entity proj;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       {
+               if(autocvar_g_balance_electro_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_electro_primary_ammo;
+                       self.electro_load = self.clip_load;
+               }
+               else
+                       self.ammo_cells -= autocvar_g_balance_electro_primary_ammo;
+       }
+
        W_SetupShot_ProjectileSize (self, '0 0 -3', '0 0 -3', FALSE, 2, "weapons/electro_fire.wav", CHAN_WEAPON, autocvar_g_balance_electro_primary_damage);
 
        pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
@@ -126,8 +193,6 @@ void W_Electro_Attack()
        proj.projectiledeathtype = WEP_ELECTRO;
        setorigin(proj, w_shotorg);
 
-       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_cells = self.ammo_cells - autocvar_g_balance_electro_primary_ammo;
        proj.movetype = MOVETYPE_FLY;
        W_SETUPPROJECTILEVELOCITY(proj, g_balance_electro_primary);
        proj.angles = vectoangles(proj.velocity);
@@ -147,6 +212,18 @@ void W_Electro_Attack2()
 {
        local entity proj;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       {
+               if(autocvar_g_balance_electro_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_electro_secondary_ammo;
+                       self.electro_load = self.clip_load;
+               }
+               else
+                       self.ammo_cells -= autocvar_g_balance_electro_secondary_ammo;
+       }
+
        W_SetupShot_ProjectileSize (self, '0 0 -4', '0 0 -4', FALSE, 2, "weapons/electro_fire2.wav", CHAN_WEAPON, autocvar_g_balance_electro_secondary_damage);
 
        w_shotdir = v_forward; // no TrueAim for grenades please
@@ -165,8 +242,6 @@ void W_Electro_Attack2()
        proj.projectiledeathtype = WEP_ELECTRO | HITTYPE_SECONDARY;
        setorigin(proj, w_shotorg);
 
-       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_cells = self.ammo_cells - autocvar_g_balance_electro_secondary_ammo;
        //proj.glow_size = 50;
        //proj.glow_color = 45;
        proj.movetype = MOVETYPE_BOUNCE;
@@ -193,7 +268,7 @@ void W_Electro_Attack2()
        CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO, FALSE); // no culling, it has sound
 
        other = proj; MUTATOR_CALLHOOK(EditProjectile);
-       }
+}
 
 .vector hook_start, hook_end;
 float lgbeam_send(entity to, float sf)
@@ -224,6 +299,16 @@ float lgbeam_send(entity to, float sf)
 }
 .entity lgbeam;
 .float prevlgfire;
+float lgbeam_checkammo()
+{
+       if(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
+               return TRUE;
+       else if(autocvar_g_balance_electro_reload_ammo)
+               return self.owner.clip_load > 0;
+       else
+               return self.owner.ammo_cells > 0;
+}
+
 void lgbeam_think()
 {
        self.owner.prevlgfire = time;
@@ -232,7 +317,8 @@ void lgbeam_think()
                remove(self);
                return;
        }
-       if (self.owner.weaponentity.state != WS_INUSE || (self.owner.ammo_cells <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK || self.owner.freezetag_frozen)
+
+       if (self.owner.weaponentity.state != WS_INUSE || !lgbeam_checkammo() || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK || self.owner.freezetag_frozen)
        {
                if(self == self.owner.lgbeam)
                        self.owner.lgbeam = world;
@@ -246,12 +332,22 @@ void lgbeam_think()
 
        float dt, f;
        dt = frametime;
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
        {
                if(autocvar_g_balance_electro_primary_ammo)
                {
-                       dt = min(dt, self.owner.ammo_cells / autocvar_g_balance_electro_primary_ammo);
-                       self.owner.ammo_cells = max(0, self.owner.ammo_cells - autocvar_g_balance_electro_primary_ammo * frametime);
+                       if(autocvar_g_balance_electro_reload_ammo)
+                       {
+                               dt = min(dt, self.owner.clip_load / autocvar_g_balance_electro_primary_ammo);
+                               self.owner.clip_load = max(0, self.owner.clip_load - autocvar_g_balance_electro_primary_ammo * frametime);
+                               self.owner.electro_load = self.owner.clip_load;
+                       }
+                       else
+                       {
+                               dt = min(dt, self.owner.ammo_cells / autocvar_g_balance_electro_primary_ammo);
+                               self.owner.ammo_cells = max(0, self.owner.ammo_cells - autocvar_g_balance_electro_primary_ammo * frametime);
+                       }
                }
        }
 
@@ -344,6 +440,7 @@ void w_electro_checkattack()
 .float BUTTON_ATCK_prev;
 float w_electro(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
        {
                self.BUTTON_ATCK=FALSE;
@@ -376,7 +473,9 @@ float w_electro(float req)
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
+               if(autocvar_g_balance_electro_reload_ammo && self.clip_load < min(autocvar_g_balance_electro_primary_ammo, autocvar_g_balance_electro_secondary_ammo)) // forced reload
+                       W_Electro_Reload();
+               else if (self.BUTTON_ATCK)
                {
                        if(autocvar_g_balance_electro_lightning)
                                if(self.BUTTON_ATCK_prev)
@@ -417,16 +516,18 @@ float w_electro(float req)
                                }
                                self.BUTTON_ATCK_prev = 0;
                        }
-               }
 
-               if (self.BUTTON_ATCK2)
-               if (time >= self.electro_secondarytime)
-               if (weapon_prepareattack(1, autocvar_g_balance_electro_secondary_refire))
-               {
-                       W_Electro_Attack2();
-                       self.electro_count = autocvar_g_balance_electro_secondary_count;
-                       weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_electro_secondary_animtime, w_electro_checkattack);
-                       self.electro_secondarytime = time + autocvar_g_balance_electro_secondary_refire2 * W_WeaponRateFactor();
+                       if (self.BUTTON_ATCK2)
+                       {
+                               if (time >= self.electro_secondarytime)
+                               if (weapon_prepareattack(1, autocvar_g_balance_electro_secondary_refire))
+                               {
+                                       W_Electro_Attack2();
+                                       self.electro_count = autocvar_g_balance_electro_secondary_count;
+                                       weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_electro_secondary_animtime, w_electro_checkattack);
+                                       self.electro_secondarytime = time + autocvar_g_balance_electro_secondary_refire2 * W_WeaponRateFactor();
+                               }
+                       }
                }
        }
        else if (req == WR_PRECACHE)
@@ -439,25 +540,48 @@ float w_electro(float req)
                precache_sound ("weapons/electro_fire2.wav");
                precache_sound ("weapons/electro_impact.wav");
                precache_sound ("weapons/electro_impact_combo.wav");
+               precache_sound ("weapons/reload.wav");
                if(autocvar_g_balance_electro_lightning)
                {
                        precache_sound ("weapons/lgbeam_fire.wav");
                }
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_ELECTRO);
+               W_Electro_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
        {
                if(autocvar_g_balance_electro_lightning)
-                       return !autocvar_g_balance_electro_primary_ammo || (self.ammo_cells > 0);
+                       ammo_amount = !autocvar_g_balance_electro_primary_ammo || (self.ammo_cells > 0);
                else
-                       return self.ammo_cells >= autocvar_g_balance_electro_primary_ammo;
+                       ammo_amount = self.ammo_cells >= autocvar_g_balance_electro_primary_ammo;
+               if(autocvar_g_balance_electro_reload_ammo)
+               {
+                       if(autocvar_g_balance_electro_lightning)
+                               ammo_amount += !autocvar_g_balance_electro_primary_ammo || (self.electro_load > 0);
+                       else
+                               ammo_amount += self.electro_load >= autocvar_g_balance_electro_primary_ammo;
+               }
+               return ammo_amount;
        }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_cells >= autocvar_g_balance_electro_secondary_ammo;
+       {
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_electro_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_electro_reload_ammo && self.electro_load >= autocvar_g_balance_electro_secondary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_RESETPLAYER)
        {
                self.electro_secondarytime = time;
+
+               // all weapons must be fully loaded when we spawn
+               self.electro_load = autocvar_g_balance_electro_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Shotgun_Reload();
        }
        return TRUE;
 };
index 73ff1595a79752e395cbd8b3e9c8737b3d58fea0..686a727cf7e97512087c21cc640e7edb10ea2dae 100644 (file)
@@ -6,6 +6,65 @@ REGISTER_WEAPON(FIREBALL, w_fireball, IT_FUEL, 9, WEP_TYPE_SPLASH, BOT_PICKUP_RA
 .vector fireball_impactvec;
 .float fireball_primarytime;
 
+// weapon load persistence, for weapons that support reloading
+.float fireball_load;
+
+void W_Fireball_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_fireball_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.fireball_load;
+               self.clip_size = autocvar_g_balance_fireball_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Fireball_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_fireball_reload_ammo && self.ammo_fuel) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_fuel -= 1;
+
+               // fuel can be a non-whole number, which brakes stuff here when between 0 and 1
+               if(self.ammo_fuel < 1)
+                       self.ammo_fuel = 0;
+       }
+       self.fireball_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_fireball_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Fireball_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_fireball_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_fuel, min(autocvar_g_balance_fireball_primary_ammo, autocvar_g_balance_fireball_secondary_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_fireball_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_fireball_reload_time, W_Fireball_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_Fireball_Explode (void)
 {
        entity e;
@@ -194,8 +253,17 @@ void W_Fireball_Attack1_Frame1()
 
 void W_Fireball_Attack1_Frame0()
 {
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_fuel = self.ammo_fuel - autocvar_g_balance_fireball_primary_ammo;
+       {
+               if(autocvar_g_balance_fireball_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_fireball_primary_ammo;
+                       self.fireball_load = self.clip_load;
+               }
+               else
+                       self.ammo_fuel -= autocvar_g_balance_fireball_primary_ammo;
+       }
 
        W_Fireball_AttackEffect(0, '-1.25 -3.75 0');
        sound (self, CHAN_WEAPON, "weapons/fireball_prefire2.wav", VOL_BASE, ATTN_NORM);
@@ -246,8 +314,17 @@ void W_Fireball_Attack2()
        vector f_diff;
        float c;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_fuel = self.ammo_fuel - autocvar_g_balance_fireball_secondary_ammo;
+       {
+               if(autocvar_g_balance_fireball_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_fireball_secondary_ammo;
+                       self.fireball_load = self.clip_load;
+               }
+               else
+                       self.ammo_fuel -= autocvar_g_balance_fireball_secondary_ammo;
+       }
 
        c = mod(self.bulletcounter, 4);
        switch(c)
@@ -304,6 +381,7 @@ void spawnfunc_weapon_fireball (void)
 
 float w_fireball(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
        {
                self.BUTTON_ATCK = FALSE;
@@ -327,18 +405,24 @@ float w_fireball(float req)
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
-               if (time >= self.fireball_primarytime)
-               if (weapon_prepareattack(0, autocvar_g_balance_fireball_primary_refire))
+               if(autocvar_g_balance_fireball_reload_ammo && self.clip_load < min(autocvar_g_balance_fireball_primary_ammo, autocvar_g_balance_fireball_secondary_ammo)) // forced reload
+                       W_Fireball_Reload();
+               else if (self.BUTTON_ATCK)
                {
-                       W_Fireball_Attack1_Frame0();
-                       self.fireball_primarytime = time + autocvar_g_balance_fireball_primary_refire2;
+                       if (time >= self.fireball_primarytime)
+                       if (weapon_prepareattack(0, autocvar_g_balance_fireball_primary_refire))
+                       {
+                               W_Fireball_Attack1_Frame0();
+                               self.fireball_primarytime = time + autocvar_g_balance_fireball_primary_refire2;
+                       }
                }
-               if (self.BUTTON_ATCK2)
-               if (weapon_prepareattack(1, autocvar_g_balance_fireball_secondary_refire))
+               else if (self.BUTTON_ATCK2)
                {
-                       W_Fireball_Attack2();
-                       weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_fireball_secondary_animtime, w_ready);
+                       if (weapon_prepareattack(1, autocvar_g_balance_fireball_secondary_refire))
+                       {
+                               W_Fireball_Attack2();
+                               weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_fireball_secondary_animtime, w_ready);
+                       }
                }
        }
        else if (req == WR_PRECACHE)
@@ -350,16 +434,35 @@ float w_fireball(float req)
                precache_sound ("weapons/fireball_fire.wav");
                precache_sound ("weapons/fireball_fire2.wav");
                precache_sound ("weapons/fireball_prefire2.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_FIREBALL);
+               W_Fireball_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_fuel >= autocvar_g_balance_fireball_primary_ammo;
+       {
+               ammo_amount = self.ammo_fuel >= autocvar_g_balance_fireball_primary_ammo;
+               ammo_amount += (autocvar_g_balance_fireball_reload_ammo && self.fireball_load >= autocvar_g_balance_fireball_primary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_fuel >= autocvar_g_balance_fireball_secondary_ammo;
+       {
+               ammo_amount = self.ammo_fuel >= autocvar_g_balance_fireball_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_fireball_reload_ammo && self.fireball_load >= autocvar_g_balance_fireball_secondary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_RESETPLAYER)
        {
                self.fireball_primarytime = time;
+
+               // all weapons must be fully loaded when we spawn
+               self.fireball_load = autocvar_g_balance_fireball_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Fireball_Reload();
        }
        return TRUE;
 };
index d5f6c5d6827f13f213330b5012a74bdbf2fd9344..1d039d5f9d8fea63dce2c83c39c7eb4810364eaa 100644 (file)
@@ -5,6 +5,61 @@ REGISTER_WEAPON(GRENADE_LAUNCHER, w_glauncher, IT_ROCKETS, 4, WEP_FLAG_NORMAL |
 .float gl_detonate_later;
 .float gl_bouncecnt;
 
+// weapon load persistence, for weapons that support reloading
+.float grenadelauncher_load;
+
+void W_GrenadeLauncher_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_grenadelauncher_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.grenadelauncher_load;
+               self.clip_size = autocvar_g_balance_grenadelauncher_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_GrenadeLauncher_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_grenadelauncher_reload_ammo && self.ammo_rockets) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_rockets -= 1;
+       }
+       self.grenadelauncher_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_grenadelauncher_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_GrenadeLauncher_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_grenadelauncher_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_rockets, min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_grenadelauncher_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_grenadelauncher_reload_time, W_GrenadeLauncher_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_Grenade_Explode (void)
 {
        if(other.takedamage == DAMAGE_AIM)
@@ -161,8 +216,18 @@ void W_Grenade_Attack (void)
 {
        local entity gren;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_grenadelauncher_primary_ammo;
+       {
+               if(autocvar_g_balance_grenadelauncher_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_grenadelauncher_primary_ammo;
+                       self.grenadelauncher_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_grenadelauncher_primary_ammo;
+       }
+
        W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CHAN_WEAPON, autocvar_g_balance_grenadelauncher_primary_damage);
        w_shotdir = v_forward; // no TrueAim for grenades please
 
@@ -208,8 +273,18 @@ void W_Grenade_Attack2 (void)
 {
        local entity gren;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_grenadelauncher_secondary_ammo;
+       {
+               if(autocvar_g_balance_grenadelauncher_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_grenadelauncher_secondary_ammo;
+                       self.grenadelauncher_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_grenadelauncher_secondary_ammo;
+       }
+
        W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CHAN_WEAPON, autocvar_g_balance_grenadelauncher_secondary_damage);
        w_shotdir = v_forward; // no TrueAim for grenades please
 
@@ -260,6 +335,7 @@ float w_glauncher(float req)
 {
        entity nade;
        float nadefound;
+       float ammo_amount;
 
        if (req == WR_AIM)
        {
@@ -284,13 +360,17 @@ float w_glauncher(float req)
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
-               if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire))
+               if(autocvar_g_balance_grenadelauncher_reload_ammo && self.clip_load < min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo)) // forced reload
+                       W_GrenadeLauncher_Reload();
+               else if (self.BUTTON_ATCK)
                {
-                       W_Grenade_Attack();
-                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready);
+                       if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire))
+                       {
+                               W_Grenade_Attack();
+                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready);
+                       }
                }
-               if (self.BUTTON_ATCK2)
+               else if (self.BUTTON_ATCK2)
                {
                        if (cvar("g_balance_grenadelauncher_secondary_remote_detonateprimary"))
                        {
@@ -326,13 +406,34 @@ float w_glauncher(float req)
                precache_sound ("weapons/grenade_bounce6.wav");
                precache_sound ("weapons/grenade_stick.wav");
                precache_sound ("weapons/grenade_fire.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_GRENADE_LAUNCHER);
+               W_GrenadeLauncher_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo;
+       {
+               ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo;
+               ammo_amount += (autocvar_g_balance_grenadelauncher_reload_ammo && self.grenadelauncher_load >= autocvar_g_balance_grenadelauncher_primary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo;
+       {
+               ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_grenadelauncher_reload_ammo && self.grenadelauncher_load >= autocvar_g_balance_grenadelauncher_secondary_ammo);
+               return ammo_amount;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.grenadelauncher_load = autocvar_g_balance_grenadelauncher_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_GrenadeLauncher_Reload();
+       }
        return TRUE;
 };
 #endif
index 5fb25642e2fa41383515d11085393ac64c74707f..7ad6ee210206d80ecbcde1664b06800fd84368bf 100644 (file)
@@ -3,6 +3,62 @@ REGISTER_WEAPON(HAGAR, w_hagar, IT_ROCKETS, 8, WEP_FLAG_NORMAL | WEP_FLAG_CANCLI
 #else
 #ifdef SVQC
 // NO bounce protection, as bounces are limited!
+
+// weapon load persistence, for weapons that support reloading
+.float hagar_load;
+
+void W_Hagar_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_hagar_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.hagar_load;
+               self.clip_size = autocvar_g_balance_hagar_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Hagar_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_hagar_reload_ammo && self.ammo_rockets) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_rockets -= 1;
+       }
+       self.hagar_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_hagar_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Hagar_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_hagar_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_rockets, min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_hagar_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_hagar_reload_time, W_Hagar_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_Hagar_Explode (void)
 {
        self.event_damage = SUB_Null;
@@ -44,8 +100,18 @@ void W_Hagar_Attack (void)
 {
        local entity missile;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_hagar_primary_ammo;
+       {
+               if(autocvar_g_balance_hagar_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_hagar_primary_ammo;
+                       self.hagar_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_hagar_primary_ammo;
+       }
+
        W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CHAN_WEAPON, autocvar_g_balance_hagar_primary_damage);
 
        pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
@@ -79,8 +145,18 @@ void W_Hagar_Attack2 (void)
 {
        local entity missile;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_hagar_secondary_ammo;
+       {
+               if(autocvar_g_balance_hagar_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_hagar_secondary_ammo;
+                       self.hagar_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_hagar_secondary_ammo;
+       }
+
        W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CHAN_WEAPON, autocvar_g_balance_hagar_secondary_damage);
 
        pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
@@ -118,6 +194,7 @@ void spawnfunc_weapon_hagar (void)
 
 float w_hagar(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
                if (random()>0.15)
                        self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hagar_primary_speed, 0, autocvar_g_balance_hagar_primary_lifetime, FALSE);
@@ -128,17 +205,23 @@ float w_hagar(float req)
                }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
-               if (weapon_prepareattack(0, autocvar_g_balance_hagar_primary_refire))
+               if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo)) // forced reload
+                       W_Hagar_Reload();
+               else if (self.BUTTON_ATCK)
                {
-                       W_Hagar_Attack();
-                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hagar_primary_refire, w_ready);
+                       if (weapon_prepareattack(0, autocvar_g_balance_hagar_primary_refire))
+                       {
+                               W_Hagar_Attack();
+                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hagar_primary_refire, w_ready);
+                       }
                }
-               if (self.BUTTON_ATCK2 && autocvar_g_balance_hagar_secondary)
-               if (weapon_prepareattack(1, autocvar_g_balance_hagar_secondary_refire))
+               else if (self.BUTTON_ATCK2 && autocvar_g_balance_hagar_secondary)
                {
-                       W_Hagar_Attack2();
-                       weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_refire, w_ready);
+                       if (weapon_prepareattack(1, autocvar_g_balance_hagar_secondary_refire))
+                       {
+                               W_Hagar_Attack2();
+                               weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_refire, w_ready);
+                       }
                }
        }
        else if (req == WR_PRECACHE)
@@ -147,13 +230,34 @@ float w_hagar(float req)
                precache_model ("models/weapons/v_hagar.md3");
                precache_model ("models/weapons/h_hagar.iqm");
                precache_sound ("weapons/hagar_fire.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_HAGAR);
+               W_Hagar_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_rockets >= autocvar_g_balance_hagar_primary_ammo;
+       {
+               ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_primary_ammo;
+               ammo_amount += (autocvar_g_balance_hagar_reload_ammo && self.hagar_load >= autocvar_g_balance_hagar_primary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo;
+       {
+               ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_hagar_reload_ammo && self.hagar_load >= autocvar_g_balance_hagar_secondary_ammo);
+               return ammo_amount;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.hagar_load = autocvar_g_balance_hagar_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Hagar_Reload();
+       }
        return TRUE;
 };
 #endif
index 4bba3b8051b8d4d504caf0047c9b3d1579e53062..2344f66bf8173ed3bf57b52705ba9a774609ff0d 100644 (file)
@@ -3,6 +3,61 @@ REGISTER_WEAPON(HLAC, w_hlac, IT_CELLS, 6, WEP_FLAG_NORMAL | WEP_TYPE_SPLASH, BO
 #else
 #ifdef SVQC
 
+// weapon load persistence, for weapons that support reloading
+.float hlac_load;
+
+void W_HLAC_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_hlac_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.hlac_load;
+               self.clip_size = autocvar_g_balance_hlac_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_HLAC_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_hlac_reload_ammo && self.ammo_cells) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_cells -= 1;
+       }
+       self.hlac_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_hlac_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_HLAC_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_hlac_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_cells, min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_hlac_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_hlac_reload_time, W_HLAC_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_HLAC_Touch (void)
 {
        PROJECTILE_TOUCH;
@@ -22,10 +77,17 @@ void W_HLAC_Attack (void)
        local entity missile;
     float spread;
 
-    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-    {
-        self.ammo_cells = self.ammo_cells - autocvar_g_balance_hlac_primary_ammo;
-    }
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       {
+               if(autocvar_g_balance_hlac_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_hlac_primary_ammo;
+                       self.hlac_load = self.clip_load;
+               }
+               else
+                       self.ammo_cells -= autocvar_g_balance_hlac_primary_ammo;
+       }
 
     spread = autocvar_g_balance_hlac_primary_spread_min + (autocvar_g_balance_hlac_primary_spread_add * self.misc_bulletcounter);
     spread = min(spread,autocvar_g_balance_hlac_primary_spread_max);
@@ -116,10 +178,17 @@ void W_HLAC_Attack2 (void)
 {
     float i;
 
-    if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-    {
-        self.ammo_cells = self.ammo_cells - autocvar_g_balance_hlac_secondary_ammo;
-    }
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       {
+               if(autocvar_g_balance_hlac_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_hlac_secondary_ammo;
+                       self.hlac_load = self.clip_load;
+               }
+               else
+                       self.ammo_cells -= autocvar_g_balance_hlac_secondary_ammo;
+       }
 
     for(i=autocvar_g_balance_hlac_secondary_shots;i>0;--i)
         W_HLAC_Attack2f();
@@ -167,25 +236,31 @@ void spawnfunc_weapon_hlac (void)
 
 float w_hlac(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
         self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hlac_primary_speed, 0, autocvar_g_balance_hlac_primary_lifetime, FALSE);
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
-               if (weapon_prepareattack(0, autocvar_g_balance_hlac_primary_refire))
+               if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo)) // forced reload
+                       W_HLAC_Reload();
+               else if (self.BUTTON_ATCK)
                {
-                       self.misc_bulletcounter = 0;
-                       W_HLAC_Attack();
-                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02);
+                       if (weapon_prepareattack(0, autocvar_g_balance_hlac_primary_refire))
+                       {
+                               self.misc_bulletcounter = 0;
+                               W_HLAC_Attack();
+                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02);
+                       }
                }
 
-               if (self.BUTTON_ATCK2 && autocvar_g_balance_hlac_secondary)
-               if (weapon_prepareattack(1, autocvar_g_balance_hlac_secondary_refire))
+               else if (self.BUTTON_ATCK2 && autocvar_g_balance_hlac_secondary)
                {
-                       W_HLAC_Attack2();
-                       weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hlac_secondary_animtime, w_ready);
+                       if (weapon_prepareattack(1, autocvar_g_balance_hlac_secondary_refire))
+                       {
+                               W_HLAC_Attack2();
+                               weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hlac_secondary_animtime, w_ready);
+                       }
                }
-
        }
        else if (req == WR_PRECACHE)
        {
@@ -193,14 +268,35 @@ float w_hlac(float req)
                precache_model ("models/weapons/v_hlac.md3");
                precache_model ("models/weapons/h_hlac.iqm");
                precache_sound ("weapons/lasergun_fire.wav");
+               precache_sound ("weapons/reload.wav");
 
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_HLAC);
+               W_HLAC_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_cells >= autocvar_g_balance_hlac_primary_ammo;
+       {
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_primary_ammo;
+               ammo_amount += (autocvar_g_balance_hlac_reload_ammo && self.hlac_load >= autocvar_g_balance_hlac_primary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_cells >= autocvar_g_balance_hlac_secondary_ammo;
+       {
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_hlac_reload_ammo && self.hlac_load >= autocvar_g_balance_hlac_secondary_ammo);
+               return ammo_amount;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.hlac_load = autocvar_g_balance_hlac_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_HLAC_Reload();
+       }
        return TRUE;
 };
 #endif
index da5e3f9423d086f6bdb236a2f744ed091fa4649d..8c4cfc897a3e681ef4121f6493013837a2eedbc1 100644 (file)
@@ -13,6 +13,12 @@ REGISTER_WEAPON(HOOK, w_hook, IT_CELLS|IT_FUEL, 0, WEP_FLAG_CANCLIMB | WEP_TYPE_
 .float hook_time_hooked;
 .float hook_time_fueldecrease;
 
+void W_Hook_SetAmmoCounter()
+{
+       // this weapon doesn't have a reload system, so always set the clip to 0 when switching to it
+       self.clip_load = self.clip_size = 0; // also keeps crosshair ammo from displaying
+}
+
 void W_Hook_ExplodeThink (void)
 {
        float dt, dmg_remaining_next, f;
@@ -228,6 +234,7 @@ float w_hook(float req)
        else if (req == WR_SETUP)
        {
                weapon_setup(WEP_HOOK);
+               W_Hook_SetAmmoCounter();
                self.hook_state &~= HOOK_WAITING_FOR_RELEASE;
        }
        else if (req == WR_CHECKAMMO1)
index 4ce1331931628366bfaf35037c429edfbbe7f3b4..6164f543d863fe2a1e5b64c6082ad8eab9141a5d 100644 (file)
@@ -4,6 +4,54 @@ REGISTER_WEAPON(LASER, w_laser, 0, 1, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_
 #ifdef SVQC
 void(float imp) W_SwitchWeapon;
 
+// weapon load persistence, for weapons that support reloading
+.float laser_load;
+
+void W_Laser_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_laser_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.laser_load;
+               self.clip_size = autocvar_g_balance_laser_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Laser_ReloadedAndReady()
+{
+       float t;
+
+       self.clip_load = autocvar_g_balance_laser_reload_ammo; // maximum load since this weapon uses no ammo
+       self.laser_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_laser_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Laser_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_laser_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(1, 0))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_laser_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_laser_reload_time, W_Laser_ReloadedAndReady);
+
+       self.clip_load = -1;
+}
+
 void W_Laser_Touch (void)
 {
        PROJECTILE_TOUCH;
@@ -226,16 +274,40 @@ float w_laser(float req)
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
-               if (weapon_prepareattack(0, autocvar_g_balance_laser_primary_refire))
+               if(autocvar_g_balance_laser_reload_ammo && self.clip_load < 1) // forced reload
+                       W_Laser_Reload();
+               else if (self.BUTTON_ATCK)
                {
-                       W_Laser_Attack(0);
-                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_primary_animtime, w_ready);
+                       if (weapon_prepareattack(0, autocvar_g_balance_laser_primary_refire))
+                       {
+                               // if this weapon is reloadable, decrease its load
+                               if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+                               {
+                                       if(autocvar_g_balance_laser_reload_ammo)
+                                       {
+                                               self.clip_load -= 1;
+                                               self.laser_load = self.clip_load;
+                                       }
+                               }
+
+                               W_Laser_Attack(0);
+                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_primary_animtime, w_ready);
+                       }
                }
-               if (self.BUTTON_ATCK2)
+               else if (self.BUTTON_ATCK2)
                {
                        if(autocvar_g_balance_laser_secondary)
                        {
+                               // if this weapon is reloadable, decrease its load
+                               if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+                               {
+                                       if(autocvar_g_balance_laser_reload_ammo)
+                                       {
+                                               self.clip_load -= 1;
+                                               self.laser_load = self.clip_load;
+                                       }
+                               }
+
                                if (weapon_prepareattack(0, 0))
                                {
                                        W_Laser_Attack2();
@@ -256,13 +328,30 @@ float w_laser(float req)
                precache_model ("models/weapons/h_laser.iqm");
                precache_sound ("weapons/lasergun_fire.wav");
                precache_sound ("weapons/gauntlet_fire.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_LASER);
+               W_Laser_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
+       {
                return TRUE;
+       }
        else if (req == WR_CHECKAMMO2)
+       {
                return TRUE;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.laser_load = autocvar_g_balance_laser_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Laser_Reload();
+       }
        return TRUE;
 };
 #endif
index 07589cf0d4a14d99e3bf264d5aeef8a384bbb751..00a836eb8e556e2eb72a72c9ee967be849fabf24 100644 (file)
@@ -6,6 +6,61 @@ void W_Mine_Think (void);
 .float minelayer_detonate, minelayer_mines;
 .float mine_time;
 
+// weapon load persistence, for weapons that support reloading
+.float minelayer_load;
+
+void W_MineLayer_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_minelayer_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.minelayer_load;
+               self.clip_size = autocvar_g_balance_minelayer_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_MineLayer_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_minelayer_reload_ammo && self.ammo_rockets) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_rockets -= 1;
+       }
+       self.minelayer_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_minelayer_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_MineLayer_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_minelayer_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_rockets, autocvar_g_balance_minelayer_ammo))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_minelayer_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_minelayer_reload_time, W_MineLayer_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void spawnfunc_weapon_minelayer (void)
 {
        weapon_defaultspawnfunc(WEP_MINE_LAYER);
@@ -214,8 +269,17 @@ void W_Mine_Attack (void)
                }
        }
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_minelayer_ammo;
+       {
+               if(autocvar_g_balance_minelayer_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_minelayer_ammo;
+                       self.minelayer_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_minelayer_ammo;
+       }
 
        W_SetupShot_ProjectileSize (self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", CHAN_WEAPON, autocvar_g_balance_minelayer_damage);
        pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
@@ -270,6 +334,8 @@ float w_minelayer(float req)
 {
        entity mine;
        float minfound;
+       float ammo_amount;
+
        if (req == WR_AIM)
        {
                // aim and decide to fire if appropriate
@@ -367,7 +433,9 @@ float w_minelayer(float req)
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
+               if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < autocvar_g_balance_minelayer_ammo) // forced reload
+                       W_MineLayer_Reload();
+               else if (self.BUTTON_ATCK)
                {
                        if(weapon_prepareattack(0, autocvar_g_balance_minelayer_refire))
                        {
@@ -376,7 +444,7 @@ float w_minelayer(float req)
                        }
                }
 
-               if (self.BUTTON_ATCK2)
+               else if (self.BUTTON_ATCK2)
                {
                        minfound = 0;
                        for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
@@ -402,20 +470,38 @@ float w_minelayer(float req)
                precache_sound ("weapons/mine_fire.wav");
                precache_sound ("weapons/mine_stick.wav");
                precache_sound ("weapons/mine_trigger.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
        {
                weapon_setup(WEP_MINE_LAYER);
+               W_MineLayer_SetAmmoCounter();
        }
        else if (req == WR_CHECKAMMO1)
        {
                // don't switch while placing a mine
-               if ((ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER)
-                       && self.ammo_rockets < autocvar_g_balance_minelayer_ammo)
-                       return FALSE;
+               if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER)
+               {
+                       if(self.ammo_rockets < autocvar_g_balance_minelayer_ammo)
+                               ammo_amount = FALSE;
+                       if(autocvar_g_balance_electro_reload_ammo && self.minelayer_load < autocvar_g_balance_minelayer_ammo)
+                               ammo_amount = FALSE;
+               }
+               return ammo_amount;
        }
        else if (req == WR_CHECKAMMO2)
+       {
                return FALSE;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.minelayer_load = autocvar_g_balance_minelayer_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_MineLayer_Reload();
+       }
        return TRUE;
 };
 #endif
index 89f209937a83f0cd58f6d335489761e89bdb41f2..721fbe42e4c95d264c40a5bab4cee08b4ed37de7 100644 (file)
@@ -4,6 +4,66 @@ REGISTER_WEAPON(MINSTANEX, w_minstanex, IT_CELLS, 7, WEP_FLAG_HIDDEN | WEP_FLAG_
 #ifdef SVQC
 .float minstanex_lasthit;
 
+// weapon load persistence, for weapons that support reloading
+.float minstanex_load;
+
+void W_Minstanex_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_minstanex_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.minstanex_load;
+               self.clip_size = autocvar_g_balance_minstanex_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Minstanex_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_minstanex_reload_ammo && self.ammo_cells) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_cells -= 1;
+       }
+       self.minstanex_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_minstanex_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Minstanex_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_minstanex_reload_ammo)
+               return;
+
+       if(autocvar_g_balance_minstanex_laser_ammo)
+       {
+               if(!W_ReloadCheck(self.ammo_cells, min(autocvar_g_balance_minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo)))
+                       return;
+       }
+       else if(!W_ReloadCheck(self.ammo_cells, autocvar_g_balance_minstanex_ammo))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_minstanex_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_minstanex_reload_time, W_Minstanex_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_MinstaNex_Attack (void)
 {
        float flying;
@@ -80,12 +140,24 @@ void W_MinstaNex_Attack (void)
        if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
                Damage_DamageInfo(trace_endpos, 10000, 0, 0, 800 * w_shotdir, WEP_MINSTANEX, self);
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
        {
-               if (g_minstagib)
-                       self.ammo_cells = self.ammo_cells - 1;
+               if(autocvar_g_balance_minstanex_reload_ammo)
+               {
+                       if (g_minstagib)
+                               self.clip_load -= - 1;
+                       else
+                               self.clip_load -= autocvar_g_balance_minstanex_ammo;
+                       self.minstanex_load = self.clip_load;
+               }
                else
-                       self.ammo_cells = self.ammo_cells - autocvar_g_balance_minstanex_ammo;
+               {
+                       if (g_minstagib)
+                               self.ammo_cells -= - 1;
+                       else
+                               self.ammo_cells -= autocvar_g_balance_minstanex_ammo;
+               }
        }
 }
 
@@ -171,18 +243,30 @@ void minstagib_ammocheck (void)
 
 void spawnfunc_weapon_minstanex (void); // defined in t_items.qc
 
+float minstanex_ammo;
 float w_minstanex(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
        {
-               if(self.ammo_cells>0)
+               if(self.ammo_cells > 0)
                        self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE);
                else
                        self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE);
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
+               if(g_minstagib)
+                       minstanex_ammo = 1;
+               else
+                       minstanex_ammo = autocvar_g_balance_minstanex_ammo;
+
+               // if the laser uses load, we also consider its ammo for reloading
+               if(autocvar_g_balance_minstanex_reload_ammo && autocvar_g_balance_minstanex_laser_ammo && self.clip_load < min(minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo)) // forced reload
+                       W_Minstanex_Reload();
+               else if(autocvar_g_balance_minstanex_reload_ammo && self.clip_load < minstanex_ammo) // forced reload
+                       W_Minstanex_Reload();
+               else if (self.BUTTON_ATCK)
                {
                        if (weapon_prepareattack(0, autocvar_g_balance_minstanex_refire))
                        {
@@ -196,6 +280,15 @@ float w_minstanex(float req)
                        {
                                self.jump_interval = time + autocvar_g_balance_laser_primary_refire * W_WeaponRateFactor();
 
+                               // decrease ammo for the laser?
+                               if(autocvar_g_balance_minstanex_laser_ammo)
+                               {
+                                       if(autocvar_g_balance_minstanex_reload_ammo)
+                                               self.clip_load -= autocvar_g_balance_minstanex_laser_ammo;
+                                       else
+                                               self.ammo_cells -= autocvar_g_balance_minstanex_laser_ammo;
+                               }
+
                                // ugly minstagib hack to reuse the fire mode of the laser
                                float w;
                                w = self.weapon;
@@ -215,25 +308,39 @@ float w_minstanex(float req)
                precache_sound ("weapons/nexwhoosh1.wav");
                precache_sound ("weapons/nexwhoosh2.wav");
                precache_sound ("weapons/nexwhoosh3.wav");
+               precache_sound ("weapons/reload.wav");
                w_laser(WR_PRECACHE);
        }
        else if (req == WR_SETUP)
        {
                weapon_setup(WEP_MINSTANEX);
+               W_Minstanex_SetAmmoCounter();
                self.minstanex_lasthit = 0;
        }
        else if (req == WR_CHECKAMMO1)
        {
-               if (g_minstagib)
-                       return self.ammo_cells >= 1;
-               else
-                       return self.ammo_cells >= autocvar_g_balance_minstanex_ammo;
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_minstanex_ammo;
+               ammo_amount += (autocvar_g_balance_minstanex_reload_ammo && self.minstanex_load >= autocvar_g_balance_minstanex_ammo);
+               return ammo_amount;
        }
        else if (req == WR_CHECKAMMO2)
-               return TRUE;
+       {
+               if(!autocvar_g_balance_minstanex_laser_ammo)
+                       return TRUE;
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_minstanex_laser_ammo;
+               ammo_amount += (autocvar_g_balance_minstanex_reload_ammo && self.minstanex_load >= autocvar_g_balance_minstanex_laser_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_RESETPLAYER)
        {
                self.minstanex_lasthit = 0;
+
+               // all weapons must be fully loaded when we spawn
+               self.minstanex_load = autocvar_g_balance_minstanex_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Minstanex_Reload();
        }
        return TRUE;
 };
index 4bc8130290d674260716b7fd7500354941aefc1d..a27cffadc9196621fdfa74aecc5356d1fba27a37 100644 (file)
@@ -2,6 +2,62 @@
 REGISTER_WEAPON(NEX, w_nex, IT_CELLS, 7, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_HIGH, "nex", "nex", _("Nex"))
 #else
 #ifdef SVQC
+
+// weapon load persistence, for weapons that support reloading
+.float nex_load;
+
+void W_Nex_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_nex_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.nex_load;
+               self.clip_size = autocvar_g_balance_nex_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Nex_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_nex_reload_ammo && self.ammo_cells) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_cells -= 1;
+       }
+       self.nex_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_nex_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Nex_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_nex_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_cells, min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_nex_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_nex_reload_time, W_Nex_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void SendCSQCNexBeamParticle(float charge) {
        vector v;
        v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
@@ -74,8 +130,17 @@ void W_Nex_Attack (float issecondary)
        if (trace_ent.solid == SOLID_BSP && !(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT))
                Damage_DamageInfo(trace_endpos, mydmg, 0, 0, myforce * w_shotdir, WEP_NEX, self);
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_cells = self.ammo_cells - myammo;
+       {
+               if(autocvar_g_balance_nex_reload_ammo)
+               {
+                       self.clip_load -= myammo;
+                       self.nex_load = self.clip_load;
+               }
+               else
+                       self.ammo_cells -= myammo;
+       }
 }
 
 void spawnfunc_weapon_nex (void); // defined in t_items.qc
@@ -84,6 +149,7 @@ void spawnfunc_weapon_nex (void); // defined in t_items.qc
 float w_nex(float req)
 {
        float dt;
+       float ammo_amount;
        if (req == WR_AIM)
        {
                self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE);
@@ -102,70 +168,89 @@ float w_nex(float req)
                                self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_nex_secondary_chargepool_pause_health_regen);
                        }
 
-               if (self.BUTTON_ATCK)
+               if(autocvar_g_balance_nex_reload_ammo && self.clip_load < min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo)) // forced reload
+                       W_Nex_Reload();
+               else
                {
-                       if (weapon_prepareattack(0, autocvar_g_balance_nex_primary_refire))
+                       if (self.BUTTON_ATCK)
                        {
-                               W_Nex_Attack(0);
-                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_primary_animtime, w_ready);
+                               if (weapon_prepareattack(0, autocvar_g_balance_nex_primary_refire))
+                               {
+                                       W_Nex_Attack(0);
+                                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_primary_animtime, w_ready);
+                               }
                        }
-               }
-               if ((autocvar_g_balance_nex_secondary_charge && !autocvar_g_balance_nex_secondary) ? self.BUTTON_ZOOM : self.BUTTON_ATCK2)
-               {
-                       if(autocvar_g_balance_nex_secondary_charge)
+                       if ((autocvar_g_balance_nex_secondary_charge && !autocvar_g_balance_nex_secondary) ? self.BUTTON_ZOOM : self.BUTTON_ATCK2)
                        {
-                               self.nex_charge_rottime = time + autocvar_g_balance_nex_charge_rot_pause;
-                               dt = frametime / W_TICSPERFRAME;
-
-                               if(self.nex_charge < 1)
+                               if(autocvar_g_balance_nex_secondary_charge)
                                {
-                                       if(autocvar_g_balance_nex_secondary_chargepool)
+                                       self.nex_charge_rottime = time + autocvar_g_balance_nex_charge_rot_pause;
+                                       dt = frametime / W_TICSPERFRAME;
+
+                                       if(self.nex_charge < 1)
                                        {
-                                               if(autocvar_g_balance_nex_secondary_ammo)
+                                               if(autocvar_g_balance_nex_secondary_chargepool)
                                                {
-                                                       // always deplete if secondary is held
-                                                       self.nex_chargepool_ammo = max(0, self.nex_chargepool_ammo - autocvar_g_balance_nex_secondary_ammo * dt);
+                                                       if(autocvar_g_balance_nex_secondary_ammo)
+                                                       {
+                                                               // always deplete if secondary is held
+                                                               self.nex_chargepool_ammo = max(0, self.nex_chargepool_ammo - autocvar_g_balance_nex_secondary_ammo * dt);
 
-                                                       dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
-                                                       self.nex_chargepool_pauseregen_finished = time + autocvar_g_balance_nex_secondary_chargepool_pause_regen;
-                                                       dt = min(dt, self.nex_chargepool_ammo);
-                                                       dt = max(0, dt);
+                                                               dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
+                                                               self.nex_chargepool_pauseregen_finished = time + autocvar_g_balance_nex_secondary_chargepool_pause_regen;
+                                                               dt = min(dt, self.nex_chargepool_ammo);
+                                                               dt = max(0, dt);
 
-                                                       self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
+                                                               self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
+                                                       }
                                                }
-                                       }
 
-                                       else if(autocvar_g_balance_nex_secondary_ammo)
-                                       {
-                                               if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed
+                                               else if(autocvar_g_balance_nex_secondary_ammo)
                                                {
-                                                       dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
-                                                       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+                                                       if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed
                                                        {
-                                                               dt = min(dt, (self.ammo_cells - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo);
-                                                               dt = max(0, dt);
-                                                               if(dt > 0)
+                                                               dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
+                                                               if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
                                                                {
-                                                                       self.ammo_cells = max(autocvar_g_balance_nex_secondary_ammo, self.ammo_cells - autocvar_g_balance_nex_secondary_ammo * dt);
+                                                                       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+                                                                       if(autocvar_g_balance_nex_reload_ammo)
+                                                                       {
+                                                                               dt = min(dt, (self.clip_load - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo);
+                                                                               dt = max(0, dt);
+                                                                               if(dt > 0)
+                                                                               {
+                                                                                       self.clip_load = max(autocvar_g_balance_nex_secondary_ammo, self.clip_load - autocvar_g_balance_nex_secondary_ammo * dt);
+                                                                               }
+                                                                               self.nex_load = self.clip_load;
+                                                                       }
+                                                                       else
+                                                                       {
+                                                                               dt = min(dt, (self.ammo_cells - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo);
+                                                                               dt = max(0, dt);
+                                                                               if(dt > 0)
+                                                                               {
+                                                                                       self.ammo_cells = max(autocvar_g_balance_nex_secondary_ammo, self.ammo_cells - autocvar_g_balance_nex_secondary_ammo * dt);
+                                                                               }
+                                                                       }
                                                                }
+                                                               self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
                                                        }
-                                                       self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
                                                }
-                                       }
 
-                                       else
-                                       {
-                                               dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
-                                               self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
+                                               else
+                                               {
+                                                       dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
+                                                       self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
+                                               }
                                        }
                                }
-                       }
-                       else if(autocvar_g_balance_nex_secondary)
-                       {
-                               if (weapon_prepareattack(0, autocvar_g_balance_nex_secondary_refire))
+                               else if(autocvar_g_balance_nex_secondary)
                                {
-                                       W_Nex_Attack(1);
-                                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_secondary_animtime, w_ready);
+                                       if (weapon_prepareattack(0, autocvar_g_balance_nex_secondary_refire))
+                                       {
+                                               W_Nex_Attack(1);
+                                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_secondary_animtime, w_ready);
+                                       }
                                }
                        }
                }
@@ -195,13 +280,36 @@ float w_nex(float req)
                precache_sound ("weapons/nexwhoosh1.wav");
                precache_sound ("weapons/nexwhoosh2.wav");
                precache_sound ("weapons/nexwhoosh3.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_NEX);
+               W_Nex_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_cells >= autocvar_g_balance_nex_primary_ammo;
+       {
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_primary_ammo;
+               ammo_amount += (autocvar_g_balance_nex_reload_ammo && self.nex_load >= autocvar_g_balance_nex_primary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_cells >= autocvar_g_balance_nex_primary_ammo; // don't allow charging if we don't have enough ammo
+       {
+               // don't allow charging if we don't have enough ammo
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_nex_reload_ammo && self.nex_load >= autocvar_g_balance_nex_secondary_ammo);
+               return ammo_amount;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.nex_load = autocvar_g_balance_nex_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Nex_Reload();
+       }
+
        return TRUE;
 };
 #endif
index 4e9a2cd706d91b359c60f37dd0e92f079add2162..d8a418ebb06c9931730e6ec80c0e372ec414390b 100644 (file)
@@ -7,6 +7,12 @@ REGISTER_WEAPON(PORTO, w_porto, 0, 0, WEP_TYPE_OTHER, 0, "porto" , "porto", _("P
 .float porto_v_angle_held;
 .vector right_vector;
 
+void W_Porto_SetAmmoCounter()
+{
+       // this weapon doesn't have a reload system, so always set the clip to 0 when switching to it
+       self.clip_load = self.clip_size = 0; // also keeps crosshair ammo from displaying
+}
+
 void W_Porto_Success (void)
 {
        if(self.owner == world)
@@ -270,7 +276,10 @@ float w_porto(float req)
                precache_sound ("porto/unsupported.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_PORTO);
+               W_Porto_SetAmmoCounter();
+       }
        else if (req == WR_RESETPLAYER)
        {
                self.porto_current = world;
index 21874b79053a00f3dafe378d763c82931a3edc6e..471350484faa4b0109272f4e345a3ddbf4a2d8d1 100644 (file)
@@ -5,6 +5,61 @@ REGISTER_WEAPON(ROCKET_LAUNCHER, w_rlauncher, IT_ROCKETS, 9, WEP_FLAG_NORMAL | W
 .float rl_release;
 .float rl_detonate_later;
 
+// weapon load persistence, for weapons that support reloading
+.float rocketlauncher_load;
+
+void W_RocketLauncher_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_rocketlauncher_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.rocketlauncher_load;
+               self.clip_size = autocvar_g_balance_rocketlauncher_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_RocketLauncher_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_rocketlauncher_reload_ammo && self.ammo_rockets) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_rockets -= 1;
+       }
+       self.rocketlauncher_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_rocketlauncher_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_RocketLauncher_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_rocketlauncher_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_rockets, autocvar_g_balance_rocketlauncher_ammo))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_rocketlauncher_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_rocketlauncher_reload_time, W_RocketLauncher_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_Rocket_Unregister()
 {
        if(self.owner && self.owner.lastrocket == self)
@@ -248,8 +303,17 @@ void W_Rocket_Attack (void)
        local entity missile;
        local entity flash;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_rocketlauncher_ammo;
+       {
+               if(autocvar_g_balance_rocketlauncher_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_rocketlauncher_ammo;
+                       self.rocketlauncher_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_rocketlauncher_ammo;
+       }
 
        W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CHAN_WEAPON, autocvar_g_balance_rocketlauncher_damage);
        pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
@@ -305,6 +369,8 @@ float w_rlauncher(float req)
 {
        entity rock;
        float rockfound;
+       float ammo_amount;
+
        if (req == WR_AIM)
        {
                // aim and decide to fire if appropriate
@@ -402,32 +468,37 @@ float w_rlauncher(float req)
        }
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
+               if(autocvar_g_balance_rocketlauncher_reload_ammo && self.clip_load < autocvar_g_balance_rocketlauncher_ammo) // forced reload
+                       W_RocketLauncher_Reload();
+               else
                {
-                       if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop)
-                       if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire))
+                       if (self.BUTTON_ATCK)
                        {
-                               W_Rocket_Attack();
-                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready);
-                               self.rl_release = 0;
+                               if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop)
+                               if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire))
+                               {
+                                       W_Rocket_Attack();
+                                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready);
+                                       self.rl_release = 0;
+                               }
                        }
-               }
-               else
-                       self.rl_release = 1;
+                       else
+                               self.rl_release = 1;
 
-               if (self.BUTTON_ATCK2)
-               {
-                       rockfound = 0;
-                       for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.owner == self)
+                       if (self.BUTTON_ATCK2)
                        {
-                               if(!rock.rl_detonate_later)
+                               rockfound = 0;
+                               for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.owner == self)
                                {
-                                       rock.rl_detonate_later = TRUE;
-                                       rockfound = 1;
+                                       if(!rock.rl_detonate_later)
+                                       {
+                                               rock.rl_detonate_later = TRUE;
+                                               rockfound = 1;
+                                       }
                                }
+                               if(rockfound)
+                                       sound (self, CHAN_WEAPON2, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM);
                        }
-                       if(rockfound)
-                               sound (self, CHAN_WEAPON2, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM);
                }
        }
        else if (req == WR_PRECACHE)
@@ -439,24 +510,38 @@ float w_rlauncher(float req)
                precache_sound ("weapons/rocket_det.wav");
                precache_sound ("weapons/rocket_fire.wav");
                precache_sound ("weapons/rocket_mode.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
        {
                weapon_setup(WEP_ROCKET_LAUNCHER);
+               W_RocketLauncher_SetAmmoCounter();
                self.rl_release = 1;
        }
        else if (req == WR_CHECKAMMO1)
        {
                // don't switch while guiding a missile
-               if ((ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER)
-                       && self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
-                       return FALSE;
+               if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER)
+               {
+                       if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
+                               ammo_amount = FALSE;
+                       if(autocvar_g_balance_electro_reload_ammo && self.minelayer_load < autocvar_g_balance_rocketlauncher_ammo)
+                               ammo_amount = FALSE;
+               }
+               return ammo_amount;
        }
        else if (req == WR_CHECKAMMO2)
                return FALSE;
        else if (req == WR_RESETPLAYER)
        {
                self.rl_release = 0;
+
+               // all weapons must be fully loaded when we spawn
+               self.rocketlauncher_load = autocvar_g_balance_rocketlauncher_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_RocketLauncher_Reload();
        }
        return TRUE;
 };
index 81d55a2265e62387359c843f37636462fd7afac6..9e02e2eca0895d117c8092c27137b8c0b4f329cd 100644 (file)
@@ -5,6 +5,61 @@ REGISTER_WEAPON(SEEKER, w_seeker, IT_ROCKETS, 8, WEP_FLAG_NORMAL | WEP_TYPE_SPLA
 //.float proxytime; = autoswitch
 //.float tl; = wait
 
+// weapon load persistence, for weapons that support reloading
+.float seeker_load;
+
+void W_Seeker_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_seeker_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.seeker_load;
+               self.clip_size = autocvar_g_balance_seeker_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Seeker_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_seeker_reload_ammo && self.ammo_rockets) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_rockets -= 1;
+       }
+       self.seeker_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_seeker_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Seeker_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_seeker_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_rockets, min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_seeker_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_seeker_reload_time, W_Seeker_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void Seeker_Missile_Explode ()
 {
        self.event_damage = SUB_Null;
@@ -158,8 +213,17 @@ void Seeker_Fire_Missile(vector f_diff)
 {
        local entity missile;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_seeker_missile_ammo;
+       {
+               if(autocvar_g_balance_seeker_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_seeker_missile_ammo;
+                       self.seeker_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_seeker_missile_ammo;
+       }
 
        makevectors(self.v_angle);
        W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", CHAN_WEAPON, 0);
@@ -294,8 +358,17 @@ void Seeker_Tag_Touch()
 void Seeker_Fire_Tag()
 {
        local entity missile;
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_seeker_tag_ammo;
+       {
+               if(autocvar_g_balance_seeker_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_seeker_tag_ammo;
+                       self.seeker_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_seeker_tag_ammo;
+       }
 
        W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CHAN_WEAPON, autocvar_g_balance_seeker_missile_damage * autocvar_g_balance_seeker_missile_count);
 
@@ -353,8 +426,17 @@ void Seeker_Fire_Flac()
        vector f_diff;
        float c;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_rockets = self.ammo_rockets - autocvar_g_balance_seeker_flac_ammo;
+       {
+               if(autocvar_g_balance_seeker_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_seeker_flac_ammo;
+                       self.seeker_load = self.clip_load;
+               }
+               else
+                       self.ammo_rockets -= autocvar_g_balance_seeker_flac_ammo;
+       }
 
        c = mod(self.bulletcounter, 4);
        switch(c)
@@ -413,25 +495,33 @@ void spawnfunc_weapon_seeker (void)
 
 float w_seeker(float req)
 {
+       float ammo_amount;
+
        if (req == WR_AIM)
                self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, 20, FALSE);
 
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
+               if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo)) // forced reload
+                       W_Seeker_Reload();
+
+               else if (self.BUTTON_ATCK)
+               {
                        if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire))
                        {
                                Seeker_Fire_Tag();
                                weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_seeker_tag_animtime, w_ready);
                        }
+               }
 
-               if (self.BUTTON_ATCK2)
+               else if (self.BUTTON_ATCK2)
+               {
                        if (weapon_prepareattack(1, autocvar_g_balance_seeker_flac_refire))
                        {
                                Seeker_Fire_Flac();
                                weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_flac_animtime, w_ready);
                        }
-
+               }
        }
        else if (req == WR_PRECACHE)
        {
@@ -441,13 +531,34 @@ float w_seeker(float req)
                precache_sound ("weapons/tag_fire.wav");
                precache_sound ("weapons/flac_fire.wav");
                precache_sound ("weapons/seeker_fire.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_SEEKER);
+               W_Seeker_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo + autocvar_g_balance_seeker_missile_ammo;
+       {
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_seeker_missile_ammo;
+               ammo_amount += (autocvar_g_balance_seeker_reload_ammo && self.seeker_load >= autocvar_g_balance_seeker_missile_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_rockets >= autocvar_g_balance_seeker_flac_ammo;
+       {
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_seeker_flac_ammo;
+               ammo_amount += (autocvar_g_balance_seeker_reload_ammo && self.seeker_load >= autocvar_g_balance_seeker_flac_ammo);
+               return ammo_amount;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.seeker_load = autocvar_g_balance_seeker_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Seeker_Reload();
+       }
        return TRUE;
 };
 #endif
index 6d0d094eb404c7800de4316a68397d04b7e0cbef..fa398933b38671ecf94a2fd7f7b39c7eb1ba03a7 100644 (file)
@@ -2,6 +2,62 @@
 REGISTER_WEAPON(SHOTGUN, w_shotgun, IT_SHELLS, 2, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT_PICKUP_RATING_LOW, "shotgun", "shotgun", _("Shotgun"))
 #else
 #ifdef SVQC
+
+// weapon load persistence, for weapons that support reloading
+.float shotgun_load;
+
+void W_Shotgun_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_shotgun_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.shotgun_load;
+               self.clip_size = autocvar_g_balance_shotgun_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_Shotgun_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_shotgun_reload_ammo && self.ammo_shells) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_shells -= 1;
+       }
+       self.shotgun_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_shotgun_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_Shotgun_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_shotgun_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_shells, autocvar_g_balance_shotgun_primary_ammo))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_shotgun_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_shotgun_reload_time, W_Shotgun_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 void W_Shotgun_Attack (void)
 {
        float   sc;
@@ -22,12 +78,22 @@ void W_Shotgun_Attack (void)
        bulletspeed = autocvar_g_balance_shotgun_primary_speed;
        bulletconstant = autocvar_g_balance_shotgun_primary_bulletconstant;
 
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       {
+               if(autocvar_g_balance_shotgun_reload_ammo)
+               {
+                       self.clip_load -= ammoamount;
+                       self.shotgun_load = self.clip_load;
+               }
+               else
+                       self.ammo_shells -= ammoamount;
+       }
+
        W_SetupShot (self, autocvar_g_antilag_bullets && bulletspeed >= autocvar_g_antilag_bullets, 5, "weapons/shotgun_fire.wav", CHAN_WEAPON, d * bullets);
        for (sc = 0;sc < bullets;sc = sc + 1)
                fireBallisticBullet(w_shotorg, w_shotdir, spread, bulletspeed, 5, d, 0, f, WEP_SHOTGUN, 0, 1, bulletconstant);
        endFireBallisticBullet();
-       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_shells = self.ammo_shells - ammoamount;
 
        pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, autocvar_g_balance_shotgun_primary_ammo);
 
@@ -43,7 +109,6 @@ void W_Shotgun_Attack (void)
        flash.nextthink = time + 0.06;
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
        W_AttachToShotorg(flash, '5 0 0');
-
 }
 
 void shotgun_meleethink (void)
@@ -102,6 +167,7 @@ void spawnfunc_weapon_shotgun(); // defined in t_items.qc
 
 float w_shotgun(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
                if(vlen(self.origin-self.enemy.origin) <= autocvar_g_balance_shotgun_secondary_melee_range)
                        self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE);
@@ -109,23 +175,28 @@ float w_shotgun(float req)
                        self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
        else if (req == WR_THINK)
        {
-               if (self.BUTTON_ATCK)
+               if(autocvar_g_balance_shotgun_reload_ammo && self.clip_load < autocvar_g_balance_shotgun_primary_ammo) // forced reload
+                       W_Shotgun_Reload();
+               else
                {
-                       if (time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+                       if (self.BUTTON_ATCK)
                        {
-                               if(weapon_prepareattack(0, autocvar_g_balance_shotgun_primary_animtime))
+                               if (time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
                                {
-                                       W_Shotgun_Attack();
-                                       self.shotgun_primarytime = time + autocvar_g_balance_shotgun_primary_refire;
-                                       weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_shotgun_primary_animtime, w_ready);
+                                       if(weapon_prepareattack(0, autocvar_g_balance_shotgun_primary_animtime))
+                                       {
+                                               W_Shotgun_Attack();
+                                               self.shotgun_primarytime = time + autocvar_g_balance_shotgun_primary_refire;
+                                               weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_shotgun_primary_animtime, w_ready);
+                                       }
                                }
                        }
-               }
-               if (self.BUTTON_ATCK2 && autocvar_g_balance_shotgun_secondary)
-               if (weapon_prepareattack(1, autocvar_g_balance_shotgun_secondary_refire))
-               {
-                       // attempt forcing playback of the anim by switching to another anim (that we never play) here...
-                       weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2);
+                       if (self.BUTTON_ATCK2 && autocvar_g_balance_shotgun_secondary)
+                       if (weapon_prepareattack(1, autocvar_g_balance_shotgun_secondary_refire))
+                       {
+                               // attempt forcing playback of the anim by switching to another anim (that we never play) here...
+                               weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2);
+                       }
                }
        }
        else if (req == WR_PRECACHE)
@@ -137,15 +208,33 @@ float w_shotgun(float req)
                precache_sound ("misc/itempickup.wav");
                precache_sound ("weapons/shotgun_fire.wav");
                precache_sound ("weapons/shotgun_melee.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_SHOTGUN);
+               W_Shotgun_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_shells >= autocvar_g_balance_shotgun_primary_ammo;
+       {
+               ammo_amount = self.ammo_shells >= autocvar_g_balance_shotgun_primary_ammo;
+               ammo_amount += (autocvar_g_balance_shotgun_reload_ammo && self.shotgun_load >= autocvar_g_balance_shotgun_primary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
        {
+               // melee attack is always available
                return TRUE;
        }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.shotgun_load = autocvar_g_balance_shotgun_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_Shotgun_Reload();
+       }
        return TRUE;
 };
 #endif
index a03a9b6108491e565170634feba2b7940815a8ae..3e2d3a665e0cd93c33425198c3625c9ed9228f26 100644 (file)
@@ -8,87 +8,81 @@ REGISTER_WEAPON(SNIPERRIFLE, w_sniperrifle, IT_NAILS, 7, WEP_FLAG_NORMAL | WEP_T
 
 .float sniperrifle_accumulator;
 
-float W_SniperRifle_CheckMaxBullets(float checkammo)
+// weapon load persistence, for weapons that support reloading
+.float sniperrifle_load;
+
+void W_SniperRifle_SetAmmoCounter()
 {
-       float maxbulls;
-       maxbulls = autocvar_g_balance_sniperrifle_magazinecapacity;
-       if(!maxbulls)
-               maxbulls = 8; // match HUD
-       if(checkammo)
-               if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-                       maxbulls = min(maxbulls, floor(self.ammo_nails / min(autocvar_g_balance_sniperrifle_primary_ammo, autocvar_g_balance_sniperrifle_secondary_ammo)));
-       if(self.sniperrifle_bulletcounter > maxbulls || !autocvar_g_balance_sniperrifle_magazinecapacity)
-               self.sniperrifle_bulletcounter = maxbulls;
-       return (self.sniperrifle_bulletcounter == maxbulls);
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_sniperrifle_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.sniperrifle_load;
+               self.clip_size = autocvar_g_balance_sniperrifle_reload_ammo; // for the crosshair ammo display
+       }
 }
 
 void W_SniperRifle_ReloadedAndReady()
 {
        float t;
-       self.sniperrifle_bulletcounter = autocvar_g_balance_sniperrifle_magazinecapacity;
-       W_SniperRifle_CheckMaxBullets(TRUE);
-       t = ATTACK_FINISHED(self) - autocvar_g_balance_sniperrifle_reloadtime - 1;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_sniperrifle_reload_ammo && self.ammo_nails) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_nails -= 1;
+       }
+       self.sniperrifle_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_sniperrifle_reload_time - 1;
        ATTACK_FINISHED(self) = t;
        w_ready();
 }
 
-float W_SniperRifle_Reload()
+void W_SniperRifle_Reload()
 {
-       float t;
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_sniperrifle_reload_ammo)
+               return;
 
-       W_SniperRifle_CheckMaxBullets(TRUE);
+       if(!W_ReloadCheck(self.ammo_nails, min(autocvar_g_balance_sniperrifle_primary_ammo, autocvar_g_balance_sniperrifle_secondary_ammo)))
+               return;
 
-       if(self.ammo_nails < min(autocvar_g_balance_sniperrifle_primary_ammo, autocvar_g_balance_sniperrifle_secondary_ammo)) // when we get here, bulletcounter must be 0 or -1
-       {
-               print("cannot reload... not enough bullets\n");
-               self.sniperrifle_bulletcounter = -1; // reload later
-               W_SwitchToOtherWeapon(self);
-               return 0;
-       }
-       
-       if (self.sniperrifle_bulletcounter >= autocvar_g_balance_sniperrifle_magazinecapacity)
-               return 0;
-
-       if (self.weaponentity)
-       {
-               if (self.weaponentity.wframe == WFRAME_RELOAD)
-                       return 0;
-
-               // allow to switch away while reloading, but this will cause a new reload!
-               self.weaponentity.state = WS_READY;
-       }
+       float t;
 
-       sound (self, CHAN_WEAPON2, "weapons/campingrifle_reload.wav", VOL_BASE, ATTN_NORM);
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
 
-       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_sniperrifle_reloadtime + 1;
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_sniperrifle_reload_time + 1;
        ATTACK_FINISHED(self) = t;
 
-       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_sniperrifle_reloadtime, W_SniperRifle_ReloadedAndReady);
-
-       self.sniperrifle_bulletcounter = -1;
-
-       return 1;
-}
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_sniperrifle_reload_time, W_SniperRifle_ReloadedAndReady);
 
-void W_SniperRifle_CheckReloadAndReady()
-{
-       w_ready();
-       if(self.sniperrifle_bulletcounter <= 0)
-               if(W_SniperRifle_Reload())
-                       return;
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
 }
 
 void W_SniperRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAddedDamage, float pForce, float pSpeed, float pLifetime, float pAmmo, float deathtype, float pBulletConstant)
 {
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
        if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-               self.ammo_nails -= pAmmo;
+       {
+               if(autocvar_g_balance_sniperrifle_reload_ammo)
+               {
+                       self.clip_load -= pAmmo;
+                       self.sniperrifle_load = self.clip_load;
+               }
+               else
+                       self.ammo_nails -= pAmmo;
+       }
 
        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);
 
-       pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
+       pointparticles(particleeffectnum("sniperrifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
 
        if(self.BUTTON_ZOOM) // if zoomed, shoot from the eye
        {
@@ -104,9 +98,6 @@ void W_SniperRifle_FireBullet(float pSpread, float pDamage, float pHeadshotAdded
 
        if (autocvar_g_casings >= 2)
                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);
-       
-       self.sniperrifle_bulletcounter = self.sniperrifle_bulletcounter - 1;
-       W_SniperRifle_CheckMaxBullets(TRUE);
 }
 
 void W_SniperRifle_Attack()
@@ -137,9 +128,7 @@ void spawnfunc_weapon_campingrifle (void)
 void W_SniperRifle_BulletHail_Continue()
 {
        float r, sw, af;
-       W_SniperRifle_CheckReloadAndReady();
-       if(self.sniperrifle_bulletcounter < 0)
-               return; // reloading, so we are done
+
        sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
        af = ATTACK_FINISHED(self);
        self.switchweapon = self.weapon;
@@ -177,14 +166,15 @@ void W_SniperRifle_BulletHail(float mode, void(void) AttackFunc, float fr, float
        else
        {
                // just one shot
-               weapon_thinkf(fr, animtime, W_SniperRifle_CheckReloadAndReady);
+               weapon_thinkf(fr, animtime, w_ready);
        }
 }
 
 .float bot_secondary_sniperriflemooth;
 float w_sniperrifle(float req)
 {
-       float full;
+       float ammo_amount;
+
        if (req == WR_AIM)
        {
                self.BUTTON_ATCK=FALSE;
@@ -210,10 +200,8 @@ float w_sniperrifle(float req)
        }
        else if (req == WR_THINK)
        {
-               if(self.sniperrifle_bulletcounter < 0) // forced reload (e.g. because interrupted)
-               {
-            self.wish_reload = 1;
-               }
+               if(autocvar_g_balance_sniperrifle_reload_ammo && self.clip_load < min(autocvar_g_balance_sniperrifle_primary_ammo, autocvar_g_balance_sniperrifle_secondary_ammo)) // forced reload
+            W_SniperRifle_Reload();
                else
                {
                        self.sniperrifle_accumulator = bound(time - autocvar_g_balance_sniperrifle_bursttime, self.sniperrifle_accumulator, time);
@@ -230,7 +218,7 @@ float w_sniperrifle(float req)
                                if (autocvar_g_balance_sniperrifle_secondary)
                                {
                     if(autocvar_g_balance_sniperrifle_secondary_reload)
-                        self.wish_reload = 1;
+                        W_SniperRifle_Reload();
                     else
                     {
                         if (weapon_prepareattack_check(1, autocvar_g_balance_sniperrifle_secondary_refire))
@@ -244,49 +232,43 @@ float w_sniperrifle(float req)
                                }
                        }
                }
-        if(self.wish_reload)
-        {
-            if(self.switchweapon == self.weapon)
-            {
-                if(self.weaponentity.state == WS_READY)
-                {
-                    self.wish_reload = 0;
-                    W_SniperRifle_Reload();
-                }
-            }
-        }
        }
        else if (req == WR_PRECACHE)
        {
                precache_model ("models/weapons/g_campingrifle.md3");
                precache_model ("models/weapons/v_campingrifle.md3");
                precache_model ("models/weapons/h_campingrifle.iqm");
-               precache_sound ("weapons/campingrifle_reload.wav");
                precache_sound ("weapons/campingrifle_fire.wav");
                precache_sound ("weapons/campingrifle_fire2.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
        {
                weapon_setup(WEP_SNIPERRIFLE);
-
-               full = W_SniperRifle_CheckMaxBullets(TRUE);
-               if(autocvar_g_balance_sniperrifle_auto_reload_on_switch)
-                       if(!full)
-                               self.sniperrifle_bulletcounter = -1;
+               W_SniperRifle_SetAmmoCounter();
        }
        else if (req == WR_CHECKAMMO1)
-               return self.ammo_nails >= autocvar_g_balance_sniperrifle_primary_ammo;
+       {
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_sniperrifle_primary_ammo;
+               ammo_amount += (autocvar_g_balance_sniperrifle_reload_ammo && self.sniperrifle_load >= autocvar_g_balance_sniperrifle_primary_ammo);
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
-               return self.ammo_nails >= autocvar_g_balance_sniperrifle_secondary_ammo;
-       else if (req == WR_RELOAD)
        {
-        self.wish_reload = 1;
+               ammo_amount = self.ammo_cells >= autocvar_g_balance_sniperrifle_secondary_ammo;
+               ammo_amount += (autocvar_g_balance_sniperrifle_reload_ammo && self.sniperrifle_load >= autocvar_g_balance_sniperrifle_secondary_ammo);
+               return ammo_amount;
        }
        else if (req == WR_RESETPLAYER)
        {
                self.sniperrifle_accumulator = time - autocvar_g_balance_sniperrifle_bursttime;
-               self.sniperrifle_bulletcounter = autocvar_g_balance_sniperrifle_magazinecapacity;
-               W_SniperRifle_CheckMaxBullets(FALSE);
+
+               // all weapons must be fully loaded when we spawn
+               self.sniperrifle_load = autocvar_g_balance_sniperrifle_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_SniperRifle_Reload();
        }
        return TRUE;
 };
index 98767516ae33e5611fec209b6db0cd1bb7dbb398..0973c5f92a8a24c4da171faa91e64f24cfe05f6e 100644 (file)
@@ -7,6 +7,12 @@ REGISTER_WEAPON(TUBA, w_tuba, 0, 1, WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH, BOT_PICKU
 .entity tuba_note;
 .float tuba_smoketime;
 
+void W_Tuba_SetAmmoCounter()
+{
+       // this weapon doesn't have a reload system, so always set the clip to 0 when switching to it
+       self.clip_load = self.clip_size = 0; // also keeps crosshair ammo from displaying
+}
+
 float Tuba_GetNote(entity pl, float hittype)
 {
        float note;
@@ -236,7 +242,10 @@ float w_tuba(float req)
                //      precache_sound(TUBA_NOTE(i));
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_TUBA);
+               W_Porto_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
                return TRUE; // TODO use fuel?
        else if (req == WR_CHECKAMMO2)
index 0e563405a1fa858ebdbd6719868e30859fd89eef..360c8913345dee4cca9b38adfb9a0b15573ab357 100644 (file)
@@ -3,8 +3,63 @@ REGISTER_WEAPON(UZI, w_uzi, IT_NAILS, 3, WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN, BOT
 #else
 #ifdef SVQC
 
+// weapon load persistence, for weapons that support reloading
+.float uzi_load;
+
+void W_UZI_SetAmmoCounter()
+{
+       // set clip_load to the weapon we have switched to, if the gun uses reloading
+       if(!autocvar_g_balance_uzi_reload_ammo)
+               self.clip_load = 0; // also keeps crosshair ammo from displaying
+       else
+       {
+               self.clip_load = self.uzi_load;
+               self.clip_size = autocvar_g_balance_uzi_reload_ammo; // for the crosshair ammo display
+       }
+}
+
+void W_UZI_ReloadedAndReady()
+{
+       float t;
+
+       // now do the ammo transfer
+       self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+       while(self.clip_load < autocvar_g_balance_uzi_reload_ammo && self.ammo_nails) // make sure we don't add more ammo than we have
+       {
+               self.clip_load += 1;
+               self.ammo_nails -= 1;
+       }
+       self.uzi_load = self.clip_load;
+
+       t = ATTACK_FINISHED(self) - autocvar_g_balance_uzi_reload_time - 1;
+       ATTACK_FINISHED(self) = t;
+       w_ready();
+}
+
+void W_UZI_Reload()
+{
+       // return if reloading is disabled for this weapon
+       if(!autocvar_g_balance_uzi_reload_ammo)
+               return;
+
+       if(!W_ReloadCheck(self.ammo_nails, min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo)))
+               return;
+
+       float t;
+
+       sound (self, CHAN_WEAPON2, "weapons/reload.wav", VOL_BASE, ATTN_NORM);
+
+       t = max(time, ATTACK_FINISHED(self)) + autocvar_g_balance_uzi_reload_time + 1;
+       ATTACK_FINISHED(self) = t;
+
+       weapon_thinkf(WFRAME_RELOAD, autocvar_g_balance_uzi_reload_time, W_UZI_ReloadedAndReady);
+
+       self.old_clip_load = self.clip_load;
+       self.clip_load = -1;
+}
+
 // leilei's fancy muzzleflash stuff
-void Uzi_Flash_Go() 
+void UZI_Flash_Go() 
 {      
        self.frame = self.frame + 2;
        self.scale = self.scale * 0.5;
@@ -30,7 +85,7 @@ void UziFlash()
        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.think = UZI_Flash_Go;
        self.muzzle_flash.nextthink = time + 0.02;
        self.muzzle_flash.frame = 2;
        self.muzzle_flash.alpha = 0.75;
@@ -39,15 +94,8 @@ void UziFlash()
        self.muzzle_flash.owner = self;
 }
 
-void W_Uzi_Attack (float deathtype)
+void W_UZI_Attack (float deathtype)
 {
-       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
-       {
-               if (self.misc_bulletcounter == 1)
-                       self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_first_ammo;
-               else
-                       self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_sustained_ammo;
-       }
        W_SetupShot (self, autocvar_g_antilag_bullets && autocvar_g_balance_uzi_speed >= autocvar_g_antilag_bullets, 0, "weapons/uzi_fire.wav", CHAN_WEAPON, ((self.misc_bulletcounter == 1) ? autocvar_g_balance_uzi_first_damage : autocvar_g_balance_uzi_sustained_damage));
        if (!g_norecoil)
        {
@@ -72,6 +120,26 @@ void W_Uzi_Attack (float deathtype)
        // casing code
        if (autocvar_g_casings >= 2)
                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);
+
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       {
+               if(autocvar_g_balance_uzi_reload_ammo)
+               {
+                       if (self.misc_bulletcounter == 1)
+                               self.clip_load -= autocvar_g_balance_uzi_first_ammo;
+                       else
+                               self.clip_load -= autocvar_g_balance_uzi_sustained_ammo;
+                       self.uzi_load = self.clip_load;
+               }
+               else
+               {
+                       if (self.misc_bulletcounter == 1)
+                               self.ammo_nails -= autocvar_g_balance_uzi_first_ammo;
+                       else
+                               self.ammo_nails -= autocvar_g_balance_uzi_sustained_ammo;
+               }
+       }
 }
 
 // weapon frames
@@ -91,7 +159,7 @@ void uzi_fire1_02()
                        return;
                }
                self.misc_bulletcounter = self.misc_bulletcounter + 1;
-               W_Uzi_Attack(WEP_UZI);
+               W_UZI_Attack(WEP_UZI);
                weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02);
        }
        else
@@ -102,6 +170,18 @@ void uzi_fire1_02()
 void uzi_mode1_fire_auto()
 {
        float uzi_spread;
+
+       // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+       {
+               if(autocvar_g_balance_uzi_reload_ammo)
+               {
+                       self.clip_load -= autocvar_g_balance_uzi_sustained_ammo;
+                       self.uzi_load = self.clip_load;
+               }
+               else
+                       self.ammo_nails -= autocvar_g_balance_uzi_sustained_ammo;
+       }
        
        if (self.BUTTON_ATCK)
                weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto);
@@ -139,10 +219,6 @@ void uzi_mode1_fire_auto()
        
        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);
-       
-       if not(self.items & IT_UNLIMITED_WEAPON_AMMO)   
-               self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_sustained_ammo;
-       
 }
 
 void uzi_mode1_fire_burst()
@@ -183,6 +259,7 @@ void spawnfunc_weapon_machinegun(); // defined in t_items.qc
 
 float w_uzi(float req)
 {
+       float ammo_amount;
        if (req == WR_AIM)
                if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
                        self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
@@ -192,7 +269,9 @@ float w_uzi(float req)
                }
        else if (req == WR_THINK)
        {
-               if(autocvar_g_balance_uzi_mode == 1)
+               if(autocvar_g_balance_uzi_reload_ammo && self.clip_load < min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo)) // forced reload
+                       W_UZI_Reload();
+               else if(autocvar_g_balance_uzi_mode == 1)
                {
                        if (self.BUTTON_ATCK)
                        if (weapon_prepareattack(0, 0))
@@ -210,9 +289,18 @@ float w_uzi(float req)
                                        w_ready();
                                        return FALSE;
                                }
-                               
-                               if not(self.items & IT_UNLIMITED_WEAPON_AMMO)   
-                                       self.ammo_nails = self.ammo_nails - autocvar_g_balance_uzi_burst_ammo;
+
+                               // if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+                               if not(self.items & IT_UNLIMITED_WEAPON_AMMO)
+                               {
+                                       if(autocvar_g_balance_uzi_reload_ammo)
+                                       {
+                                               self.clip_load -= autocvar_g_balance_uzi_burst_ammo;
+                                               self.uzi_load = self.clip_load;
+                                       }
+                                       else
+                                               self.ammo_nails -= autocvar_g_balance_uzi_burst_ammo;
+                               }
 
                                self.misc_bulletcounter = autocvar_g_balance_uzi_burst * -1;
                                uzi_mode1_fire_burst();
@@ -225,7 +313,7 @@ float w_uzi(float req)
                        if (weapon_prepareattack(0, 0))
                        {
                                self.misc_bulletcounter = 1;
-                               W_Uzi_Attack(WEP_UZI); // sets attack_finished
+                               W_UZI_Attack(WEP_UZI); // sets attack_finished
                                weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02);
                        }
 
@@ -233,7 +321,7 @@ float w_uzi(float req)
                        if (weapon_prepareattack(1, 0))
                        {
                                self.misc_bulletcounter = 1;
-                               W_Uzi_Attack(WEP_UZI | HITTYPE_SECONDARY); // sets attack_finished
+                               W_UZI_Attack(WEP_UZI | HITTYPE_SECONDARY); // sets attack_finished
                                weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_first_refire, w_ready);
                        }
                }
@@ -245,19 +333,54 @@ float w_uzi(float req)
                precache_model ("models/weapons/v_uzi.md3");
                precache_model ("models/weapons/h_uzi.iqm");
                precache_sound ("weapons/uzi_fire.wav");
+               precache_sound ("weapons/reload.wav");
        }
        else if (req == WR_SETUP)
+       {
                weapon_setup(WEP_UZI);
+               W_UZI_SetAmmoCounter();
+       }
        else if (req == WR_CHECKAMMO1)
+       {
                if(autocvar_g_balance_uzi_mode == 1)
-                       return self.ammo_nails >= autocvar_g_balance_uzi_sustained_ammo;
+                       ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_sustained_ammo;
                else
-                       return self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
+                       ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
+
+               if(autocvar_g_balance_uzi_reload_ammo)
+               {
+                       if(autocvar_g_balance_uzi_mode == 1)
+                               ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_sustained_ammo;
+                       else
+                               ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_first_ammo;
+               }
+               return ammo_amount;
+       }
        else if (req == WR_CHECKAMMO2)
+       {
                if(autocvar_g_balance_uzi_mode == 1)
-                       return self.ammo_nails >= autocvar_g_balance_uzi_burst_ammo;
+                       ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_burst_ammo;
                else
-                       return self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
+                       ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
+
+               if(autocvar_g_balance_uzi_reload_ammo)
+               {
+                       if(autocvar_g_balance_uzi_mode == 1)
+                               ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_burst_ammo;
+                       else
+                               ammo_amount += self.uzi_load >= autocvar_g_balance_uzi_first_ammo;
+               }
+               return ammo_amount;
+       }
+       else if (req == WR_RESETPLAYER)
+       {
+               // all weapons must be fully loaded when we spawn
+               self.uzi_load = autocvar_g_balance_uzi_reload_ammo;
+       }
+       else if (req == WR_RELOAD)
+       {
+               W_UZI_Reload();
+       }
        return TRUE;
 };
 #endif
diff --git a/sound/weapons/campingrifle_reload.ogg b/sound/weapons/campingrifle_reload.ogg
deleted file mode 100644 (file)
index 2edb373..0000000
Binary files a/sound/weapons/campingrifle_reload.ogg and /dev/null differ
diff --git a/sound/weapons/reload.ogg b/sound/weapons/reload.ogg
new file mode 100644 (file)
index 0000000..2edb373
Binary files /dev/null and b/sound/weapons/reload.ogg differ