Added loading for texternal MOTD/Mapinfo files

Added ammo purchases and caliber infotypes
Started working on the Escape gamemode
Crouching is now implemented
This commit is contained in:
Marco Hladik 2016-12-05 01:22:52 +01:00
parent 2acddc369d
commit 786b51c2e6
22 changed files with 426 additions and 62 deletions

View File

@ -4,15 +4,32 @@ Open-Source implementation of CS running on FTE QuakeWorld
# Goals
The goal of this project is to provide an open-source implementation of Counter-Strike 1.5.
Counter-Strike, being one of the most popular multiplayer games to exist, surprisingly hasn't had
a free-software implementation done until now. Meaning you could only run it on the platforms
Valve chose to support ( Microsoft Windows, MacOS X and GNU/Linux at the time of this writing )
a free-software implementation done until now.
Together we can create a foundation for people to enhance the Counter-Strike experience
by allowing them to add new weapons, gamemodes and more!
Some of the cool things you can do with this:
* Play/Host CS and CS Servers on virtually every platform. ( Main selling point )
* Customize the game to whatever extent you like.
* Create entirely new weapons!
* Create completely new and refreshing gamemodes!
* Have a guarantee to be able to play it 20 years into the future!
* Use it as a base for your own games/mods! (As long as you own the rights to the assets)
# Compiling
# Status
All the weapons are implemented, but only hostage rescue maps are supported at the moment.
No equipment is implemented, no map radar/overview and no player animations.
Basically, hostage rescue is playable as long as you don't care about grenades/kevlar.
# Compiling/Installing
1. Download the latest version of FTE QuakeWorld.
2. Download csv15full.exe and to get the cstrike folder.
3. Move both the cstrike folder and FTE QuakeWorld into a folder
4. Compile the Client and Server modules using fteqcc and put them into the cstrike folder
4. Compile the Client and Server modules using FTEQCC and put them into the cstrike folder
5. Run FTE QuakeWorld
# Special Thanks
Spike - Creator of FTE QuakeWorld and FTEQCC ( http://fte.triptohell.info/ )
TWHL - Mapping Community with CS/HL entity information ( http://twhl.info )
This repository uses no content from Half-Life nor the original CS, for credits
as to who created the ORIGINAL Counter-Strike, please visit
http://web.archive.org/web/20021016230745/http://counter-strike.net/csteam.html

View File

@ -40,7 +40,6 @@ void CSQC_UpdateView( float fWinWidth, float fWinHeight, float fGameFocus ) {
if( fGameFocus == TRUE ) {
HUD_Draw();
CSQC_VGUI_Draw();
drawstring( '320 240 0 ', sprintf( "FRAMETIME: %f", eViewModel.frame1time ) , '8 8 0', '1 1 1', 1, 0 );
}
}

View File

@ -31,7 +31,7 @@ Now you can call sounds in advance
*/
void Sound_Delayed( string sSample, float fVol, float fDelay ) {
static void Sound_Delayed_PlayBack( void ) {
print( sprintf( "[SOUND] Playing Event %s\n", self.sSoundSample ) );
//print( sprintf( "[SOUND] Playing Event %s\n", self.sSoundSample ) );
localsound( self.sSoundSample, CHAN_AUTO, self.fVolume );
remove( self );
}

View File

@ -68,6 +68,30 @@ Initialize all there is
=================
*/
void CSQC_VGUI_Init( void ) {
string sTemp;
// First load the MESSAGE OF THE DAY
filestream fmMOTD = fopen( "motd.txt", FILE_READ);
for ( int i = 0; i < 25; i++ ) {
sTemp = fgets( fmMOTD );
if not ( sTemp ) {
break;
}
sMOTDString[ i ] = sTemp;
}
fclose( fmMOTD );
// Now load the MAP DESCRIPTION
fmMOTD = fopen( sprintf( "maps/%s.txt", mapname ), FILE_READ);
for ( int i = 0; i < 35; i++ ) {
sTemp = fgets( fmMOTD );
if not ( sTemp ) {
break;
}
sMapString[ i ] = sTemp;
}
fclose( fmMOTD );
// We start on the MOTD, always
fVGUI_Display = VGUI_MOTD;
}

View File

@ -41,6 +41,9 @@ enum {
vector vVGUIWindowPos;
vector vVGUIButtonPos;
string sMOTDString[25];
string sMapString[35];
typedef struct {
string sTitle;
void( vector vPos ) vDraw;

View File

@ -65,9 +65,11 @@ void VGUI_BuyMenu_Main( vector vPos ) {
fVGUI_Display = VGUI_BM_MGS;
}
static void BuyMenu_Main_6( void ) {
sendevent( "GamePlayerBuyAmmo", "f", 0 );
fVGUI_Display = VGUI_NONE;
}
static void BuyMenu_Main_7( void ) {
sendevent( "GamePlayerBuyAmmo", "f", 1 );
fVGUI_Display = VGUI_NONE;
}
static void BuyMenu_Main_8( void ) {

View File

@ -28,8 +28,11 @@ void VGUI_MessageOfTheDay( vector vPos ) {
VGUI_Text( serverkey( "hostname" ), vPos + '16 64 0', '16 16 0');
VGUI_Text( "You are playing an early preview of this game.", vPos + '16 116 0', '8 8 0' );
VGUI_Text( "Just press OK to proceed, or whatever.", vPos + '16 132 0', '8 8 0' );
vector vTextPos = vPos + '16 116 0';
for ( int i = 0; i < 25; i++ ) {
VGUI_Text( sMOTDString[ i ], vTextPos, '8 8 0' );
vTextPos_y += 10;
}
VGUI_Button( "OK", MessageOfTheDay_ButtonOK, vPos + '16 440 0', '80 24 0' );
}

View File

@ -35,13 +35,16 @@ void VGUI_TeamSelect_Main( vector vPos ) {
fVGUI_Display = VGUI_NONE;
}
VGUI_Text( "Gamemode Title", vPos + '16 64 0', '16 16 0');
VGUI_Text( sMapString[ 0 ], vPos + '16 64 0', '16 16 0');
VGUI_Text( "This is a description of the gamemode that you are playing.", vPos + '16 116 0', '8 8 0' );
VGUI_Text( "As you can see, that stuff is not implemented yet.", vPos + '16 132 0', '8 8 0' );
VGUI_Button( "Terrorists", TeamSelect_Main_ButtonT, vPos + '16 240 0', '180 24 0' );
VGUI_Button( "Counter-Terrorists", TeamSelect_Main_ButtonCT, vPos + '16 272 0', '180 24 0' );
vector vTextPos = vPos + '224 116 0';
for ( int i = 1; i < 35; i++ ) {
VGUI_Text( sMapString[ i ], vTextPos, '8 8 0' );
vTextPos_y += 10;
}
VGUI_Button( "Terrorists", TeamSelect_Main_ButtonT, vPos + '16 116 0', '180 24 0' );
VGUI_Button( "Counter-Terrorists", TeamSelect_Main_ButtonCT, vPos + '16 148 0', '180 24 0' );
VGUI_Button( "Auto-Assign", TeamSelect_Main_ButtonAuto, vPos + '16 336 0', '180 24 0' );
VGUI_Button( "Spectate", TeamSelect_Main_ButtonSpectate, vPos + '16 368 0', '180 24 0' );

View File

@ -81,6 +81,7 @@ enum {
CALIBER_50AE = 1,
CALIBER_762MM,
CALIBER_556MM,
CALIBER_556MMBOX,
CALIBER_338MAG,
CALIBER_9MM,
CALIBER_BUCKSHOT,
@ -92,6 +93,7 @@ enum {
.int iAmmo_50AE;
.int iAmmo_762MM;
.int iAmmo_556MM;
.int iAmmo_556MMBOX;
.int iAmmo_338MAG;
.int iAmmo_9MM;
.int iAmmo_BUCKSHOT;
@ -142,6 +144,12 @@ typedef struct {
float fMaxInaccuracy;
} weaponinfo_t;
typedef struct {
int iSize;
int iMaxAmount;
int iPrice;
} ammoinfo_t;
typedef struct {
void() vDraw;
void() vPrimary;

85
Source/Server/Ammo.c Normal file
View File

@ -0,0 +1,85 @@
/*
OpenCS Project
Copyright (C) 2015 Marco "eukara" Hladik
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
ammoinfo_t ammoTable[11] = {
{ 0, 0, 0 },
{ 7, 35, 40 }, //CALIBER_50AE
{ 30, 90, 80 }, //CALIBER_762MM
{ 30, 90, 60 }, //CALIBER_556MM
{ 30, 200, 60 }, //CALIBER_556MMBOX
{ 10, 30, 125 }, //CALIBER_338MAG
{ 30, 150, 20 }, //CALIBER_9MM
{ 8, 32, 65 }, //CALIBER_BUCKSHOT
{ 12, 100, 25 }, //CALIBER_45ACP
{ 13, 52, 50 }, //CALIBER_357SIG
{ 50, 100, 50 } //CALIBER_57MM
};
void Ammo_BuyPrimary( void ) {
if ( !self.iSlotPrimary ) {
return;
}
int iRequiredAmmo = ( ammoTable[ wptTable[ self.iSlotPrimary ].iCaliber ].iMaxAmount - self.(wptTable[ self.iSlotPrimary ].iCaliberfld));
float fNew = ceil( ( (float)iRequiredAmmo / (float)ammoTable[ wptTable[ self.iSlotPrimary ].iCaliber ].iSize ) );
for ( int i = 0; i < fNew; i++ ) {
self.(wptTable[ self.iSlotPrimary ].iCaliberfld) += ammoTable[ wptTable[ self.iSlotPrimary ].iCaliber ].iSize;
self.fMoney -= ammoTable[ wptTable[ self.iSlotPrimary ].iCaliber ].iPrice;
if ( self.(wptTable[ self.iSlotPrimary ].iCaliberfld) > ammoTable[ wptTable[ self.iSlotPrimary ].iCaliber ].iMaxAmount ) {
self.(wptTable[ self.iSlotPrimary ].iCaliberfld) = ammoTable[ wptTable[ self.iSlotPrimary ].iCaliber ].iMaxAmount;
}
}
}
void Ammo_BuySecondary( void ) {
if ( !self.iSlotSecondary ) {
return;
}
int iRequiredAmmo = ( ammoTable[ wptTable[ self.iSlotSecondary ].iCaliber ].iMaxAmount - self.(wptTable[ self.iSlotSecondary ].iCaliberfld));
float fNew = ceil( ( (float)iRequiredAmmo / (float)ammoTable[ wptTable[ self.iSlotSecondary ].iCaliber ].iSize ) );
for ( int i = 0; i < fNew; i++ ) {
self.(wptTable[ self.iSlotSecondary ].iCaliberfld) += ammoTable[ wptTable[ self.iSlotSecondary ].iCaliber ].iSize;
self.fMoney -= ammoTable[ wptTable[ self.iSlotSecondary ].iCaliber ].iPrice;
if ( self.(wptTable[ self.iSlotSecondary ].iCaliberfld) > ammoTable[ wptTable[ self.iSlotSecondary ].iCaliber ].iMaxAmount ) {
self.(wptTable[ self.iSlotSecondary ].iCaliberfld) = ammoTable[ wptTable[ self.iSlotSecondary ].iCaliber ].iMaxAmount;
}
}
}
void CSEv_GamePlayerBuyAmmo_f( float fType ) {
if ( Rules_BuyingPossible() == FALSE ) {
return;
}
if ( fType == 0 ) {
Ammo_BuyPrimary();
} else {
Ammo_BuySecondary();
}
Weapon_UpdateCurrents();
self.fAttackFinished = time + 1.0;
}

View File

@ -20,6 +20,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define VEC_HULL_MIN '-16 -16 -36'
#define VEC_HULL_MAX '16 16 36'
#define VEC_PLAYER_VIEWPOS '0 0 24'
#define VEC_CHULL_MIN '-16 -16 -18'
#define VEC_CHULL_MAX '16 16 18'
#define VEC_PLAYER_CVIEWPOS '0 0 12'
// Particle Fields
float EFFECT_GUNSHOT;
@ -32,6 +38,9 @@ float EFFECT_BLOOD;
.float fMoney;
.float fStepTime;
.int iInGame;
.float fCharModel;
.int iCrouching;
.int iCrouchAttempt;
// Match specific fields
int iWon_T;
@ -40,7 +49,6 @@ int iInGamePlayers_T;
int iInGamePlayers_CT;
int fOldInGamePlayers;
float fGameState;
float fGameTime;
@ -89,9 +97,10 @@ string sCSPlayers[9] = {
"models/player/gign/gign.mdl"
};
float Rules_BuyingPossible( void );
void Timer_Begin( float fTime, float fMode);
void Spawn_RespawnClient( int iTeam );
void Spawn_CreateClient( int iTeam );
void Spawn_RespawnClient( float fTeam );
void Spawn_CreateClient( float fTeam );
void Spawn_MakeSpectator( void );
void Client_SendEvent( entity eClient, float fEVType );

View File

@ -54,12 +54,14 @@ void hostage_die( void ) {
// Happens upon calling 'use'
void hostage_use( void ) {
if ( self.eUser == world ) {
sound( self, CHAN_VOICE, sprintf( "hostage/hos%d.wav", ceil( random() * 5 ) ), 1.0, ATTN_IDLE );
self.eUser = eActivator;
self.eTargetPoint = self.eUser;
} else {
self.eUser = world;
if ( eActivator.team == TEAM_CT ) {
if ( ( self.eUser == world ) ) {
sound( self, CHAN_VOICE, sprintf( "hostage/hos%d.wav", ceil( random() * 5 ) ), 1.0, ATTN_IDLE );
self.eUser = eActivator;
self.eTargetPoint = self.eUser;
} else {
self.eUser = world;
}
}
}

View File

@ -0,0 +1,54 @@
/*
OpenCS Project
Copyright (C) 2015 Marco "eukara" Hladik
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
=================
func_escapezone_touch
=================
*/
void func_escapezone_touch( void ) {
if ( ( other.classname == "player" ) && ( other.team == TEAM_T ) ) {
}
}
/*
=================
SPAWN: func_escapezone
Entry function for the terrorist escape zone
=================
*/
void func_escapezone( void ) {
self.angles = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_TRIGGER;
if ( self.model ) {
setmodel( self, self.model );
} else {
setsize( self, self.mins, self.maxs );
}
self.model = 0;
self.touch = func_escapezone_touch;
iRescueZones++;
}

View File

@ -19,6 +19,22 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
void Input_Handle( void ) {
// TODO: Make this fast switch only
if ( self.impulse == 1 ) {
Weapon_Switch( SLOT_MELEE );
} else if ( self.impulse == 2 ) {
Weapon_Switch( SLOT_SECONDARY );
} else if ( self.impulse == 3 ) {
Weapon_Switch( SLOT_PRIMARY );
} else if ( self.impulse == 4 ) {
Weapon_Switch( SLOT_GRENADE );
}
if ( self.button3 ) {
Player_CrouchDown();
} else if ( self.iCrouching == TRUE ) {
Player_CrouchUp();
}
if ( self.button0 ) {
Weapon_PrimaryAttack( self.weapon );
@ -28,23 +44,6 @@ void Input_Handle( void ) {
Weapon_SecondaryAttack( self.weapon );
}
if ( cvar( "developer" ) == 1 ) {
if( self.impulse == 10 ) {
if ( self.weapon < ( CS_WEAPON_COUNT - 1 ) ) {
dprint( "Weapon Cheat +\n" );
self.weapon++;
CSEv_GamePlayerBuy_f( self.weapon );
}
}
if( self.impulse == 11 ) {
if ( self.weapon > 1 ) {
dprint( "Weapon Cheat -\n" );
self.weapon--;
CSEv_GamePlayerBuy_f( self.weapon );
}
}
}
self.impulse = 0;
}

View File

@ -49,3 +49,88 @@ void Player_Death( void ) {
// TODO: Finish me
}
}
/*
=================
Player_CrouchCheck
TODO: Tracebox implementation sucks, BUT SHOULD BE USED HERE.
This is just a hack because for some reason traceboxes hate HLBSP
=================
*/
float Player_CrouchCheck( entity targ ) {
float fCheck = TRUE;
vector vTrace = self.origin + '0 0 20';
traceline( vTrace + '0 0 -36', vTrace + '0 0 36', FALSE, self );
if ( trace_fraction != 1 ) {
fCheck = FALSE;
}
// Now the 4 edges
traceline( vTrace + '-16 0 -36', vTrace + '-16 0 36', FALSE, self );
if ( trace_fraction != 1 ) {
fCheck = FALSE;
}
traceline( vTrace + '0 -16 -36', vTrace + '0 -16 36', FALSE, self );
if ( trace_fraction != 1 ) {
fCheck = FALSE;
}
traceline( vTrace + '16 0 -36', vTrace + '16 0 36', FALSE, self );
if ( trace_fraction != 1 ) {
fCheck = FALSE;
}
traceline( vTrace + '0 16 -36', vTrace + '0 16 36', FALSE, self );
if ( trace_fraction != 1 ) {
fCheck = FALSE;
}
return fCheck;
}
/*
=================
Player_CrouchDown
=================
*/
void Player_CrouchDown( void ) {
if( self.movetype != MOVETYPE_WALK ) {
return;
}
if( !self.iCrouching ) {
setsize( self, VEC_CHULL_MIN, VEC_CHULL_MAX );
self.iCrouching = TRUE;
self.view_ofs = VEC_PLAYER_CVIEWPOS;
self.velocity_z = self.velocity_z + 50;
self.iCrouchAttempt = 1;
return;
}
self.iCrouchAttempt = FALSE;
}
/*
=================
Player_CrouchUp
=================
*/
void Player_CrouchUp( void ) {
if ( self.movetype != MOVETYPE_WALK ) {
return;
}
if ( self.iCrouching && ( !self.velocity_z ) && (Player_CrouchCheck( self ) ) ) {
setsize (self, VEC_HULL_MIN, VEC_HULL_MAX);
setorigin( self, self.origin + '0 0 18');
self.velocity_z = self.velocity_z + 16;
self.view_ofs = VEC_PLAYER_VIEWPOS;
self.iCrouching = FALSE;
self.iCrouchAttempt = FALSE;
return;
}
self.iCrouchAttempt = TRUE;
}

View File

@ -18,9 +18,22 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// Checks if it is possible for players to buy anything
float Rules_BuyingPossible( void ) {
if ( fGameState == GAME_ACTIVE ) {
if ( ( ( cvar( "mp_roundtime" ) * 60 ) - fGameTime ) > cvar( "mp_buytime" ) ) {
centerprint( self, sprintf( "%d seconds have passed...\nYou can't buy anything now!", cvar( "mp_buytime" ) ) );
self.fAttackFinished = time + 1.0;
return FALSE;
}
}
return TRUE;
}
// Loop through all players and respawn them
void Rules_Restart( void ) {
localcmd( "restart_ents" );
//localcmd( "restart_ents" );
entity eFind = findchain( classname, "player" );
@ -31,7 +44,7 @@ void Rules_Restart( void ) {
if ( self.health > 0 ) {
Spawn_RespawnClient( self.team );
} else {
Spawn_CreateClient( self.team );
Spawn_CreateClient( self.fCharModel );
}
self = eOldSelf;

View File

@ -20,13 +20,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
entity eLastTSpawn;
entity eLastCTSpawn;
entity Spawn_FindSpawnPoint( int iTeam ) {
entity Spawn_FindSpawnPoint( float fTeam ) {
entity eSpot, eLastSpawn;
entity eThing;
int iCount;
string sClassname;
if ( iTeam == TEAM_T ) {
if ( fTeam == TEAM_T ) {
sClassname = "info_player_deathmatch";
eSpot = eLastSpawn = eLastTSpawn;
} else {
@ -57,7 +57,7 @@ entity Spawn_FindSpawnPoint( int iTeam ) {
return eSpot;
}
void Spawn_RespawnClient( int iTeam ) {
void Spawn_RespawnClient( float fTeam ) {
entity eSpawn;
forceinfokey( self, "*spectator", "0" ); // Make sure we are known as a spectator
eSpawn = Spawn_FindSpawnPoint( self.team );
@ -76,21 +76,21 @@ void Spawn_RespawnClient( int iTeam ) {
self.fixangle = TRUE;
// Get the player-model from Defs.h's list
setmodel( self, sCSPlayers[ iTeam ] );
setmodel( self, sCSPlayers[ self.fCharModel ] );
setsize( self, VEC_HULL_MIN, VEC_HULL_MAX );
self.view_ofs = '0 0 24';
self.view_ofs = VEC_PLAYER_VIEWPOS;
self.velocity = '0 0 0';
self.frame = 1; // Idle frame
}
void Spawn_CreateClient( int iTeam ) {
void Spawn_CreateClient( float fCharModel ) {
// What team are we on - 0= Spectator, < 5 Terrorists, CT rest
if( iTeam == 0 ) {
if( fCharModel == 0 ) {
PutClientInServer();
return;
} else if( iTeam < 5 ) {
} else if( fCharModel < 5 ) {
self.team = TEAM_T;
iInGamePlayers_T++;
@ -102,7 +102,6 @@ void Spawn_CreateClient( int iTeam ) {
Weapon_AddItem( WEAPON_USP45 );
Weapon_GiveAmmo( WEAPON_USP45, 24 );
}
if( self.iInGame == FALSE ) {
@ -134,11 +133,34 @@ void Spawn_MakeSpectator( void ) {
self.(wptTable[ i ].iClipfld) = 0;
self.(wptTable[ i ].iCaliberfld) = 0;
}
// Clear the inventory
self.iSlotMelee = self.iSlotPrimary = self.iSlotSecondary = self.iSlotGrenade = 0;
}
// Event Handling, called by the Client codebase via 'sendevent'
void CSEv_GamePlayerSpawn_f( float fTeam ) {
Spawn_CreateClient( fTeam );
void CSEv_GamePlayerSpawn_f( float fChar ) {
// Only allow to spawn directly into the game if we are still freezed/inactive
if ( fGameState == GAME_ACTIVE || fGameState == GAME_END ) {
// Yeah, set the future player model and stuff but let's act dead
if( fChar == 0 ) {
PutClientInServer();
return;
} else if( fChar < 5 ) {
self.team = TEAM_T;
} else {
self.team = TEAM_CT;
}
self.classname = "player";
self.fCharModel = fChar;
self.health = 0;
Spawn_MakeSpectator();
} else {
self.fCharModel = fChar;
Spawn_CreateClient( fChar );
}
}
// Counter-Terrorist Spawnpoints

View File

@ -96,6 +96,5 @@ void multi_manager( void ) {
}
self.message = __fullspawndata;
self.think = multi_manager_use;
self.nextthink = self.ltime + 5;
self.vUse = multi_manager_use;
}

View File

@ -32,8 +32,9 @@ Defs.h
../Shared/WeaponXM1014.c
../Shared/WeaponBase.c
../Shared/Weapons.c
../Shared/Effects.c
Ammo.c
Damage.c
TraceAttack.c
Rules.c

View File

@ -87,12 +87,13 @@ float OpenCSGunBase_Reload( void ) {
return FALSE;
}
// What if we've got less in our caliberfield than we need
if ( self.(wptTable[ self.weapon ].iCaliberfld) < wptTable[ self.weapon ].iClipSize ) {
self.(wptTable[ self.weapon ].iClipfld) = self.(wptTable[ self.weapon ].iCaliberfld);
self.(wptTable[ self.weapon ].iCaliberfld) = 0;
} else {
self.(wptTable[ self.weapon ].iCaliberfld) -= ( wptTable[ self.weapon ].iClipSize - self.(wptTable[ self.weapon ].iClipfld) );
self.(wptTable[ self.weapon ].iClipfld) = wptTable[ self.weapon ].iClipSize;
self.(wptTable[ self.weapon ].iCaliberfld) -= wptTable[ self.weapon ].iClipSize;
}
self.fAttackFinished = time + wptTable[ self.weapon ].fReloadFinished;

View File

@ -25,7 +25,7 @@ weaponinfo_t wptPARA = {
WEAPON_PARA, // Identifier
SLOT_PRIMARY,
5750, // Price
CALIBER_556MM, // Caliber ID
CALIBER_556MMBOX, // Caliber ID
220, // Max Player Speed
1, // Bullets Per Shot
100, // Clip/MagSize
@ -36,7 +36,7 @@ weaponinfo_t wptPARA = {
TYPE_AUTO,
0.08, // Attack-Delay
3.0, // Reload-Delay
iAmmo_556MM, // Caliber Pointer
iAmmo_556MMBOX, // Caliber Pointer
iClip_PARA, // Clip Pointer
175, // Accuracy Divisor
0.4, // Accuracy Offset

View File

@ -53,10 +53,15 @@ weaponfunc_t wpnFuncTable[ CS_WEAPON_COUNT ] = {
};
void Weapon_Draw( float fWeapon ) {
if ( !fWeapon ) {
return;
}
wpnFuncTable[ fWeapon ].vDraw();
#ifdef SSQC
self.maxspeed = (float)wptTable[ fWeapon ].iPlayerSpeed;
self.fAttackFinished = time + 1.0;
#endif
}
@ -91,6 +96,32 @@ void Weapon_Reload( float fWeapon ) {
}
#ifdef SSQC
void Weapon_Switch( int iSlot ) {
if ( self.fAttackFinished > time ) {
return;
}
float fWeapon;
if ( iSlot == SLOT_MELEE ) {
fWeapon = self.iSlotMelee;
} else if ( iSlot == SLOT_PRIMARY ) {
fWeapon = self.iSlotPrimary;
} else if ( iSlot == SLOT_SECONDARY ) {
fWeapon = self.iSlotSecondary;
} else if ( iSlot == SLOT_GRENADE ) {
fWeapon = self.iSlotGrenade;
}
if ( !fWeapon || self.weapon == fWeapon ) {
return;
}
self.weapon = fWeapon;
Weapon_Draw( fWeapon );
}
void Weapon_UpdateCurrents( void ) {
self.iCurrentClip = self.(wptTable[ self.weapon ].iClipfld);
self.iCurrentCaliber = self.(wptTable[ self.weapon ].iCaliberfld);
@ -127,8 +158,12 @@ void Weapon_GiveAmmo( float fWeapon, float fAmount ) {
}
void CSEv_GamePlayerBuy_f( float fWeapon ) {
if ( Rules_BuyingPossible() == FALSE ) {
return;
}
Weapon_AddItem( fWeapon );
Weapon_GiveAmmo( fWeapon, 99 );
self.fMoney -= wptTable[ fWeapon ].iPrice;
self.fAttackFinished = time + 1.0;
}