SERVER: Major Weapon Logic Revamp

This commit is contained in:
cypress 2024-01-09 17:45:23 -05:00
parent 81d7d9464a
commit 671ee73a19
23 changed files with 480 additions and 437 deletions

View File

@ -4,6 +4,7 @@
../source/shared/defs/custom.qc
../source/server/defs/custom.qc
../source/shared/weapon_defines.qc
../source/server/utilities/math.qc
../source/server/clientfuncs.qc
../source/server/hash_table.qc
@ -13,7 +14,6 @@
../source/server/utilities/weapon_utilities.qc
../source/server/utilities/game_restart.qc
../source/server/utilities/command_parser.qc
../source/server/utilities/math.qc
../source/server/player.qc
../source/server/damage.qc

View File

@ -6,6 +6,7 @@
../source/shared/defs/custom.qc
../source/server/defs/custom.qc
../source/shared/weapon_defines.qc
../source/server/utilities/math.qc
../source/server/clientfuncs.qc
../source/server/hash_table.qc
@ -15,7 +16,6 @@
../source/server/utilities/weapon_utilities.qc
../source/server/utilities/game_restart.qc
../source/server/utilities/command_parser.qc
../source/server/utilities/math.qc
../source/server/player.qc
../source/server/damage.qc

View File

@ -113,7 +113,6 @@ noref void(float apiver, string enginename, float enginever) CSQC_Init =
fullscreenval = cvar("vid_fullscreen");
// cvars for custom settings
autocvar(cl_adsmode, 0);
autocvar(cl_cinematic, 0);
autocvar(nzp_particles, 1);
autocvar(nzp_decals, 1);
@ -1426,9 +1425,6 @@ noref void() CSQC_Parse_Event =
if (Hitmark_time < time)
Hitmark_time = time + 0.2;
break;
case 4:
zoom_2_time = time + 0.05;
break;
case 5:
crosshair_spread_time = time + 70/getWeaponRecoilReturn(getstatf(STAT_ACTIVEWEAPON));
break;
@ -1472,12 +1468,6 @@ noref void() CSQC_Parse_Event =
fade_time = readbyte();
fade_type = readbyte();
break;
case EVENT_PUNCHANGLE:
vector changetest;
changetest_x = readcoord();
changetest_y = readcoord();
changetest_z = readcoord();
break;
case EVENT_SCROLLTEXT:
scrolltext = readstring();
stext = TRUE;

View File

@ -772,9 +772,14 @@ void() settings_sens2 = {
void() settings_adsmode =
{
float adsmode = cvar("cl_adsmode");
tokenize(findkeysforcommand("+button8"));
string button8_key = strtoupper(keynumtostring(stof(argv(0))));
localcmd(strcat("seta cl_adsmode ", ftos(!adsmode)));
// ADS Mode
if (button8_key == "MOUSE2")
localcmd("bind MOUSE2 \"impulse 26\"\n");
else
localcmd("bind MOUSE2 \"+button8\"\n");
}
void() setting_mastervol =
@ -1442,8 +1447,11 @@ void() Draw_Extra_CSettings =
string cset_desc;
cset_desc = "";
tokenize(findkeysforcommand("+button8"));
string button8_key = strtoupper(keynumtostring(stof(argv(0))));
// ADS Mode
if (cvar("cl_adsmode") == 0)
if (button8_key == "MOUSE2")
drawstring([320, 75], "HOLD", [14, 14], [1, 1, 1], 1, 0);
else
drawstring([320, 75], "TOGGLE", [14, 14], [1, 1, 1], 1, 0);

View File

@ -57,49 +57,48 @@ void () Waypoint_Functions =
break;
}
if(self.button8 && !self.semi)
if(self.button8 && !(self.semi_actions & SEMIACTION_WAYPOINT))
{
self.semi = true;
self.semi_actions |= SEMIACTION_WAYPOINT;
Dual_Link_Waypoints();
waypoint_action = waypoint_action + 1;
}
if (self.button0 && !self.semi)
if (self.button0 && !(self.semi_actions & SEMIACTION_WAYPOINT))
{
self.semi_actions |= SEMIACTION_WAYPOINT;
Create_New_Waypoint();
waypoint_action = waypoint_action + 1;
self.semi = true;
}
if (self.button7 && !self.semiuse)
if (self.button7 && !(self.semi_actions & SEMIACTION_WAYPOINT))
{
self.semi_actions |= SEMIACTION_WAYPOINT;
Select_Waypoint();
waypoint_action = waypoint_action + 1;
self.semiuse = true;
}
if(self.button4 && !self.semiuse)
if(self.button4 && !(self.semi_actions & SEMIACTION_WAYPOINT))
{
self.semiuse = true;
self.semi_actions |= SEMIACTION_WAYPOINT;
waypoint_action = waypoint_action + 1;
Move_Waypoint();
}
if(self.button6 && !self.semiuse)
if(self.button6 && !(self.semi_actions & SEMIACTION_WAYPOINT))
{
self.semi_actions |= SEMIACTION_WAYPOINT;
Remove_Waypoint ();
waypoint_action = waypoint_action + 1;
self.semiuse = true;
}
if(self.button5 && !self.semiuse)
if(self.button5 && !(self.semi_actions & SEMIACTION_WAYPOINT))
{
self.semi_actions |= SEMIACTION_WAYPOINT;
Make_Special_Waypoint();
waypoint_action = waypoint_action + 1;
self.semiuse = true;
}
if(!self.button0 && !self.button7 && !self.button4 && !self.button5 && !self.button6 && !self.button8)
{
self.semiuse = false;
self.semi = false;
self.semi_actions &= ~SEMIACTION_WAYPOINT;
}
self.impulse = 0;

View File

@ -344,53 +344,97 @@ void(entity who) nzp_bettyprompt =
#endif // FTE
void(entity who) UpdatePunchangle =
{
#ifdef FTE
// naievil -- shit logic lol...but result looks clean as fuck...
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EVENT_PUNCHANGLE);
WriteCoord(MSG_MULTICAST, who.punchangle_x);
WriteCoord(MSG_MULTICAST, who.punchangle_y);
WriteCoord(MSG_MULTICAST, who.punchangle_z);
msg_entity = who;
multicast('0 0 0', MULTICAST_ONE);
//
// FTE_InterpolatePunchAngle(person)
// Punch Angle interpolation from our native sourceports,
// handled in SSQC for FTE.
//
void(entity person) FTE_InterpolatePunchAngle =
{
vector last_punchangle = person.punchangle;
float lerp_factor = 0.9*frametime; // It's fine that this is server-dependent, since it's server-executed..
vector tempv = who.punchangle;
// Early-out: Let's not spam fabs calls if we have no punchangle.
if (person.punchangle_x == 0 && person.punchangle_y == 0)
return;
if (fabs(who.punchangle_x) > 0.01) {
if (who.punchangle_x >= 0.05*tempv_x)
who.punchangle_x -= 0.05*tempv_x;
else if (who.punchangle_x <= -0.05*tempv_x)
who.punchangle_x -= 0.05*tempv_x;
else
who.punchangle_x = 0;
} else
who.punchangle_x = 0;
// Begin interpolation.
for(int i = 0; i < 2; i++) {
float difference = last_punchangle[i] * lerp_factor;
if (fabs(who.punchangle_y) > 0.01) {
if (who.punchangle_y >= 0.05*tempv_y)
who.punchangle_y -= 0.05*tempv_y;
else if (who.punchangle_y <= -0.05*tempv_y)
who.punchangle_y -= 0.05*tempv_y;
else
who.punchangle_y = 0;
} else
who.punchangle_y = 0;
if (fabs(person.punchangle[i]) > 0.01) {
if (person.punchangle[i] >= difference)
person.punchangle[i] -= difference;
else if (person.punchangle[i] <= -difference)
person.punchangle[i] -= difference;
else
person.punchangle[i] = 0;
} else {
person.punchangle[i] = 0;
}
}
};
if (fabs(who.punchangle_z) > 0.01) {
if (who.punchangle_z >= 0.05*tempv_z)
who.punchangle_z -= 0.05*tempv_z;
else if (who.punchangle_z <= -0.05*tempv_z)
who.punchangle_z -= 0.05*tempv_z;
else
who.punchangle_z = 0;
} else
who.punchangle_z = 0;
//
// FTE_UpdateDynamicFOV(person)
// Context-sensitive adjustment of client's viewzoom
// factor.
//
void(entity person) FTE_UpdateDynamicFOV =
{
// Early-out if client is not zoomed in at all
// and viewzoom is correctly applied
if (!person.zoom && person.viewzoom == 1)
return;
// Calculate viewzoom FOV differential
float viewzoom_differential = 1 - (0.018*GetWeaponZoomAmount(person.weapon));
float has_scoped_weapon = WepDef_HasSniperScore(person.weapon);
// Sniper scope-in: Force-set as soon as the Scope draws
if (person.zoom == 2) {
person.viewzoom = viewzoom_differential;
return;
}
// Force-set viewzoom back to one if client is holding a scoped
// weapon and need their viewzoom adjusted.
else if (person.viewzoom != 1 && has_scoped_weapon) {
person.viewzoom = 1;
return;
} else if (has_scoped_weapon) {
return;
}
// Utilize a sigmoid curve to minimize motion sickness.
float sigmoid_input, sigmoid_output;
float viewzoom_adjustment_rate;
// If we're Aiming down the Sight and viewzoom has not reached it's end
if (person.zoom == 1 && person.viewzoom != viewzoom_differential) {
sigmoid_input = (person.viewzoom - viewzoom_differential) * 10;
sigmoid_output = 1 / (1 + exp(-sigmoid_input));
viewzoom_adjustment_rate = 0.06 * (sigmoid_output + 0.5) * (frametime*20);
if (person.viewzoom > viewzoom_differential) {
person.viewzoom -= viewzoom_adjustment_rate;
if (person.viewzoom < viewzoom_differential)
person.viewzoom = viewzoom_differential;
} else {
person.viewzoom = viewzoom_differential;
}
}
// If we're not Aiming down the Sight and viewzoom is not reset
else if (person.zoom != 1 && person.viewzoom != 1) {
// We can zoom out at a constant rate without consequence.
person.viewzoom += 0.85 * frametime;
if (person.viewzoom > 1)
person.viewzoom = 1;
}
};
#endif // FTE
}
#ifdef FTE
void(string h, float h2, entity who) pushHUD = {

View File

@ -155,7 +155,7 @@ void() W_SprintStop;
//Weaponsystem defines
void SwitchWeapon(float to);
void GetUp();
void Weapon_Logic();
void WeaponCore_ClientLogic();
void (float shotcount, float sprd, float Damage, float side) FireTrace;
.float downed;
.float fire_delay;
@ -174,18 +174,23 @@ void (float shotcount, float sprd, float Damage, float side) FireTrace;
.float currentmagbk;
.float currentmagbk2;
.float currentammobk;
.float semi;
.float semi2;
.float semiuse;
.float semiswitch; // Weapon Swap Toggle
.float seminade; // Grenade Toggle
.float semireload;
.float NeedLoad;
.string weapon2model;
.float weapon2frame;
.float reloadinterupted;
.float hitcount;
#define SEMIACTION_FIRE_RIGHT 1
#define SEMIACTION_FIRE_LEFT 2
#define SEMIACTION_USE 4
#define SEMIACTION_GRENADE 8
#define SEMIACTION_MELEE 16
#define SEMIACTION_WAYPOINT 32
#define SEMIACTION_WEAPONSWAP 64
// Semi-automatic actions (requires button release)
.float semi_actions;
#define MAX_PLAYER_WEAPONS 3
#define MULEKICK_WEAPON_SLOT 3
@ -214,7 +219,6 @@ var struct guninventory_struct
#define S_BOTH 2
//Knife
.float semiknife;
.float knife_delay;
.float bowie;

View File

@ -268,9 +268,9 @@ if (self.state == STATE_TOP || self.state == STATE_UP)
}
}
if (other.button7 && !other.semiuse)
if (other.button7 && !(other.semi_actions & SEMIACTION_USE))
{
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
if (other.points >= self.cost)
{
door_fire();
@ -296,7 +296,7 @@ if (self.state == STATE_TOP || self.state == STATE_UP)
{
centerprint (other, STR_NOTENOUGHPOINTS);
sound(other, 0, "sounds/misc/denybuy.wav", 1, 1);
other.semiuse = 1;
other.semi_actions |= SEMIACTION_USE;
}
}
}

View File

@ -339,8 +339,8 @@ void() button_touch =
centerprint(other,ftos(self.cost));
centerprint(other,"]\n");
if (other.button7 && !other.semiuse) {
other.semiuse = true;
if (other.button7 && !(other.semi_actions & SEMIACTION_USE)) {
other.semi_actions |= SEMIACTION_USE;
if(other.points >= self.cost) {
self.enemy = other;
addmoney(other, 0 - self.cost, FALSE);

View File

@ -292,7 +292,7 @@ void() touch_perk =
// sequence = perk ID in client
useprint(other, 9, price, self.sequence);
if (other.points >= price && other.button7 && !other.semiuse) {
if (other.points >= price && other.button7 && !(other.semi_actions & SEMIACTION_USE)) {
addmoney(other, -price, 0);
// Play the sound of the bottle "vending"
@ -329,12 +329,12 @@ void() touch_perk =
if (self.perk_purchase_count >= perk_purchase_limit)
Perk_MachineGoAway();
other.semiuse = true;
} else if (other.button7 && !other.semiuse) {
other.semi_actions |= SEMIACTION_USE;
} else if (other.button7 && !(other.semi_actions & SEMIACTION_USE)) {
// We tried to use, but we don't have the cash..
centerprint(other, STR_NOTENOUGHPOINTS);
sound(other, 0, "sounds/misc/denybuy.wav", 1, 1);
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
}
}
}

View File

@ -680,9 +680,9 @@ void() MBOX_Touch =
useprint (other, 7, 0, self.boxweapon.weapon);
}
if (other.button7 && !other.semiuse)
if (other.button7 && !(other.semi_actions & SEMIACTION_USE))
{
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
if (!self.boxstatus)
{
if (other.points >= mystery_box_cost)

View File

@ -279,8 +279,8 @@ void() PAP_Touch =
PAP_UpgradeWeapon(self, other);
}
// They're broke! Notify.
else if (other.button7 && other.weapon && !other.semiuse) {
other.semiuse = true;
else if (other.button7 && other.weapon && !(other.semi_actions & SEMIACTION_USE)) {
other.semi_actions |= SEMIACTION_USE;
centerprint (other, STR_NOTENOUGHPOINTS);
sound(other, 0, "sounds/misc/denybuy.wav", 1, 1);
}

View File

@ -276,8 +276,8 @@ void() teleport_touch =
useprint(other, 15, self.cost, 0);
if (other.button7 && !other.semiuse) {
other.semiuse = true;
if (other.button7 && !(other.semi_actions & SEMIACTION_USE)) {
other.semi_actions |= SEMIACTION_USE;
if (other.points < self.cost) {
centerprint(other, STR_NOTENOUGHPOINTS);

View File

@ -239,11 +239,11 @@ void zapper_touch () {
if (self.state == 0) {
useprint (other, 11, self.cost, self.weapon);
if (!other.button7 || other.semiuse) {
if (!other.button7 || (other.semi_actions & SEMIACTION_USE)) {
return;
}
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
if (other.points < self.cost) {
centerprint(other, STR_NOTENOUGHPOINTS);
sound(other, 0, "sounds/misc/denybuy.wav", 1, 1);

View File

@ -167,7 +167,7 @@ void () WallWeapon_TouchTrigger =
useprint(other, 3, wcost, wep);
if (!other.button7 || other.semiuse || other.isBuying) {
if (!other.button7 || (other.semi_actions & SEMIACTION_USE) || other.isBuying) {
return;
}
@ -181,7 +181,7 @@ void () WallWeapon_TouchTrigger =
if (ammo >= wall_ammo)
return;
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
// Player doesn't have enough points. Abort.
if (other.points < wcost) {
@ -225,11 +225,11 @@ void () WallWeapon_TouchTrigger =
useprint(other, 3, wcost, other.weapon);
if (!other.button7 || other.semiuse || other.isBuying) {
if (!other.button7 || (other.semi_actions & SEMIACTION_USE) || other.isBuying) {
return;
}
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
// Player doesn't have enough points. Abort.
if (other.points < wcost) {
@ -262,7 +262,7 @@ void () WallWeapon_TouchTrigger =
useprint (other, 4, self.cost, self.weapon);
if (!other.button7 || other.semiuse)
if (!other.button7 || (other.semi_actions & SEMIACTION_USE))
return;
if (other.points < self.cost2)
{
@ -288,7 +288,7 @@ void () WallWeapon_TouchTrigger =
self = oldent;
}
}
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
return;
}
else if (self.weapon == W_GRENADE)
@ -297,7 +297,7 @@ void () WallWeapon_TouchTrigger =
useprint (other, 3, self.cost2, self.weapon);
else
return;
if (!other.button7 || other.semiuse)
if (!other.button7 || (other.semi_actions & SEMIACTION_USE))
return;
if (other.points < self.cost)
{
@ -321,7 +321,7 @@ void () WallWeapon_TouchTrigger =
self = oldent;
}
}
other.semiuse = true;
other.semi_actions |= SEMIACTION_USE;
return;
}
else if (self.weapon == W_BOWIE)
@ -362,18 +362,16 @@ void () WallWeapon_TouchTrigger =
//centerprint(other, self.message);
useprint (other, 4, self.cost, self.weapon);
if (!other.button7 || other.semiuse) {
if (!other.button7 || (other.semi_actions & SEMIACTION_USE)) {
return;
}
other.semiuse = 1;
other.semi_actions |= SEMIACTION_USE;
if (other.points < self.cost) {
centerprint (other, STR_NOTENOUGHPOINTS);
sound(other, 0, "sounds/misc/denybuy.wav", 1, 1);
return;
}
other.semiuse = true;
other.ach_tracker_coll++;
sound(other, 0, "sounds/misc/ching.wav", 1, 1);

View File

@ -420,11 +420,6 @@ void() PlayerPreThink =
#ifdef FTE
if (self.viewzoom > 0.97)
self.viewzoom -= 0.015;
else if (self.viewzoom < 0.97)
self.viewzoom = 0.97;
// viewbob when running
self.punchangle_y = 0.6*sin(time*10);
@ -435,11 +430,6 @@ void() PlayerPreThink =
} else if (!self.sprinting && !self.zoom) {
#ifdef FTE
if (self.viewzoom < 1)
self.viewzoom += 0.015;
else
self.viewzoom = 1;
if (checkMovement(-1))
self.punchangle_x = 0.25*sin(time*15);
@ -514,7 +504,7 @@ void() PlayerPreThink =
if (cvar("waypoint_mode")) {
Waypoint_Logic();
} else {
Weapon_Logic();
WeaponCore_ClientLogic();
}
JumpCheck(0);

View File

@ -200,7 +200,7 @@ void (float animation_type, void(optional float t) end_function, float playback_
break;
}
self.reload_delay2 = self.fire_delay2 = self.reload_delay = self.fire_delay = self.knife_delay = time + (duration - 0.1);
self.switch_delay = self.reload_delay2 = self.fire_delay2 = self.reload_delay = self.fire_delay = self.knife_delay = time + (duration - 0.1);
UpdateVmodel(self.weaponmodel, GetWepSkin(self.weapon));
self.weapon2model = GetWeapon2Model(self.weapon);
@ -264,7 +264,7 @@ void Weapon_SwapWeapons(float play_animation)
SwitchWeapon(self.weapon);
W_HideCrosshair(self);
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, ReturnWeaponModel, 0);
#ifndef FTE
self.weaponskin = self.weapons[0].weapon_skin;

View File

@ -173,6 +173,5 @@ void() W_PrimeBetty =
// Subtract a betty from our inventory, set up delays, prevent use spam.
self.secondary_grenades -= 1;
self.reload_delay2 = self.fire_delay2 = self.throw_delay = self.reload_delay = self.fire_delay = time + 6;
self.seminade = true;
self.grenade_delay = self.reload_delay2 = self.fire_delay2 = self.throw_delay = self.reload_delay = self.fire_delay = time + 6;
}

View File

@ -119,12 +119,14 @@ void() W_AimIn =
if (WepDef_DoesNotADS(self.weapon))
return;
if ((self.stance == PLAYER_STANCE_PRONE) && self.velocity)
return;
if (IsDualWeapon(self.weapon) ||
self.reload_delay > time ||
self.knife_delay > time ||
self.sprinting ||
self.new_anim_stop ||
self.semiknife == true) {
self.new_anim_stop) {
return;
}
@ -134,15 +136,13 @@ void() W_AimIn =
} else if (self.zoom) {
return;
}
if (self.weapon == W_KAR_SCOPE || self.weapon == W_PTRS ||
self.weapon == W_HEADCRACKER || self.weapon == W_PENETRATOR) {
SetUpdate(self, UT_ZOOM2, 0, 0, 0);
self.zoom = 2;
if (WepDef_HasSniperScore(self.weapon))
self.scopetime = time + 0.3;
} else {
self.zoom = 1;
}
// Even if the weapon is scoped, we should still initialize
// the Zoom factor of one so it begins moving into position.
self.zoom = 1;
}
void() W_AimOut =
@ -157,12 +157,13 @@ void() W_AimOut =
self.weapon == W_HEADCRACKER || self.weapon == W_PENETRATOR) {
ReturnWeaponModel();
}
#ifndef FTE
self.zoom = 0;
#endif // FTE
// Always set ads_release to false, to avoid complicating
// actions where the player is forced to Aim Out with
// Toggled ADS.
self.ads_release = false;
}
void() W_SprintStop =
@ -229,10 +230,13 @@ void() W_PutOutHack =
void() W_PutOut =
{
// We don't hold more than one weapon
if (self.weapons[1].weapon_id == 0 || self.downed)
if (self.weapons[1].weapon_id == 0 || self.downed ||
self.switch_delay > time)
return;
float duration = getWeaponDelay(self.weapon, PUTOUT);
self.switch_delay = duration + time;
self.semi_actions |= SEMIACTION_WEAPONSWAP;
W_AimOut();
W_HideCrosshair(self);
@ -249,6 +253,7 @@ void() W_TakeOut =
self.isBuying = false;
float duration = getWeaponDelay(self.weapon, TAKEOUT);
self.switch_delay = duration + time;
W_AimOut();
W_HideCrosshair(self);
@ -977,7 +982,7 @@ void(float side) W_Fire =
if (GetFiretype(self.weapon) == FIRETYPE_FLAME && self.cooldown)
return;
if (self.semiswitch == true || self.dive)
if (self.switch_delay > time || self.dive)
return;
//First check that we can actualy fire
@ -1081,11 +1086,11 @@ void(float side) W_Fire =
// Check if weapon is semi-automatic and if it is, if it's ready to be fired.
if (Weapon_IsSemiAutomatic(self.weapon)) {
if (side == S_RIGHT) {
if (self.semi) return;
self.semi = true;
if (self.semi_actions & SEMIACTION_FIRE_RIGHT) return;
self.semi_actions |= SEMIACTION_FIRE_RIGHT;
} else if (side == S_LEFT) {
if (self.semi2) return;
self.semi2 = true;
if (self.semi_actions & SEMIACTION_FIRE_LEFT) return;
self.semi_actions |= SEMIACTION_FIRE_LEFT;
}
}
@ -1331,7 +1336,7 @@ void () W_Knife =
void() switch_nade =
{
if (self.downed || self.isBuying || !(self.grenades & 2) || self.seminade)
if (self.downed || self.isBuying || !(self.grenades & 2) || self.grenade_delay > time)
return;
if (self.pri_grenade_state == 0)
@ -1508,7 +1513,6 @@ void() W_Grenade =
self.primary_grenades -= 1;
self.reload_delay2 = self.fire_delay2 = self.throw_delay = self.reload_delay = self.fire_delay = time + 6;
self.grenade_delay = time + 5;
self.seminade = true;
}
void(float wepnum) CheckButton = {
@ -1616,8 +1620,10 @@ void () Impulse_Functions =
#endif // FTE
break;
case 22:
addmoney(self, 10000, 0);
rounds += 4;
if (cheats_have_been_activated) {
addmoney(self, 10000, 0);
rounds += 4;
}
break;
case 23:
@ -1642,6 +1648,9 @@ void () Impulse_Functions =
case 25:
switch_nade();
break;
case 26:
self.ads_release = !self.ads_release;
break;
case 33:
W_PrimeBetty();
break;
@ -1658,11 +1667,6 @@ void () Impulse_Functions =
case 32:
self.sprintflag = 1;
break;
case 110:
case 111:
W_PutOut();
self.semiswitch = true;
break;
case 100:
cvar_set("waypoint_mode", "1");
localcmd("restart\n");
@ -1681,11 +1685,6 @@ void () Impulse_Functions =
self.impulse = 0;
};
void() CheckImpulses =
{
self.impulse = 0;
}
void(entity ent) CheckPowerups =
{
if (instakill_finished >= time)
@ -1921,12 +1920,12 @@ void() CheckPlayer =
}
//
// Wep_UpdateRecoilAndSpread()
// WeaponCore_UpdateRecoilAndSpread()
// Somewhat-intelligent serverside Weapon Recoil
// update system that takes into account velocity
// and how long the weapon has been fired.
//
void() Wep_UpdateRecoilAndSpread =
void() WeaponCore_UpdateRecoilAndSpread =
{
// Moving? Our weapon spread should be the maximum.
if (self.velocity)
@ -1952,327 +1951,319 @@ void() Wep_UpdateRecoilAndSpread =
}
}
void () Weapon_Logic =
//
// WeaponCore_UpdateViewModels()
// Updates animation playback for View models,
// if applicable.
//
void() WeaponCore_UpdateViewModels =
{
// HACK HACK: Don't let the frame updater take control of hold fire.
if (self.weaponframe == GetFrame(self.weapon, FIRE_HOLD) && GetFrame(self.weapon, FIRE_HOLD) != 0 && self.weaponmodel == GetWeaponModel(self.weapon, 0)) {
// If the weapon has a "Hold Fire" frame (e.g., M2 Flamethrower)
// And it's actively firing, we shouldn't force an update.
float hold_fire_frame = GetFrame(self.weapon, FIRE_HOLD); // Avoid iterating through long switch twice.
if (self.weaponmodel == GetWeaponModel(self.weapon, false) &&
hold_fire_frame != 0 && self.weaponframe == hold_fire_frame)
return;
} else {
W_Frame_Update();
W2_Frame_Update();
// Checks passed -- update view model animations.
W_Frame_Update();
W2_Frame_Update();
};
//
// WeaponCore_ResetHoldFireWeapons()
// Allows for a "Hold Fire" weapon to reach its base
// position again.
//
void() WeaponCore_ResetHoldFireWeapon =
{
float hold_fire_frame = GetFrame(self.weapon, FIRE_HOLD); // Avoid iterating through long switch twice.
if (hold_fire_frame != 0 && self.weaponframe == hold_fire_frame &&
self.weaponmodel == GetWeaponModel(self.weapon, 0)) {
self.weaponframe = 0;
}
Impulse_Functions();
};
#ifndef FTE
// For non-FTE only to tell our engine to display the scope
//
// WeaponCore_UpdateSniperScope
// If eligible, reports to the client via
// the .zoom stat to draw the Sniper Scope
// HUD graphic.
//
void() WeaponCore_UpdateSniperScope =
{
if ((self.scopetime < time) && self.scopetime) {
self.scopetime = 0;
self.zoom = 2;
self.weapon2model = "";
self.weaponmodel = "";
}
};
//
// WeaponCore_UpdateWeaponStats()
// Specific weapon fields are used to network weapon
// stats to the client, since arrays and structs
// can't be used for this task. This is where we store
// them for pass-off.
//
inline void() WeaponCore_UpdateWeaponStats =
{
self.currentammo = self.weapons[0].weapon_reserve; // Weapon Reserve Ammo
self.currentmag = self.weapons[0].weapon_magazine; // Weapon Magazine
self.currentmag2 = self.weapons[0].weapon_magazine_left; // Left-side Weapon Magazine
};
//
// WeaponCore_FireButtonPressed()
// Executed when WeaponCore_ClientLogic
// detects that button0 has been pressed.
//
void() WeaponCore_FireButtonPressed =
{
// With keyboard/mouse input, we want akimbo weapons to actually correspond
// to which click of the mouse you've provided, which is different behavior
// to single-hand weapons, where left click fires its right-side. (Hooray
// for ternaries!).
#ifdef FTE
(IsDualWeapon(self.weapon)) ? W_Fire(S_LEFT) : W_Fire(S_RIGHT);
#else
UpdatePunchangle(self);
// Always fire right-side elsewhere.
W_Fire(S_RIGHT);
#endif // FTE
};
// If the player is aiming down the sight while prone and moving,
// force them to stop
if (self.stance == 0 && self.velocity && self.zoom) {
W_AimOut();
self.zoom = 0;
//
// WeaponCore_FireButtonReleased()
// Executed when WeaponCore_ClientLogic
// detects that button0 has been released.
//
void() WeaponCore_FireButtonReleased =
{
// Allow semi-automatic fire again -- see WeaponCore_FireButtonPressed() for platform discrepancy.
#ifdef FTE
self.viewzoom = 1;
UpdateVmodel(self.weaponmodel, GetWepSkin(self.weapon));
UpdateV2model(self.weapon2model, 0);
#endif // FTE
}
//
// Force-ADS if toggled
//
if (cvar("cl_adsmode")) {
// Toggle ADS back and forth
if (self.ads_toggle == false) {
W_AimOut();
self.zoom = 0;
#ifdef FTE
self.viewzoom = 1;
UpdateVmodel(self.weaponmodel, GetWepSkin(self.weapon));
UpdateV2model(self.weapon2model, 0);
#endif // FTE
} else if (self.reload_delay < time && self.reload_delay2 < time &&
self.knife_delay < time && self.grenade_delay < time) {
if (self.stance == 0 && self.velocity)
return;
W_AimIn();
#ifdef FTE
if (self.weapon == W_KAR_SCOPE || self.weapon == W_PTRS ||
self.weapon == W_HEADCRACKER || self.weapon == W_PENETRATOR) {
if (self.scopetime >= time) {
self.viewzoom = 1 - (0.018*GetWeaponZoomAmount(self.weapon));
self.zoom = 2;
}
} else {
self.viewzoom = 1 - (0.018*GetWeaponZoomAmount(self.weapon));
}
#endif // FTE
if (!self.zoom) {
if (self.weapon == W_KAR_SCOPE || self.weapon == W_PTRS ||
self.weapon == W_HEADCRACKER || self.weapon == W_PENETRATOR) {
SetUpdate(self, UT_ZOOM2, 0, 0, 0);
self.zoom = 2;
self.scopetime = time + 0.3;
} else {
self.zoom = 1;
}
}
}
}
//
// Fire Button Logic
// NOTE: Since the right weapon is the "normal" side there's some
// flip flop logic on FTE so that LMB will fire the left side instead.
//
// Right Trigger/LMB/etc.
if (self.button0) {
#ifdef FTE
if (IsDualWeapon(self.weapon)) { W_Fire(S_LEFT); } else { W_Fire(S_RIGHT); }
(IsDualWeapon(self.weapon)) ? self.semi_actions &= ~SEMIACTION_FIRE_LEFT : self.semi_actions &= ~SEMIACTION_FIRE_RIGHT;
#else
// Always allow right-side elsewhere.
self.semi_actions &= ~SEMIACTION_FIRE_RIGHT;
#endif // FTE
// Make sure Hold-special weapons are allowed
// back to base-frame.
WeaponCore_ResetHoldFireWeapon();
};
//
// WeaponCore_AimButtonPressed()
// Executed when WeaponCore_ClientLogic
// detects that button8 has been pressed.
//
void() WeaponCore_AimButtonPressed =
{
// If we're holding an akimbo weapon, we actually want to
// fire our secondary as opposed to Aiming down the Sight.
if (IsDualWeapon(self.weapon)) {
#ifdef FTE
W_Fire(S_RIGHT);
#endif // FTE
} else {
// Check for release for semi automatic weapons.
#ifdef FTE
if (IsDualWeapon(self.weapon)) { self.semi2 = false; } else { self.semi = false; }
// Hold fire weapons should get set back to base frame.
if (GetFrame(self.weapon, FIRE_HOLD) != 0 && self.weaponframe == GetFrame(self.weapon, FIRE_HOLD) &&
self.weaponmodel == GetWeaponModel(self.weapon, 0)) {
self.weaponframe = 0;
}
#else
self.semi = false;
W_Fire(S_LEFT);
#endif // FTE
}
// Don't permit Aiming down the Sights if the client
// is moving and Prone.
else if (!self.ads_release) {
W_AimIn();
}
};
// Left Trigger/RMB/etc.
if (self.button8) {
if (IsDualWeapon(self.weapon)) {
#ifdef FTE
W_Fire(S_RIGHT);
#else
W_Fire(S_LEFT);
#endif // FTE
} else {
if (cvar("cl_adsmode")) {
if (self.ads_release == false)
return;
self.ads_toggle = !self.ads_toggle;
self.ads_release = false;
} else {
if (self.stance == 0 && self.velocity)
return;
W_AimIn();
#ifdef FTE
if (self.zoom) {
if (self.weapon == W_KAR_SCOPE || self.weapon == W_PTRS ||
self.weapon == W_HEADCRACKER || self.weapon == W_PENETRATOR) {
if (self.scopetime >= time)
self.viewzoom = 1 - (0.018*GetWeaponZoomAmount(self.weapon));
} else {
float zoom_factor = 1 - (0.018*GetWeaponZoomAmount(self.weapon));
float sigmoid_input = (self.viewzoom - zoom_factor) * 10; // multiply by 10 to adjust the steepness of the sigmoid
float sigmoid_output = 1 / (1 + exp(-sigmoid_input)); // apply the sigmoid function
float zoom_speed = 0.06 * (sigmoid_output + 0.5) * (frametime*40); // adjust the zoom speed based on the sigmoid output
if (self.viewzoom > zoom_factor) {
self.viewzoom -= zoom_speed;
if (self.viewzoom < zoom_factor)
self.viewzoom = zoom_factor;
} else {
self.viewzoom = zoom_factor;
}
}
}
#endif // FTE
}
}
}
// AIM button is released
else if (!self.button8 && self.zoom) {
// So ADS toggle knows not to spam updates.
self.ads_release = true;
if (cvar("cl_adsmode") && self.ads_toggle == true)
return;
#ifdef FTE
if (self.weapon == W_KAR_SCOPE || self.weapon == W_PTRS ||
self.weapon == W_HEADCRACKER || self.weapon == W_PENETRATOR) {
ReturnWeaponModel();
UpdateVmodel(self.weaponmodel, GetWepSkin(self.weapon));
UpdateV2model(self.weapon2model, 0);
self.viewzoom = 1;
self.zoom = 0;
if (self.weapons[0].weapon_magazine == 0)
W_Reload(S_BOTH);
} else {
if (self.viewzoom == 0.75) {
W_AimOut();
} else {
float zoom_factor2 = 1 + (0.018 * GetWeaponZoomAmount(self.weapon)); // increase zoom factor
float sigmoid_input2 = (zoom_factor2 - self.viewzoom) * 10; // adjust sigmoid input
float sigmoid_output2 = 1 / (1 + exp(-sigmoid_input2)); // apply the sigmoid function
float zoom_speed2 = 0.06 * (sigmoid_output2 + 0.5) * (frametime * 80); // adjust the zoom speed based on the sigmoid output
if (self.viewzoom < zoom_factor2) {
self.viewzoom += zoom_speed2;
if (self.viewzoom > zoom_factor2)
self.viewzoom = zoom_factor2;
} else {
self.viewzoom = zoom_factor2;
}
}
}
// Don't stop aiming until the camera is restored
if (self.viewzoom >= 1) {
self.viewzoom = 1;
if (self.zoom != 3)
self.zoom = 0;
}
#else
//
// WeaponCore_AimButtonReleased()
// Executed when WeaponCore_ClientLogic
// detects that button8 has been released.
//
void() WeaponCore_AimButtonReleased =
{
// Lower weapon if Aiming down the Sight.
if (!self.ads_release)
W_AimOut();
#endif // FTE
} else {
// So ADS toggle knows not to spam updates.
self.ads_release = true;
// Check for release for semi automatic weapons.
if (IsDualWeapon(self.weapon)) {
// Allow akimbo semi-automatic weapons to fire again.
if (IsDualWeapon(self.weapon)) {
#ifdef FTE
self.semi = false;
self.semi_actions &= ~SEMIACTION_FIRE_RIGHT;
#else
self.semi2 = false;
self.semi_actions &= ~SEMIACTION_FIRE_LEFT;
#endif // FTE
}
};
}
}
if (!self.button7) {
self.semiuse = false;
}
if (self.button4 && !self.semiswitch && self.weapon_count != 1 && !self.zoom)
{
W_PutOut();
self.semiswitch = true;
} else if (!self.button4 && self.semiswitch && self.impulse != 110 && self.impulse != 111) {
self.semiswitch = false;
}
if (self.button3 && self.isBuying != true && self.seminade != true)
{
if (self.pri_grenade_state == 0)
W_Grenade();
else
W_PrimeBetty();
self.seminade = true;
} else if (!self.button3 && self.seminade) {
self.seminade = false;
}
//
// WeaponCore_GrenadeButtonPressed()
// Executed when WeaponCore_ClientLogic
// detects that button3 has been pressed.
//
void() WeaponCore_GrenadeButtonPressed =
{
// Leave if there is already a Grenade action
// being performed.
if (self.grenade_delay > time || (self.semi_actions & SEMIACTION_GRENADE))
return;
if (self.button5 && !self.semireload)
{
W_Reload(S_BOTH);
self.semireload = TRUE;
}
else if (!self.button5) {
self.semireload = FALSE;
}
if (self.button6 && !self.semiknife)
{
if (self.pri_grenade_state == 0)
W_Grenade();
else
W_PrimeBetty();
// Don't do this at all on FTE.
self.semi_actions |= SEMIACTION_GRENADE;
};
//
// WeaponCore_MeleeButtonPressed()
// Executed when WeaponCore_ClientLogic
// detects that button6 has been pressed.
//
void() WeaponCore_MeleeButtonPressed =
{
// On platforms with limited control schemes,
// performing a melee-action while sprinting
// triggers Dive-to-Prone.
#ifndef FTE
if (self.sprinting) {
dolphin_dive();
return;
}
if (self.sprinting) {
dolphin_dive();
return;
}
#endif // FTE
W_Knife();
self.semiknife = true;
}
else if (!self.button6)
self.semiknife = false;
CheckImpulses();
CheckPlayer();
Wep_UpdateRecoilAndSpread();
if (self.semi_actions & SEMIACTION_MELEE)
return;
// These are sent to clients in engine for stat
// reference.
self.currentammo = self.weapons[0].weapon_reserve;
self.currentmag = self.weapons[0].weapon_magazine;
self.currentmag2 = self.weapons[0].weapon_magazine_left;
}
W_Knife();
self.semi_actions |= SEMIACTION_MELEE;
};
//
// WeaponCore_ClientLogic()
// Executes every frame on clients, dictates
// weapon behaviors such as receiving inputs
// or updating animation playback.
//
void() WeaponCore_ClientLogic =
{
// Make sure information about our weapon stats
// are being networked to the client.
WeaponCore_UpdateWeaponStats();
// Viewmodel animation playback.
WeaponCore_UpdateViewModels();
// Dynamic Weapon Recoil and Spread adjustment.
WeaponCore_UpdateRecoilAndSpread();
// Register changes to client's .impulse
Impulse_Functions();
// Tells client to draw Sniper HUD element.
WeaponCore_UpdateSniperScope();
// Call to the client to do some update
// checks specific to them.
CheckPlayer();
#ifdef FTE
// FTE-only: custom Punchangle Interpolation Implementation
FTE_InterpolatePunchAngle(self);
// FTE-only: update dynamic FOV
FTE_UpdateDynamicFOV(self);
#endif // FTE
// If the client is Aiming down the Sight while prone and
// moving, force them to stop
if (self.stance == PLAYER_STANCE_PRONE && self.velocity && self.zoom) {
W_AimOut();
}
// Fire Button Pressed
if (self.button0) {
WeaponCore_FireButtonPressed();
}
// Fire Button Released
else {
WeaponCore_FireButtonReleased();
}
// If Client has ADS bound to impulse 26 (toggle),
// check if the flag is set and W_AimIn()
if (self.ads_release)
W_AimIn();
else
W_AimOut();
// ADS Button Pressed
if (self.button8) {
WeaponCore_AimButtonPressed();
}
// ADS Button Released
else {
WeaponCore_AimButtonReleased();
}
// Use Button Released
if (!self.button7) {
// Allow use to be triggered again.
self.semi_actions &= ~SEMIACTION_USE;
}
// Switch Button Pressed
if (self.button4) {
W_PutOut();
} else {
// Allow Switch to be pressed again.
self.semi_actions &= ~SEMIACTION_WEAPONSWAP;
}
// Grenade Button Pressed
if (self.button3) {
WeaponCore_GrenadeButtonPressed();
} else {
// Allow Grenade to be pressed again.
self.semi_actions &= ~SEMIACTION_GRENADE;
}
// Reload Button Pressed
if (self.button5) {
W_Reload(S_BOTH);
}
// Melee Button Pressed
if (self.button6) {
WeaponCore_MeleeButtonPressed();
}
// Melee Button Released
else {
// Allow Melee to be pressed again
self.semi_actions &= ~SEMIACTION_MELEE;
}
};

View File

@ -40,7 +40,7 @@ const float EVENT_UPDATE = 23;
const float EVENT_BROADCAST = 24;
const float EVENT_POINTUPDATE = 25;
const float EVENT_BLACKOUT = 26;
const float EVENT_PUNCHANGLE = 27;
//const float EVENT_PUNCHANGLE = 27;
const float EVENT_SCROLLTEXT = 28;
const float EVENT_WORLDDATA = 29;
const float EVENT_ACHIEVEMENT = 30;

View File

@ -4508,6 +4508,26 @@ float(float wep) GetWeaponZoomAmount =
return 0;
}
//
// WepDef_HasSniperScore(weapon)
// Returns true if the weapon should display the Scope
// HUD element when Aiming down the Sights.
//
float(float weapon) WepDef_HasSniperScore =
{
switch(weapon) {
case W_KAR_SCOPE:
case W_HEADCRACKER:
case W_PTRS:
case W_PENETRATOR:
return true;
default:
return false;
}
return false;
}
//
// WepDef_WeaponMaxSpread(weapon, stance)
// Returns the maximum amount of Spread a Weapon

View File

@ -13,10 +13,10 @@ cd bin/
# build..
echo "Compiling FTE CSQC.."
./fteqcc-cli-lin -srcfile ../progs/fte-client.src | grep -E -i "warning |error |defined |not |unknown"
./fteqcc-cli-lin -srcfile ../progs/fte-client.src | grep -E -i "warning |error |defined |not |unknown |branches"
echo "Compiling FTE SSQC.."
./fteqcc-cli-lin -O2 -srcfile ../progs/fte-server.src | grep -E -i "warning |error |defined |not |unknown"
./fteqcc-cli-lin -O2 -srcfile ../progs/fte-server.src | grep -E -i "warning |error |defined |not |unknown |branches"
echo "Compiling Standard/Id SSQC.."
./fteqcc-cli-lin -O2 -srcfile ../progs/standard.src | grep -E -i "warning |error |defined |not |unknown"
./fteqcc-cli-lin -O2 -srcfile ../progs/standard.src | grep -E -i "warning |error |defined |not |unknown |branches"
echo "End of script."

View File

@ -13,10 +13,10 @@ cd bin/
# build..
echo "Compiling FTE CSQC.."
./fteqcc-cli-mac -srcfile ../progs/fte-client.src | grep -E -i "warning |error |defined |not |unknown"
./fteqcc-cli-mac -srcfile ../progs/fte-client.src | grep -E -i "warning |error |defined |not |unknown |branches"
echo "Compiling FTE SSQC.."
./fteqcc-cli-mac -O2 -srcfile ../progs/fte-server.src | grep -E -i "warning |error |defined |not |unknown"
./fteqcc-cli-mac -O2 -srcfile ../progs/fte-server.src | grep -E -i "warning |error |defined |not |unknown |branches"
echo "Compiling Standard/Id SSQC.."
./fteqcc-cli-mac -O2 -srcfile ../progs/standard.src | grep -E -i "warning |error |defined |not |unknown"
./fteqcc-cli-mac -O2 -srcfile ../progs/standard.src | grep -E -i "warning |error |defined |not |unknown |branches"
echo "End of script."