SERVER: Control crosshair via QuakeC

This commit is contained in:
cypress 2023-10-16 10:23:50 -04:00
parent 7e3113ec63
commit b8763ca465
13 changed files with 204 additions and 57 deletions

View file

@ -91,6 +91,7 @@ float scrollheight;
float HUD_Change_time;
float Hitmark_time;
float crosshair_spread_time;
float crosshair_pulse_grenade;
float zoom_2_time;
float broadcast_time;
float broadcast_type;

View file

@ -1145,7 +1145,18 @@ void() Draw_Crosshair =
drawline(2, [0, 0, 0], [g_width/2, g_height/2, 0], [0, 0, 1], 0.5);
}
if (!cvar("crosshair"))
hide_viewmodel = false;
if (getstatf(STAT_WEAPONZOOM) == 2 && zoom_2_time < time)
{
hide_viewmodel = true;
drawfill('0 0 0', [g_width/2 - g_height/2, g_height, 0], '0 0 0', 1, 0);
drawpic([(g_width/2 - g_height/2),0,0], "gfx/hud/scope_nb.tga", [g_height, g_height, 1], [1,1,1], 1);
drawfill([(g_width/2 + g_height/2),0,0], [g_width, g_height, 0], '0 0 0', 1, 0);
return;
}
float crosshair_value = cvar("crosshair");
if (!crosshair_value)
return;
if (!crosshair_opacity)
@ -1184,15 +1195,6 @@ void() Draw_Crosshair =
crosshair_color = TEXT_RED;
else
crosshair_color = [1, 1, 1];
hide_viewmodel = false;
if (getstatf(STAT_WEAPONZOOM) == 2 && zoom_2_time < time)
{
hide_viewmodel = true;
drawfill('0 0 0', [g_width/2 - g_height/2, g_height, 0], '0 0 0', 1, 0);
drawpic([(g_width/2 - g_height/2),0,0], "gfx/hud/scope_nb.tga", [g_height, g_height, 1], [1,1,1], 1);
drawfill([(g_width/2 + g_height/2),0,0], [g_width, g_height, 0], '0 0 0', 1, 0);
}
if (getstatf(STAT_HEALTH) < 1)
return;
@ -1216,41 +1218,61 @@ void() Draw_Crosshair =
}
}
if (getstatf(STAT_WEAPONZOOM) != 1 && getstatf(STAT_WEAPONZOOM) != 2) {
// 'O' crosshair
if (getstatf(STAT_ACTIVEWEAPON) == W_M2 || getstatf(STAT_ACTIVEWEAPON) == W_FIW || getstatf(STAT_ACTIVEWEAPON) == W_TESLA || getstatf(STAT_ACTIVEWEAPON) == W_DG3) {
float circle_offset = stringwidth("O", 0, [12, 12])/2;
drawstring([g_width/2 - circle_offset, g_height/2 - circle_offset], "O", [12, 12], crosshair_color, 1, 0);
// Standard crosshair (+)
if (crosshair_value == 1) {
int x_value, y_value;
int crosshair_offset;
crosshair_offset = CrossHairWeapon(getstatf(STAT_ACTIVEWEAPON), getstatf(STAT_PLAYERSTANCE)) + cur_spread;
if (CrossHairMaxSpread(getstatf(STAT_ACTIVEWEAPON), getstatf(STAT_PLAYERSTANCE)) < crosshair_offset)
crosshair_offset = CrossHairMaxSpread(getstatf(STAT_ACTIVEWEAPON), getstatf(STAT_PLAYERSTANCE));
if (perks & P_DEAD)
crosshair_offset *= 0.65;
crosshair_offset_step += (crosshair_offset - crosshair_offset_step) * 0.5;
// Creds to heartologic for some actually good crosshair position stuff.
vector crossSize = [1, 5];
vector screenSize = [g_width, g_height];
drawfill(screenSize / 2 - [crossSize.x, +crossSize.y * 2 + crosshair_offset_step], crossSize, crosshair_color, crosshair_opacity, 0); // top
drawfill(screenSize / 2 - [crossSize.x, -crossSize.y * 1 - crosshair_offset_step + 2], crossSize, crosshair_color, crosshair_opacity, 0); // bottom
drawfill(screenSize / 2 - [+crossSize.y * 2 + crosshair_offset_step, crossSize.x], [crossSize.y, crossSize.x], crosshair_color, crosshair_opacity, 0); // right
drawfill(screenSize / 2 - [-crossSize.y * 1 - crosshair_offset_step, crossSize.x], [crossSize.y, crossSize.x], crosshair_color, crosshair_opacity, 0); // left
}
// Area of Effect (o)
else if (crosshair_value == 2) {
float circle_offset = stringwidth("O", 0, [12, 12])/2;
drawstring([g_width/2 - circle_offset, g_height/2 - circle_offset], "O", [12, 12], crosshair_color, 1, 0);
}
// Dot crosshair (.)
else if (crosshair_value == 3) {
vector screenSize2 = [g_width, g_height];
drawfill(screenSize2 / 2 - [2, 2], [4, 4], crosshair_color, crosshair_opacity, 0); // dot
}
// Grenade crosshair
else if (crosshair_value == 4) {
if (crosshair_pulse_grenade) {
crosshair_offset_step = 0;
cur_spread = 12;
}
// '.' crosshair
else if (getstatf(STAT_ACTIVEWEAPON) == W_PANZER || getstatf(STAT_ACTIVEWEAPON) == W_LONGINUS) {
vector screenSize2 = [g_width, g_height];
drawfill(screenSize2 / 2 - [2, 2], [4, 4], crosshair_color, crosshair_opacity, 0); // dot
}
// Standard crosshair
else {
int x_value, y_value;
int crosshair_offset;
crosshair_offset = CrossHairWeapon(getstatf(STAT_ACTIVEWEAPON), getstatf(STAT_PLAYERSTANCE)) + cur_spread;
if (CrossHairMaxSpread(getstatf(STAT_ACTIVEWEAPON), getstatf(STAT_PLAYERSTANCE)) < crosshair_offset)
crosshair_offset = CrossHairMaxSpread(getstatf(STAT_ACTIVEWEAPON), getstatf(STAT_PLAYERSTANCE));
if (perks & P_DEAD)
crosshair_offset *= 0.65;
crosshair_offset_step += (crosshair_offset - crosshair_offset_step) * 0.5;
crosshair_pulse_grenade = false;
// Creds to heartologic for some actually good crosshair position stuff.
vector crossSize = [1, 5];
vector screenSize = [g_width, g_height];
int crosshair_offset2;
crosshair_offset2 = 3 + cur_spread;
crosshair_offset_step += (crosshair_offset2 - crosshair_offset_step) * 0.05;
drawfill(screenSize / 2 - [crossSize.x, +crossSize.y * 2 + crosshair_offset_step], crossSize, crosshair_color, crosshair_opacity, 0); // top
drawfill(screenSize / 2 - [crossSize.x, -crossSize.y * 1 - crosshair_offset_step], crossSize, crosshair_color, crosshair_opacity, 0); // bottom
drawfill(screenSize / 2 - [+crossSize.y * 2 + crosshair_offset_step, crossSize.x], [crossSize.y, crossSize.x], crosshair_color, crosshair_opacity, 0); // right
drawfill(screenSize / 2 - [-crossSize.y * 1 - crosshair_offset_step, crossSize.x], [crossSize.y, crossSize.x], crosshair_color, crosshair_opacity, 0); // left
}
// Creds to heartologic for some actually good crosshair position stuff.
vector crossSize2 = [1, 5];
vector screenSize3 = [g_width, g_height];
drawfill(screenSize3 / 2 - [crossSize2.x, +crossSize2.y * 2 + crosshair_offset_step], crossSize2, crosshair_color, crosshair_opacity, 0); // top
drawfill(screenSize3 / 2 - [crossSize2.x, -crossSize2.y * 1 - crosshair_offset_step + 2], crossSize2, crosshair_color, crosshair_opacity, 0); // bottom
drawfill(screenSize3 / 2 - [+crossSize2.y * 2 + crosshair_offset_step, crossSize2.x], [crossSize2.y, crossSize2.x], crosshair_color, crosshair_opacity, 0); // right
drawfill(screenSize3 / 2 - [-crossSize2.y * 1 - crosshair_offset_step, crossSize2.x], [crossSize2.y, crossSize2.x], crosshair_color, crosshair_opacity, 0); // left
}
}
@ -1556,9 +1578,7 @@ void(float width, float height) HUD_Draw =
if (!getstatf(STAT_SPECTATING) && (getstatf(STAT_HEALTH) > 1) && !score_show)
{
if (vmodel.model == GetWeaponModel(getstatf(STAT_ACTIVEWEAPON), FALSE) && vmodel.model != "" || getstatf(STAT_WEAPONZOOM) == 2)
Draw_Crosshair();
Draw_Crosshair();
if (!cvar("waypoint_mode")) {
HUD_Health(width, height);

View file

@ -1203,6 +1203,9 @@ noref void() CSQC_Parse_Event =
case EVENT_PLAYERUPDATE:
player_count = readbyte();
break;
case EVENT_GRENADEPULSE:
crosshair_pulse_grenade = true;
break;
case EVENT_WEAPONUPDATE:
float wepnum = readbyte();
string wepname = readstring();

View file

@ -321,6 +321,18 @@ void(float newtime, float newtype, entity change) PromptLevelChange =
#endif // FTE
}
#ifdef FTE
void(entity who) grenade_pulse =
{
WriteByte(MSG_MULTICAST, SVC_CGAMEPACKET);
WriteByte(MSG_MULTICAST, EVENT_GRENADEPULSE);
msg_entity = who;
multicast('0 0 0', MULTICAST_ONE);
}
#endif // FTE
void(entity who) UpdatePunchangle =
{
#ifdef FTE

View file

@ -266,6 +266,7 @@ string(float num)
// 2001-11-15 DarkPlaces general builtin functions by Lord Havoc end
void (string trackname) songegg = #500;
void () nzp_maxammo = #501;
void (entity who) grenade_pulse = #502;
//
// constants

View file

@ -28,6 +28,7 @@
float backupWepSkin;
float sound_perk_delay;
void() W_TakeOut;
void(entity person) W_HideCrosshair;
//
// --------------------
@ -115,7 +116,7 @@ void GivePerk(optional float p) {
self.weaponskin = backupWepSkin;
self.perk_delay = self.fire_delay;
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, SUB_Null, 0);
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, ReturnWeaponModel, 0);
SetPerk(self, self.perks);
}
@ -143,7 +144,8 @@ void DrinkPerk(float perk) {
self.maxspeed *= GetWeaponWalkSpeed(self.perks, self.weapon);
self.knife_delay = self.reload_delay2 = self.fire_delay2 = self.fire_delay = self.reload_delay = 3 + time;
self.knife_delay = self.reload_delay2 = self.fire_delay2 = self.fire_delay = self.reload_delay = 3 + time;
W_HideCrosshair(self);
Set_W_Frame (tempe.weapon_animduration, tempe.weapon2_animduration, 2.25, 0, PERK, GivePerk, tempe.weapon2model, true, S_RIGHT);
self = tempe;
sound(other, CHAN_ITEM, self.oldmodel, 1, ATTN_NORM);
@ -1185,6 +1187,7 @@ void PapUpgrade(entity pap, entity buyer) {
pap.weapon = self.weapon;
Weapon_RemoveWeapon(0);
W_HideCrosshair(self);
Set_W_Frame (0, 39, 2.0, 0, 0, W_PlayTakeOut, "models/machines/v_pap.mdl", true, S_BOTH);
self.weapon2model = "";
UpdateV2model(self.weapon2model, 0);

View file

@ -330,12 +330,13 @@ void () WallWeapon_TouchTrigger =
sound(other, 0, "sounds/misc/denybuy.wav", 1, 1);
return;
} else {
W_HideCrosshair(other);
addmoney(other, -self.cost2, FALSE);
other.ach_tracker_coll++;
entity tempz;
tempz = self;
self = other;
Set_W_Frame(15, 30, 2.75, 0, 0, ReturnWeaponModel, "models/weapons/knife/v_bowie.mdl", false, S_BOTH);
Set_W_Frame(15, 30, 2.75, 0, 0, W_PlayTakeOut, "models/weapons/knife/v_bowie.mdl", false, S_BOTH);
self.bowie = 1;
}
}

View file

@ -49,6 +49,7 @@
void() W_AimOut;
void() ReturnWeaponModel;
void(entity person) W_HideCrosshair;
//
// Weapon_GetPlayerAmmoInSlot(person, slot)
@ -180,7 +181,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;
self.reload_delay2 = self.fire_delay2 = self.reload_delay = self.fire_delay = self.knife_delay = time + duration + 0.2;
UpdateVmodel(self.weaponmodel, GetWepSkin(self.weapon));
self.weapon2model = GetWeapon2Model(self.weapon);
@ -242,6 +243,7 @@ void Weapon_SwapWeapons(float play_animation)
self.weapon = self.weapons[0].weapon_id;
SwitchWeapon(self.weapon);
W_HideCrosshair(self);
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, ReturnWeaponModel, 0);
#ifndef FTE
@ -272,9 +274,9 @@ void Weapon_SetActiveInSlot(float slot, float play_first_raise)
SwitchWeapon(self.weapon);
if (GetFrame(self.weapon, FIRST_TAKE_START) != 0 && play_first_raise == true)
Weapon_PlayViewModelAnimation(ANIM_FIRST_TAKE, SUB_Null, 0);
Weapon_PlayViewModelAnimation(ANIM_FIRST_TAKE, ReturnWeaponModel, 0);
else
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, SUB_Null, 0);
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, ReturnWeaponModel, 0);
#ifndef FTE
@ -328,6 +330,8 @@ void Weapon_AssignWeapon(float weapon_slot, float weapon_id, float weapon_mag, f
//
void Weapon_GiveWeapon(float weapon_id, float weapon_mag, float weapon_reserve)
{
W_HideCrosshair(self);
float should_leave = false;
// Find next available weapon slot

View file

@ -163,6 +163,8 @@ void() W_PrimeBetty =
if (self.sprinting)
W_SprintStop();
W_HideCrosshair(self);
// Play the "prime" animation for the betty viewmodel.
Set_W_Frame (0, 18, 1, 0, GRENADE, Betty_CheckForRelease, "models/weapons/grenade/v_betty.mdl", true, S_RIGHT);

View file

@ -25,6 +25,8 @@
*/
void(entity person) W_ShowCrosshair;
void() ContinueRun =
{
float startframe;
@ -157,6 +159,8 @@ void () W_Frame_Update =
}
else
{
if (self.callfuncat != self.weaponframe)
W_ShowCrosshair(self);
self.weaponframe_end = self.weaponframe = GetFrame(self.weapon,BASE_FRAME);
self.new_anim_stop = FALSE;
self.weapon_anim_type = 0;

View file

@ -36,6 +36,48 @@ void() AI_RevertEnemySolidState
float() push_away_zombies;
#endif // FTE
//
// W_HideCrosshair(person)
// Toggles off the crosshair for provided client.
// This is considered "nasty" by use of stuffcmd,
// however non-FTE has no way of better controlling
// cvars for individual clients.
//
void(entity person) W_HideCrosshair =
{
if (person == world)
return;
stuffcmd(person, "crosshair 0\n");
}
//
// W_ShowCrosshair(person)
// Toggles on the crosshair for provided client.
// This is considered "nasty" by use of stuffcmd,
// however non-FTE has no way of better controlling
// cvars for individual clients.
//
void(entity person) W_ShowCrosshair =
{
if (person == world)
return;
// Grab the type of crosshair
float crosshair_type;
// Grenades have a special crosshair type that can pulse.
if (person.grenade_delay) {
crosshair_type = 4;
} else
crosshair_type = WepDef_GetWeaponCrosshairType(person.weapon);
string crosshair_string = "crosshair ";
crosshair_string = strzone(strcat(crosshair_string, ftos(crosshair_type)));
stuffcmd(person, strcat(crosshair_string, "\n"));
strunzone(crosshair_string);
}
void() ReturnWeaponModel =
{
self.weaponmodel = GetWeaponModel(self.weapon, 0);
@ -57,11 +99,13 @@ void() ReturnWeaponModel =
// If the person is swapping, play the sprint anim if they're sprinting after swap. Otherwise it plays idle
if (self.sprinting == TRUE)
W_SprintStart();
W_ShowCrosshair(self);
}
void() W_PlayTakeOut =
{
W_HideCrosshair(self);
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, ReturnWeaponModel, 0);
}
@ -197,19 +241,25 @@ void() W_PutOut =
// We don't hold more than one weapon
if (self.weapons[1].weapon_id == 0 || self.downed)
return;
float duration = getWeaponDelay(self.weapon, PUTOUT);
W_AimOut();
W_HideCrosshair(self);
if (self.weapon_count != 1 && !self.new_anim_stop)
Weapon_PlayViewModelAnimation(ANIM_PUT_AWAY, W_PutOutHack, 0);
Weapon_PlayViewModelAnimation(ANIM_PUT_AWAY, W_PutOutHack, duration);
}
void() W_TakeOut =
{
self.isBuying = false;
float duration = getWeaponDelay(self.weapon, TAKEOUT);
W_AimOut();
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, SUB_Null, 0);
W_HideCrosshair(self);
Weapon_PlayViewModelAnimation(ANIM_TAKE_OUT, ReturnWeaponModel, duration);
}
@ -255,6 +305,8 @@ void() ContinueReload = //Special reloads
if (self.weapon == W_GUT && self.weapons[0].weapon_magazine == 10)
return;
W_HideCrosshair(self);
float delay = 0;
string modelname = GetWeaponModel(self.weapon, 0);
float startframe = 0;
@ -359,6 +411,7 @@ void(float side) W_Reload =
W_AimOut();
W_SprintStop();
W_HideCrosshair(self);
float endframe, startframe, reloadcancelframe, delay;
string modelname = "";
@ -726,7 +779,7 @@ void() LungeKnifeHit =
sound (self, CHAN_WEAPON, "sounds/weapons/knife/knife_hitbod.wav", 1, ATTN_NORM);
// Calculate melee damage
f_damage = WepDefp_CalculateMeleeDamage(self.weapon, self.bowie);
f_damage = WepDef_CalculateMeleeDamage(self.weapon, self.bowie);
if (trace_ent.classname == "ai_zombie_head")
{
@ -1178,6 +1231,8 @@ void () W_Knife =
if (self.sprinting) {
W_SprintStop();
}
W_HideCrosshair(self);
backupSkin = self.weaponskin;
self.weaponskin = 0;
@ -1356,6 +1411,8 @@ void() W_ThrowGrenade =
float endframe;
local entity nade;
W_HideCrosshair(self);
if (self.pri_grenade_state == 0) {
nade = spawn ();
nade.owner = self;
@ -1425,7 +1482,18 @@ void() checkHold =
}
else
{
self.isBuying = true;
if (self.isBuying == false) {
W_ShowCrosshair(self);
self.isBuying = true;
}
// Pulse the grenade crosshair every 1 second
float difference = rint(self.grenade_delay - time);
if (difference != self.beingrevived) {
self.beingrevived = difference;
grenade_pulse(self);
}
Set_W_Frame (2, 2, 0, 0, GRENADE, checkHold, "models/weapons/grenade/v_grenade.mdl", true, S_RIGHT);
}
}
@ -1440,11 +1508,12 @@ void() W_Grenade =
if (self.sprinting)
W_SprintStop();
W_HideCrosshair(self);
Set_W_Frame (0, 2, 0.6, 0, GRENADE, checkHold, "models/weapons/grenade/v_grenade.mdl", true, S_RIGHT);
sound (self, CHAN_WEAPON, "sounds/weapons/grenade/prime.wav", 1, ATTN_NORM);
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.6;
self.grenade_delay = time + 5;
self.seminade = true;
}

View file

@ -55,6 +55,7 @@ const float EVENT_REVIVEOFF = 38;
const float EVENT_REVIVECHANGE = 39;
const float EVENT_WEAPONRECOIL = 40;
const float EVENT_SONGPLAY = 41;
const float EVENT_GRENADEPULSE = 42;
// Define our FTE platform
#ifndef STANDARD

View file

@ -4517,7 +4517,7 @@ float(float wep) GetWeaponZoomAmount =
// Returns the amount of melee damage the Player can
// do given their weapon and Bowie Knife status.
//
float(float weapon, float has_bowie) WepDefp_CalculateMeleeDamage =
float(float weapon, float has_bowie) WepDef_CalculateMeleeDamage =
{
switch(weapon) {
case W_BK:
@ -4618,3 +4618,29 @@ float(string weapon) WepDef_GetWeaponIDFromName =
}
return W_COLT;
}
//
// WepDef_GetWeaponCrosshairType(weapon)
// Returns the type of crosshair used by active
// weapon.
// 0. No crosshair
// 1. Standard crosshair (+)
// 2. Area of Effect (o)
// 3. Dot crosshair (.) (unused).
// 4 is reserved for the grenade, do not use.
//
float WepDef_GetWeaponCrosshairType(float weapon)
{
switch(weapon) {
case W_M2:
case W_FIW:
case W_TESLA:
case W_DG3:
return 2;
case W_PANZER:
case W_LONGINUS:
return 0;
default:
return 1;
}
}