/* Copyright 2016-2018 Marco "eukara" Hladik MIT LICENSE Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ void Temp_Nothing( void ) { } #ifdef SSQC string sWeaponModels[ CS_WEAPON_COUNT ] = { "", "models/w_knife.mdl", "models/w_usp.mdl", "models/w_glock18.mdl", "models/w_deagle.mdl", "models/w_p228.mdl", "models/w_elite.mdl", "models/w_fiveseven.mdl", "models/w_m3.mdl", "models/w_xm1014.mdl", "models/w_mp5.mdl", "models/w_p90.mdl", "models/w_ump45.mdl", "models/w_mac10.mdl", "models/w_tmp.mdl", "models/w_ak47.mdl", "models/w_sg552.mdl", "models/w_m4a1.mdl", "models/w_aug.mdl", "models/w_scout.mdl", "models/w_awp.mdl", "models/w_g3sg1.mdl", "models/w_sg550.mdl", "models/w_m249.mdl", "models/w_backpack.mdl", "models/w_flashbang.mdl", "models/w_hegrenade.mdl", "models/w_smokegrenade.mdl" }; #endif weaponfunc_t wpnFuncTable[ CS_WEAPON_COUNT ] = { { Temp_Nothing, Temp_Nothing, Temp_Nothing, Temp_Nothing }, { WeaponKNIFE_Draw, WeaponKNIFE_PrimaryFire, WeaponKNIFE_Secondary, Temp_Nothing }, { WeaponUSP45_Draw, WeaponUSP45_PrimaryFire, WeaponUSP45_Secondary, WeaponUSP45_Reload }, { WeaponGLOCK18_Draw, WeaponGLOCK18_PrimaryFire, WeaponGLOCK18_Secondary, WeaponGLOCK18_Reload }, { WeaponDEAGLE_Draw, WeaponDEAGLE_PrimaryFire, Temp_Nothing, WeaponDEAGLE_Reload }, { WeaponP228_Draw, WeaponP228_PrimaryFire, Temp_Nothing, WeaponP228_Reload }, { WeaponELITES_Draw, WeaponELITES_PrimaryFire, Temp_Nothing, WeaponELITES_Reload }, { WeaponFIVESEVEN_Draw, WeaponFIVESEVEN_PrimaryFire, Temp_Nothing, WeaponFIVESEVEN_Reload }, #ifdef SSQC { WeaponM3_Draw, WeaponM3_PrimaryFire, Temp_Nothing, WeaponM3_Reload }, { WeaponXM1014_Draw, WeaponXM1014_PrimaryFire, Temp_Nothing, WeaponXM1014_Reload }, #else { WeaponM3_Draw, WeaponM3_PrimaryFire, WeaponM3_Secondary, WeaponM3_Reload }, { WeaponXM1014_Draw, WeaponXM1014_PrimaryFire, WeaponXM1014_Secondary, WeaponXM1014_Reload }, #endif { WeaponMP5_Draw, WeaponMP5_PrimaryFire, Temp_Nothing, WeaponMP5_Reload }, { WeaponP90_Draw, WeaponP90_PrimaryFire, Temp_Nothing, WeaponP90_Reload }, { WeaponUMP45_Draw, WeaponUMP45_PrimaryFire, Temp_Nothing, WeaponUMP45_Reload }, { WeaponMAC10_Draw, WeaponMAC10_PrimaryFire, Temp_Nothing, WeaponMAC10_Reload }, { WeaponTMP_Draw, WeaponTMP_PrimaryFire, Temp_Nothing, WeaponTMP_Reload }, { WeaponAK47_Draw, WeaponAK47_PrimaryFire, Temp_Nothing, WeaponAK47_Reload }, { WeaponSG552_Draw, WeaponSG552_PrimaryFire, WeaponSG552_SecondaryFire, WeaponSG552_Reload }, { WeaponM4A1_Draw, WeaponM4A1_PrimaryFire, WeaponM4A1_Secondary, WeaponM4A1_Reload }, { WeaponAUG_Draw, WeaponAUG_PrimaryFire, WeaponAUG_SecondaryFire, WeaponAUG_Reload }, { WeaponSCOUT_Draw, WeaponSCOUT_PrimaryFire, WeaponSCOUT_SecondaryFire, WeaponSCOUT_Reload }, { WeaponAWP_Draw, WeaponAWP_PrimaryFire, WeaponAWP_SecondaryFire, WeaponAWP_Reload }, { WeaponG3SG1_Draw, WeaponG3SG1_PrimaryFire, WeaponG3SG1_SecondaryFire, WeaponG3SG1_Reload }, { WeaponSG550_Draw, WeaponSG550_PrimaryFire, WeaponSG550_SecondaryFire, WeaponSG550_Reload }, { WeaponPARA_Draw, WeaponPARA_PrimaryFire, Temp_Nothing, WeaponPARA_Reload }, { WeaponC4BOMB_Draw, WeaponC4BOMB_PrimaryFire, Temp_Nothing, Temp_Nothing }, { WeaponFLASHBANG_Draw, WeaponFLASHBANG_PrimaryFire, Temp_Nothing, Temp_Nothing }, { WeaponHEGRENADE_Draw, WeaponHEGRENADE_PrimaryFire, Temp_Nothing, Temp_Nothing }, { WeaponSMOKEGRENADE_Draw, WeaponSMOKEGRENADE_PrimaryFire, Temp_Nothing, Temp_Nothing } }; /* ================= Weapon_Draw ================= */ void Weapon_Draw( float fWeapon ) { if ( !fWeapon ) { return; } #ifdef SSQC // In case reloading logic is still going on self.think = Empty; self.viewzoom = 1.0; self.weapon = fWeapon; self.fAttackFinished = time + 1.0; #endif #ifdef CSQC if ( fWeaponEventPlayer != player_localentnum ) { return; } #endif wpnFuncTable[ fWeapon ].vDraw(); } /* ================= Weapon_PrimaryAttack ================= */ void Weapon_PrimaryAttack( float fWeapon ) { #ifdef SSQC if ( self.fAttackFinished > time ) { return; } if ( !( self.flags & FL_SEMI_TOGGLED ) ) { return; } #endif #ifdef CSQC if ( fWeaponEventPlayer != player_localentnum || autocvar_cl_thirdperson == TRUE ) { entity ono = findfloat( world, entnum, fWeaponEventPlayer ); if ( ono != __NULL__ ) { Animation_ShootWeapon( ono ); } return; } #endif wpnFuncTable[ fWeapon ].vPrimary(); } /* ================= Weapon_SecondaryAttack ================= */ void Weapon_SecondaryAttack( float fWeapon ) { #ifdef SSQC if ( self.fAttackFinished > time ) { return; } #endif #ifdef CSQC if ( fWeaponEventPlayer != player_localentnum || autocvar_cl_thirdperson == TRUE ) { return; } #endif wpnFuncTable[ fWeapon ].vSecondary(); } /* ================= Weapon_Reload ================= */ void Weapon_Reload( float fWeapon ) { #ifdef SSQC if ( self.fAttackFinished > time ) { return; } self.viewzoom = 1.0; #endif #ifdef CSQC if ( fWeaponEventPlayer != player_localentnum || autocvar_cl_thirdperson == TRUE ) { entity ono = findfloat( world, entnum, fWeaponEventPlayer ); if ( ono != __NULL__ ) { Animation_ReloadWeapon( ono ); } return; } #endif wpnFuncTable[ fWeapon ].vReload(); } /* ================= Weapon_GetAnimType Returns which animationset a weapon will use on a player ================= */ float Weapon_GetAnimType( float fWeapon ) { return wptTable[ fWeapon ].fAnimType; } /* ================= Weapon_GetFireRate Returns the delay between shots of a given weapon ================= */ float Weapon_GetFireRate( float fWeapon ) { return wptTable[ fWeapon ].fAttackFinished; } /* ================= Weapon_GetReloadTime Returns the reloading delay before being able to be fired again ================= */ float Weapon_GetReloadTime( float fWeapon ) { return wptTable[ fWeapon ].fReloadFinished; } /* ================= Weapon_GetSpeedM Returns the speed multiplier ================= */ float Weapon_GetSpeedM( float fWeapon ) { return wptTable[ fWeapon ].fSpeedM; } #ifdef SSQC /* ================= Weapon_Release Called when letting go one of the weapon firing buttons ================= */ void Weapon_Release( void ) { self.flags = self.flags | FL_SEMI_TOGGLED; if ( self.weapon == WEAPON_FLASHBANG ) { WeaponFLASHBANG_Release(); } else if ( self.weapon == WEAPON_HEGRENADE ) { WeaponHEGRENADE_Release(); } else if ( self.weapon == WEAPON_SMOKEGRENADE ) { WeaponSMOKEGRENADE_Release(); } else if ( self.weapon == WEAPON_C4BOMB ) { WeaponC4BOMB_Release(); } else { if (self.(wptTable[ self.weapon ].iMagfld) == 0 && self.(wptTable[ self.weapon ].iCaliberfld)) { Weapon_Reload(self.weapon); } } } /* ================= Weapon_GetSlot Returns which slot a weapon belongs to ================= */ int Weapon_GetSlot( float fWeapon ) { return wptTable[ fWeapon ].iSlot; } /* ================= Weapon_AlreadyExists Returns whether or not we have the given weapon already ================= */ float Weapon_AlreadyExists( float fWeapon ) { if ( fWeapon == WEAPON_FLASHBANG || fWeapon == WEAPON_HEGRENADE || fWeapon == WEAPON_SMOKEGRENADE ) { int iNades = self.iAmmo_FLASHBANG + self.iAmmo_HEGRENADE + self.iAmmo_SMOKEGRENADE; if ( iNades ) { return TRUE; } else { return FALSE; } } else { if ( wptTable[ fWeapon ].iSlot == SLOT_PRIMARY ) { if ( self.fSlotPrimary == fWeapon ) { return TRUE; } } else if ( wptTable[ fWeapon ].iSlot == SLOT_SECONDARY ) { if ( self.fSlotSecondary == fWeapon ) { return TRUE; } } else if ( wptTable[ fWeapon ].iSlot == SLOT_GRENADE ) { if ( self.fSlotGrenade == fWeapon ) { return TRUE; } } else if ( wptTable[ fWeapon ].iSlot == SLOT_C4BOMB ) { if ( self.fSlotC4Bomb == fWeapon ) { return TRUE; } } } return FALSE; } /* ================= Weapon_SlotEmpty Returns whether or not a slot is empty ================= */ float Weapon_SlotEmpty( int fSlot ) { if ( fSlot == SLOT_PRIMARY ) { if ( self.fSlotPrimary == 0 ) { return TRUE; } } else if ( fSlot == SLOT_SECONDARY ) { if ( self.fSlotSecondary == 0 ) { return TRUE; } } else if ( fSlot == SLOT_GRENADE ) { if ( self.fSlotGrenade == 0 ) { return TRUE; } } else if ( fSlot == SLOT_C4BOMB ) { if ( self.fSlotC4Bomb == 0 ) { return TRUE; } } return FALSE; } /* ================= Weapon_Switch Switch to the weapon in a given slot ================= */ void Weapon_Switch( int iSlot ) { float fWeapon; if ( iSlot == SLOT_MELEE ) { fWeapon = self.fSlotMelee; } else if ( iSlot == SLOT_PRIMARY ) { fWeapon = self.fSlotPrimary; } else if ( iSlot == SLOT_SECONDARY ) { fWeapon = self.fSlotSecondary; } else if ( iSlot == SLOT_GRENADE ) { fWeapon = self.fSlotGrenade; } else if ( iSlot == SLOT_C4BOMB ) { fWeapon = self.fSlotC4Bomb; } if ( !fWeapon || self.weapon == fWeapon ) { return; } Weapon_Draw( fWeapon ); } /* ================= Weapon_UpdateCurrents Update the ammo fields for the clientside display ================= */ void Weapon_UpdateCurrents( void ) { self.iCurrentMag = self.(wptTable[ self.weapon ].iMagfld); self.iCurrentCaliber = self.(wptTable[ self.weapon ].iCaliberfld); } /* ================= Weapon_AddItem Gives a weapon to the player ================= */ void Weapon_AddItem( float fWeapon ) { if ( Weapon_SlotEmpty ( wptTable[ fWeapon ].iSlot ) == FALSE ) { Weapon_DropWeapon( wptTable[ fWeapon ].iSlot ); } // Add the gun to the appropriate slot if( wptTable[ fWeapon ].iSlot == SLOT_MELEE ) { self.fSlotMelee = fWeapon; } else if ( wptTable[ fWeapon ].iSlot == SLOT_SECONDARY ) { self.fSlotSecondary = fWeapon; } else if( wptTable[ fWeapon ].iSlot == SLOT_PRIMARY ) { self.fSlotPrimary = fWeapon; } else if ( wptTable[ fWeapon ].iSlot == SLOT_GRENADE ) { self.fSlotGrenade = fWeapon; } else if ( wptTable[ fWeapon ].iSlot == SLOT_C4BOMB ) { self.fSlotC4Bomb = fWeapon; } // Make sure we've got at least one full clip self.(wptTable[ fWeapon ].iMagfld) = wptTable[ fWeapon ].iMagSize; } /* ================= Weapon_GiveAmmo Gives a specific amount of ammo to the player ================= */ void Weapon_GiveAmmo( float fWeapon, float fAmount ) { self.(wptTable[ fWeapon ].iCaliberfld ) += fAmount; Weapon_UpdateCurrents(); } /* ================= Weapon_SwitchBest Switches to the currently best suited weapon ================= */ void Weapon_SwitchBest( void ) { if ( self.fSlotSecondary ) { Weapon_Switch( SLOT_SECONDARY ); } else if ( self.fSlotPrimary ) { Weapon_Switch( SLOT_PRIMARY ); } else { Weapon_Switch( SLOT_MELEE ); } } /* ================= Weapon_DropWeapon Drop the weapon in a given slot ================= */ void Weapon_DropWeapon( int iSlot ) { static void Weapon_DropWeapon_Touch( void ) { if ( other.classname != "player" ) { return; } else if ( other == self.owner ) { return; } // No bomb for the CTs if ( ( self.weapon == WEAPON_C4BOMB ) && ( other.team == TEAM_CT ) ) { return; } entity eOld = self; self = other; if ( Weapon_SlotEmpty( Weapon_GetSlot( eOld.weapon ) ) ) { Weapon_AddItem( eOld.weapon ); Weapon_Draw( eOld.weapon ); self.(wptTable[ eOld.weapon ].iMagfld) = eOld.health; Weapon_UpdateCurrents(); } else { self = eOld; return; } self = eOld; remove( self ); } static void Weapon_DropWeapon_Think( void ) { self.owner = world; } float fWeapon; if ( iSlot == SLOT_PRIMARY ) { fWeapon = self.fSlotPrimary; self.fSlotPrimary = 0; } else if ( iSlot == SLOT_SECONDARY ) { fWeapon = self.fSlotSecondary; self.fSlotSecondary = 0; } else if ( iSlot == SLOT_GRENADE ) { fWeapon = self.fSlotGrenade; self.fSlotGrenade = 0; } else if ( iSlot == SLOT_C4BOMB ) { fWeapon = self.fSlotC4Bomb; self.fSlotC4Bomb = 0; } else { return; } entity eDrop = spawn(); setorigin( eDrop, self.origin + self.view_ofs ); setmodel( eDrop, sWeaponModels[ fWeapon ] ); eDrop.classname = "remove_me"; eDrop.owner = self; eDrop.movetype = MOVETYPE_TOSS; eDrop.solid = SOLID_TRIGGER; eDrop.weapon = fWeapon; eDrop.think = Weapon_DropWeapon_Think; eDrop.touch = Weapon_DropWeapon_Touch; eDrop.nextthink = time + 1.0f; eDrop.health = self.(wptTable[ fWeapon ].iMagfld); setsize( eDrop, '-16 -16 0', '16 16 16' ); makevectors( self.v_angle ); eDrop.velocity = aim( self, 10000 ) * 256; self.weapon = 0; Weapon_SwitchBest(); } /* ================= CSEv_PlayerBuyWeapon_f Client call for buying a weapon through GUI or console command ================= */ void CSEv_PlayerBuyWeapon_f( float fWeapon ) { if ( Rules_BuyingPossible() == FALSE ) { return; } if ( self.team == TEAM_T ) { if ( fWeapon == WEAPON_M4A1 ) { return; } if ( fWeapon == WEAPON_AUG ) { return; } if ( fWeapon == WEAPON_SG550 ) { return; } if ( fWeapon == WEAPON_FIVESEVEN ) { return; } if ( fWeapon == WEAPON_TMP ) { return; } } else if ( self.team == TEAM_CT ) { if ( fWeapon == WEAPON_AK47 ) { return; } if ( fWeapon == WEAPON_SG552 ) { return; } if ( fWeapon == WEAPON_G3SG1 ) { return; } if ( fWeapon == WEAPON_ELITES ) { return; } if ( fWeapon == WEAPON_MAC10 ) { return; } } if ( ( self.fMoney - wptTable[ fWeapon ].iPrice ) >= 0 ) { Weapon_AddItem(fWeapon); Ammo_AutoFill(fWeapon); Weapon_Draw( fWeapon ); Money_AddMoney( self, -wptTable[ fWeapon ].iPrice ); sound( self, CHAN_ITEM, "items/gunpickup2.wav", 1, ATTN_IDLE ); } else { centerprint( self, "You have insufficient funds!" ); } } /* ================= CSEv_PlayerSwitchWeapon_f Client-HUD call that switches to a specific weapon ================= */ void CSEv_PlayerSwitchWeapon_f( float fWeapon ) { if ( ( Weapon_AlreadyExists( fWeapon ) == FALSE ) && ( fWeapon != WEAPON_KNIFE ) ) { return; } if (wptTable[fWeapon].iSlot == SLOT_GRENADE) { if (fWeapon == WEAPON_HEGRENADE && !(self.iAmmo_HEGRENADE)) { return; } else if (fWeapon == WEAPON_FLASHBANG && !(self.iAmmo_FLASHBANG)) { return; } else if (fWeapon == WEAPON_SMOKEGRENADE && !(self.iAmmo_SMOKEGRENADE)) { return; } } if ( fWeapon != self.weapon ) { Weapon_Draw( fWeapon ); } } /* ================= CSEv_WeaponDrop Client call that tells us to drop the currently equipped weapon ================= */ void CSEv_WeaponDrop( void ) { Weapon_DropWeapon( wptTable[ self.weapon ].iSlot ); } #endif