Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
sv_nades.qc File Reference
Include dependency graph for sv_nades.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

class  NadeOffhand

Macros

#define NADE_TYPE_CHECK(nade_ent, nade_cvar)
#define SET_NADE_EFFECT(nade_type, exp_effect, exp_color_min, exp_color_max)
#define SPREE_ITEM(counta, countb, center, normal, gentle)

Functions

bool CanThrowNade (entity this)
 MUTATOR_HOOKFUNCTION (nades, BuildMutatorsPrettyString)
 MUTATOR_HOOKFUNCTION (nades, BuildMutatorsString)
 MUTATOR_HOOKFUNCTION (nades, ClientDisconnect)
 MUTATOR_HOOKFUNCTION (nades, Damage_Calculate)
 MUTATOR_HOOKFUNCTION (nades, DropSpecialItems)
 MUTATOR_HOOKFUNCTION (nades, ForbidThrowCurrentWeapon, CBC_ORDER_LAST)
 MUTATOR_HOOKFUNCTION (nades, MakePlayerObserver)
 MUTATOR_HOOKFUNCTION (nades, MonsterDies)
 MUTATOR_HOOKFUNCTION (nades, PlayerDies, CBC_ORDER_LAST)
 MUTATOR_HOOKFUNCTION (nades, PlayerPreThink)
 MUTATOR_HOOKFUNCTION (nades, PlayerSpawn)
 MUTATOR_HOOKFUNCTION (nades, PutClientInServer)
 MUTATOR_HOOKFUNCTION (nades, reset_map_global)
 MUTATOR_HOOKFUNCTION (nades, SpectateCopy)
 MUTATOR_HOOKFUNCTION (nades, VehicleEnter)
void nade_beep (entity this)
void nade_boom (entity this)
void nade_burn_spawn (entity _nade)
int nade_choose_random ()
bool nade_customize (entity this, entity client)
void nade_damage (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void nade_pickup (entity this, entity thenade)
void nade_prime (entity this)
void nade_spawn (entity _nade)
void nade_timer_think (entity this)
void nade_touch (entity this, entity toucher)
void nades_CheckThrow (entity this)
Nade nades_CheckTypes (Nade ntype)
void nades_Clear (entity player)
 Remove nades that are being thrown.
Nade Nades_FromString (string ntype)
Nade Nades_GetType (string ntype)
void nades_GiveBonus (entity player, float score)
 Give a bonus grenade to a player.
void nades_orb_think (entity this)
vector nades_PlayerColor (entity this, bool isPants)
void nades_RemoveBonus (entity player)
 Remove all bonus nades from a player.
void nades_RemovePlayer (entity this)
 Remove nades and bonus nades from a player.
entity nades_spawn_orb (entity this, float orb_lifetime, float orb_rad)
 Spawns an orb for some nade types.
 REGISTER_MUTATOR (nades, autocvar_g_nades)
void spawn_held_nade (entity player, entity nowner, float ntime, string ntype, string pntype)
void toss_nade (entity e, bool set_owner, vector _velocity, float _time)

Variables

bool nade_altbutton
entity nade_spawnloc
float nade_time_primed
NadeOffhand OFFHAND_NADE

Macro Definition Documentation

◆ NADE_TYPE_CHECK

#define NADE_TYPE_CHECK ( nade_ent,
nade_cvar )
Value:
case nade_ent.m_id: \
if (nade_cvar) \
return ntype; \
break

Referenced by nades_CheckTypes().

◆ SET_NADE_EFFECT

#define SET_NADE_EFFECT ( nade_type,
exp_effect,
exp_color_min,
exp_color_max )
Value:
case nade_type: \
expef = exp_effect; \
expcol_min = exp_color_min; \
expcol_max = exp_color_max; \
break

Referenced by nade_boom().

◆ SPREE_ITEM

#define SPREE_ITEM ( counta,
countb,
center,
normal,
gentle )
Value:
case counta: \
nades_GiveBonus(frag_attacker, autocvar_g_nades_bonus_score_spree); \
break;
int autocvar_g_nades_bonus_score_spree
Definition sv_nades.qh:40

Function Documentation

◆ CanThrowNade()

bool CanThrowNade ( entity this)

Definition at line 618 of file sv_nades.qc.

619{
620 return !(this.vehicle || !autocvar_g_nades || IS_DEAD(this) || !IS_PLAYER(this) || weaponLocked(this));
621}
#define IS_DEAD(s)
Definition player.qh:244
#define IS_PLAYER(s)
Definition player.qh:242
bool autocvar_g_nades
Definition sv_nades.qh:5
entity vehicle
bool weaponLocked(entity player)

References autocvar_g_nades, entity(), IS_DEAD, IS_PLAYER, vehicle, and weaponLocked().

Referenced by nade_touch(), nades_CheckThrow(), and NadeOffhand::offhand_think().

◆ MUTATOR_HOOKFUNCTION() [1/15]

MUTATOR_HOOKFUNCTION ( nades ,
BuildMutatorsPrettyString  )

Definition at line 949 of file sv_nades.qc.

950{
951 M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Nades");
952}
#define M_ARGV(x, type)
Definition events.qh:17
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))

References M_ARGV, and strcat().

◆ MUTATOR_HOOKFUNCTION() [2/15]

MUTATOR_HOOKFUNCTION ( nades ,
BuildMutatorsString  )

Definition at line 954 of file sv_nades.qc.

955{
956 M_ARGV(0, string) = strcat(M_ARGV(0, string), ":Nades");
957}

References M_ARGV, and strcat().

◆ MUTATOR_HOOKFUNCTION() [3/15]

MUTATOR_HOOKFUNCTION ( nades ,
ClientDisconnect  )

Definition at line 927 of file sv_nades.qc.

928{
929 entity player = M_ARGV(0, entity);
930 nades_RemovePlayer(player);
931}
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void nades_RemovePlayer(entity this)
Remove nades and bonus nades from a player.
Definition sv_nades.qc:914

References ClientDisconnect, entity(), M_ARGV, and nades_RemovePlayer().

◆ MUTATOR_HOOKFUNCTION() [4/15]

MUTATOR_HOOKFUNCTION ( nades ,
Damage_Calculate  )

Definition at line 876 of file sv_nades.qc.

877{
878 entity frag_inflictor = M_ARGV(0, entity);
879 entity frag_attacker = M_ARGV(1, entity);
881 float frag_deathtype = M_ARGV(3, float);
882
883 if (autocvar_g_freezetag_revive_nade && STAT(FROZEN, frag_target) && frag_attacker == frag_target && frag_deathtype == DEATH_NADE.m_id
884 && time - frag_inflictor.toss_time <= 0.1)
885 {
888 Send_Effect(EFFECT_ICEORGLASS, frag_target.origin, '0 0 0', 3);
889 M_ARGV(4, float) = 0;
890 M_ARGV(6, vector) = '0 0 0';
891 Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED_NADE, frag_target.netname);
892 Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
893 }
894}
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
float time
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:120
#define STAT(...)
Definition stats.qh:82
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1573
#define NULL
Definition post.qh:14
vector
Definition self.qh:92
entity frag_target
Definition sv_ctf.qc:2314
void freezetag_Unfreeze(entity targ, bool reset_health)
float autocvar_g_freezetag_revive_nade_health
bool autocvar_g_freezetag_revive_nade

References autocvar_g_freezetag_revive_nade, autocvar_g_freezetag_revive_nade_health, entity(), frag_target, freezetag_Unfreeze(), M_ARGV, NULL, Send_Effect(), Send_Notification(), SetResource(), STAT, time, and vector.

◆ MUTATOR_HOOKFUNCTION() [5/15]

MUTATOR_HOOKFUNCTION ( nades ,
DropSpecialItems  )

Definition at line 906 of file sv_nades.qc.

907{
909
910 if (frag_target.nade)
911 toss_nade(frag_target, true, '0 0 0', time + 0.05);
912}
void toss_nade(entity e, bool set_owner, vector _velocity, float _time)
Definition sv_nades.qc:321

References entity(), frag_target, M_ARGV, time, and toss_nade().

◆ MUTATOR_HOOKFUNCTION() [6/15]

MUTATOR_HOOKFUNCTION ( nades ,
ForbidThrowCurrentWeapon ,
CBC_ORDER_LAST  )

Definition at line 715 of file sv_nades.qc.

716{
717 entity player = M_ARGV(0, entity);
718
719 if (player.offhand != OFFHAND_NADE || (STAT(WEAPONS, player) & WEPSET(HOOK)) || autocvar_g_nades_override_dropweapon)
720 {
721 nades_CheckThrow(player);
722 return true;
723 }
724}
void nades_CheckThrow(entity this)
Definition sv_nades.qc:625
NadeOffhand OFFHAND_NADE
Definition sv_nades.qc:705
bool autocvar_g_nades_override_dropweapon
Definition sv_nades.qh:6
#define WEPSET(id)
Definition all.qh:47

References autocvar_g_nades_override_dropweapon, CBC_ORDER_LAST, entity(), M_ARGV, nades_CheckThrow(), OFFHAND_NADE, STAT, and WEPSET.

◆ MUTATOR_HOOKFUNCTION() [7/15]

MUTATOR_HOOKFUNCTION ( nades ,
MakePlayerObserver  )

Definition at line 922 of file sv_nades.qc.

923{
924 entity player = M_ARGV(0, entity);
925 nades_RemovePlayer(player);
926}

References entity(), M_ARGV, and nades_RemovePlayer().

◆ MUTATOR_HOOKFUNCTION() [8/15]

MUTATOR_HOOKFUNCTION ( nades ,
MonsterDies  )

Definition at line 896 of file sv_nades.qc.

897{
899 entity frag_attacker = M_ARGV(1, entity);
900
901 if (IS_PLAYER(frag_attacker) && DIFF_TEAM(frag_attacker, frag_target)
902 && !(frag_target.spawnflags & MONSTERFLAG_SPAWNED))
904}
const int MONSTERFLAG_SPAWNED
flag for spawned monsters
void nades_GiveBonus(entity player, float score)
Give a bonus grenade to a player.
Definition sv_nades.qc:445
int autocvar_g_nades_bonus_score_minor
Definition sv_nades.qh:36
#define DIFF_TEAM(a, b)
Definition teams.qh:242

References autocvar_g_nades_bonus_score_minor, DIFF_TEAM, entity(), frag_target, IS_PLAYER, M_ARGV, MONSTERFLAG_SPAWNED, and nades_GiveBonus().

◆ MUTATOR_HOOKFUNCTION() [9/15]

MUTATOR_HOOKFUNCTION ( nades ,
PlayerDies ,
CBC_ORDER_LAST  )

Definition at line 836 of file sv_nades.qc.

837{
838 entity frag_attacker = M_ARGV(1, entity);
840
841 if (frag_target.nade
843 toss_nade(frag_target, true, '0 0 100', max(frag_target.nade.wait, time + 0.05));
844
845 if (IS_PLAYER(frag_attacker))
846 {
847 float killcount_bonus = (CS(frag_attacker).killcount >= 1)
850 if (SAME_TEAM(frag_attacker, frag_target) || frag_attacker == frag_target)
851 nades_RemoveBonus(frag_attacker);
854 else if (autocvar_g_nades_bonus_score_spree && CS(frag_attacker).killcount > 1)
855 {
856 #define SPREE_ITEM(counta, countb, center, normal, gentle) \
857 case counta: \
858 nades_GiveBonus(frag_attacker, autocvar_g_nades_bonus_score_spree); \
859 break;
860 switch (CS(frag_attacker).killcount)
861 {
863 default:
865 break;
866 }
867 #undef SPREE_ITEM
868 }
869 else
870 nades_GiveBonus(frag_attacker, killcount_bonus);
871 }
872
874}
float bound(float min, float value, float max)
float max(float f,...)
#define KILL_SPREE_LIST
Definition all.qh:491
int killcount
Definition client.qh:315
ClientState CS(Client this)
Definition state.qh:47
void nades_RemoveBonus(entity player)
Remove all bonus nades from a player.
Definition sv_nades.qc:465
int autocvar_g_nades_bonus_score_medium
Definition sv_nades.qh:39
#define GameRules_scoring_is_vip(player)
Definition sv_rules.qh:79
#define SAME_TEAM(a, b)
Definition teams.qh:241

References autocvar_g_freezetag_revive_nade, autocvar_g_nades_bonus_score_medium, autocvar_g_nades_bonus_score_minor, autocvar_g_nades_bonus_score_spree, bound(), CBC_ORDER_LAST, CS(), entity(), frag_target, GameRules_scoring_is_vip, IS_PLAYER, KILL_SPREE_LIST, killcount, M_ARGV, max(), nades_GiveBonus(), nades_RemoveBonus(), SAME_TEAM, STAT, time, and toss_nade().

◆ MUTATOR_HOOKFUNCTION() [10/15]

MUTATOR_HOOKFUNCTION ( nades ,
PlayerPreThink  )

Definition at line 726 of file sv_nades.qc.

727{
728 entity player = M_ARGV(0, entity);
729
730 if (!IS_PLAYER(player))
731 return;
732
733 if (player.nade && (player.offhand != OFFHAND_NADE || (STAT(WEAPONS, player) & WEPSET(HOOK))))
734 OFFHAND_NADE.offhand_think(OFFHAND_NADE, player, player.nade_altbutton);
735
736 entity held_nade = player.nade;
737 if (held_nade)
738 {
739 STAT(NADE_TIMER, player) = bound(0, (time - held_nade.nade_time_primed) / held_nade.nade_lifetime, 1);
740 // LOG_TRACEF("%d %d", STAT(NADE_TIMER, player), time - held_nade.nade_time_primed);
741 makevectors(player.angles);
742 held_nade.velocity = player.velocity;
743 setorigin(held_nade, player.origin + player.view_ofs + v_forward * 8 + v_right * -8 + v_up * 0);
744 held_nade.angles.y = player.angles.y;
745
746 if (time + 0.1 >= held_nade.wait)
747 {
748 toss_nade(player, false, '0 0 0', time + 0.05);
749 int ntype = STAT(NADE_BONUS_TYPE, held_nade);
750 if (ntype == NADE_TYPE_NORMAL.m_id
751 || ntype == NADE_TYPE_NAPALM.m_id
752 || (ntype == NADE_TYPE_ICE.m_id && !autocvar_g_nades_ice_teamcheck)
753 || ntype == NADE_TYPE_TRANSLOCATE.m_id
754 || (ntype == NADE_TYPE_HEAL.m_id && (autocvar_g_nades_heal_friend < 0 || autocvar_g_nades_heal_armor_rate < 0))
755 || (ntype == NADE_TYPE_ENTRAP.m_id && (autocvar_g_nades_entrap_speed < 1 || autocvar_g_nades_entrap_strength < 1))
756 || (ntype == NADE_TYPE_MONSTER.m_id && !autocvar_g_monsters)
757 || (ntype == NADE_TYPE_AMMO.m_id && autocvar_g_nades_ammo_friend < 0)
758 || (ntype == NADE_TYPE_DARKNESS.m_id && !autocvar_g_nades_darkness_teamcheck))
759 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_THROW);
760 }
761 }
762
763 if (IS_PLAYER(player))
764 {
766 {
767 entity key;
768 int key_count = 0;
769 FOR_EACH_KH_KEY(key)
770 if (key.owner == player)
771 ++key_count;
772
773 float time_score = (GameRules_scoring_is_vip(player))
776
777 if (key_count)
778 time_score = autocvar_g_nades_bonus_score_time_flagcarrier * key_count; // multiply by the number of keys the player is holding
779
781 {
782 STAT(NADE_BONUS_TYPE, player) = nades_CheckTypes(Nades_FromString(CS_CVAR(player).cvar_cl_nade_type)).m_id;
783 player.pokenade_type = CS_CVAR(player).cvar_cl_pokenade_type;
784 }
785 else
786 {
787 STAT(NADE_BONUS_TYPE, player) = Nades_FromString(autocvar_g_nades_bonus_type).m_id;
788 player.pokenade_type = autocvar_g_nades_pokenade_monster_type;
789 }
790
791 if (STAT(NADE_BONUS_SCORE, player) >= 0 && autocvar_g_nades_bonus_score_max)
793 }
794 else
795 STAT(NADE_BONUS, player) = STAT(NADE_BONUS_SCORE, player) = 0;
796
797 nade_veil_Apply(player);
798 }
799}
int m_id
Definition nades.qh:15
float autocvar_g_nades_ammo_friend
Definition ammo.qh:9
vector v_up
vector v_right
vector v_forward
bool autocvar_g_nades_darkness_teamcheck
Definition darkness.qh:8
float autocvar_g_nades_entrap_strength
Definition entrap.qh:7
float autocvar_g_nades_entrap_speed
Definition entrap.qh:8
bool autocvar_g_nades_ice_teamcheck
Definition ice.qh:9
float autocvar_g_nades_heal_friend
Definition heal.qh:10
float autocvar_g_nades_heal_armor_rate
Definition heal.qh:9
string autocvar_g_nades_pokenade_monster_type
Definition monster.qh:8
#define makevectors
Definition post.qh:21
#define CS_CVAR(this)
Definition state.qh:51
#define FOR_EACH_KH_KEY(v)
Definition sv_keyhunt.qh:27
float autocvar_g_monsters
Definition sv_monsters.qh:5
Nade Nades_FromString(string ntype)
Definition sv_nades.qc:513
Nade nades_CheckTypes(Nade ntype)
Definition sv_nades.qc:419
bool autocvar_g_nades_bonus_client_select
Definition sv_nades.qh:29
int autocvar_g_nades_bonus_score_time_flagcarrier
Definition sv_nades.qh:35
bool autocvar_g_nades_bonus
Definition sv_nades.qh:27
int autocvar_g_nades_bonus_score_time
Definition sv_nades.qh:34
string autocvar_g_nades_bonus_type
Definition sv_nades.qh:28
string cvar_cl_nade_type
Definition sv_nades.qh:50
int autocvar_g_nades_bonus_score_max
Definition sv_nades.qh:33
void nade_veil_Apply(entity player)
Definition veil.qc:34

References autocvar_g_monsters, autocvar_g_nades, autocvar_g_nades_ammo_friend, autocvar_g_nades_bonus, autocvar_g_nades_bonus_client_select, autocvar_g_nades_bonus_score_max, autocvar_g_nades_bonus_score_time, autocvar_g_nades_bonus_score_time_flagcarrier, autocvar_g_nades_bonus_type, autocvar_g_nades_darkness_teamcheck, autocvar_g_nades_entrap_speed, autocvar_g_nades_entrap_strength, autocvar_g_nades_heal_armor_rate, autocvar_g_nades_heal_friend, autocvar_g_nades_ice_teamcheck, autocvar_g_nades_pokenade_monster_type, bound(), CS_CVAR, cvar_cl_nade_type, entity(), FOR_EACH_KH_KEY, GameRules_scoring_is_vip, IS_PLAYER, M_ARGV, Nade::m_id, makevectors, nade_veil_Apply(), nades_CheckTypes(), Nades_FromString(), nades_GiveBonus(), OFFHAND_NADE, PlayerPreThink, Send_Notification(), STAT, time, toss_nade(), v_forward, v_right, v_up, and WEPSET.

◆ MUTATOR_HOOKFUNCTION() [11/15]

MUTATOR_HOOKFUNCTION ( nades ,
PlayerSpawn  )

Definition at line 801 of file sv_nades.qc.

802{
803 entity player = M_ARGV(0, entity);
804
805 if (StatusEffects_active(STATUSEFFECT_SpawnShield, player))
806 player.nade_refire = StatusEffects_gettime(STATUSEFFECT_SpawnShield, player);
807 else
808 player.nade_refire = time;
809
811 player.nade_refire += autocvar_g_nades_nade_refire;
812
814 STAT(NADE_BONUS_TYPE, player) = Nades_FromString(CS_CVAR(player).cvar_cl_nade_type).m_id;
815
816 STAT(NADE_TIMER, player) = 0;
817
818 if (!player.offhand)
819 player.offhand = OFFHAND_NADE;
820
821 if (player.nade_spawnloc)
822 {
823 setorigin(player, player.nade_spawnloc.origin);
824 --player.nade_spawnloc.cnt;
825
826 if (player.nade_spawnloc.cnt <= 0)
827 {
828 delete(player.nade_spawnloc);
829 player.nade_spawnloc = NULL;
830 }
831
833 }
834}
void nade_spawn_SetSpawnHealth(entity player)
Definition spawn.qc:22
float StatusEffects_gettime(StatusEffect this, entity actor)
bool StatusEffects_active(StatusEffect this, entity actor)
float autocvar_g_nades_nade_refire
Definition sv_nades.qh:18
bool autocvar_g_nades_onspawn
Definition sv_nades.qh:8

References autocvar_g_nades_bonus_client_select, autocvar_g_nades_nade_refire, autocvar_g_nades_onspawn, CS_CVAR, cvar_cl_nade_type, entity(), M_ARGV, Nade::m_id, nade_spawn_SetSpawnHealth(), Nades_FromString(), NULL, OFFHAND_NADE, STAT, StatusEffects_active(), StatusEffects_gettime(), and time.

◆ MUTATOR_HOOKFUNCTION() [12/15]

MUTATOR_HOOKFUNCTION ( nades ,
PutClientInServer  )

Definition at line 470 of file sv_nades.qc.

471{
472 entity player = M_ARGV(0, entity);
473
474 nades_RemoveBonus(player);
475}

References entity(), M_ARGV, nades_RemoveBonus(), and PutClientInServer.

◆ MUTATOR_HOOKFUNCTION() [13/15]

MUTATOR_HOOKFUNCTION ( nades ,
reset_map_global  )

Definition at line 932 of file sv_nades.qc.

933{
935}
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52

References FOREACH_CLIENT, IS_PLAYER, and nades_RemovePlayer().

◆ MUTATOR_HOOKFUNCTION() [14/15]

MUTATOR_HOOKFUNCTION ( nades ,
SpectateCopy  )

Definition at line 937 of file sv_nades.qc.

938{
939 entity spectatee = M_ARGV(0, entity);
940 entity client = M_ARGV(1, entity);
941
942 STAT(NADE_TIMER, client) = STAT(NADE_TIMER, spectatee);
943 STAT(NADE_BONUS_TYPE, client) = STAT(NADE_BONUS_TYPE, spectatee);
944 client.pokenade_type = spectatee.pokenade_type;
945 STAT(NADE_BONUS, client) = STAT(NADE_BONUS, spectatee);
946 STAT(NADE_BONUS_SCORE, client) = STAT(NADE_BONUS_SCORE, spectatee);
947}

References entity(), M_ARGV, SpectateCopy(), and STAT.

◆ MUTATOR_HOOKFUNCTION() [15/15]

MUTATOR_HOOKFUNCTION ( nades ,
VehicleEnter  )

Definition at line 667 of file sv_nades.qc.

668{
669 entity player = M_ARGV(0, entity);
670
671 if (player.nade)
672 toss_nade(player, true, '0 0 100', max(player.nade.wait, time + 0.05));
673}

References entity(), M_ARGV, max(), time, and toss_nade().

◆ nade_beep()

void nade_beep ( entity this)

Definition at line 239 of file sv_nades.qc.

240{
241 sound(this, CH_SHOTS_SINGLE, SND_NADE_BEEP, VOL_BASE, 0.5 * (ATTEN_LARGE + ATTEN_MAX));
242 setthink(this, nade_boom);
243 this.nextthink = max(this.wait, time);
244}
float wait
Definition items.qc:17
float nextthink
#define setthink(e, f)
const float VOL_BASE
Definition sound.qh:36
const float ATTEN_MAX
Definition sound.qh:34
const int CH_SHOTS_SINGLE
Definition sound.qh:15
#define sound(e, c, s, v, a)
Definition sound.qh:52
const float ATTEN_LARGE
Definition sound.qh:31
void nade_boom(entity this)
Definition sv_nades.qc:114

References ATTEN_LARGE, ATTEN_MAX, CH_SHOTS_SINGLE, entity(), max(), nade_boom(), nextthink, setthink, sound, time, VOL_BASE, and wait.

Referenced by nade_damage(), and spawn_held_nade().

◆ nade_boom()

void nade_boom ( entity this)

Definition at line 114 of file sv_nades.qc.

115{
116 entity expef = NULL;
117 vector expcol_min = '0 0 0', expcol_max = '0 0 0';
118
119 Nade ntype = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
120
121 if (!this.takedamage || ntype == NADE_TYPE_Null)
122 {
123 // first condition: nade was destroyed by something (lava, void, etc.), just do a normal explosion
124 // this prevents weird cases like spawn nade setting your spawnpoint on the void, translocate sending you into the void, etc.
125 ntype = NADE_TYPE_NORMAL;
126 }
127
128#define SET_NADE_EFFECT(nade_type, exp_effect, exp_color_min, exp_color_max) \
129 case nade_type: \
130 expef = exp_effect; \
131 expcol_min = exp_color_min; \
132 expcol_max = exp_color_max; \
133 break
134
135 switch (ntype)
136 {
137 SET_NADE_EFFECT(NADE_TYPE_NAPALM, EFFECT_EXPLOSION_MEDIUM, '0 0 0', '0 0 0');
138 SET_NADE_EFFECT(NADE_TYPE_ICE, EFFECT_ELECTRO_COMBO, '0 0 0', '0 0 0');
139 SET_NADE_EFFECT(NADE_TYPE_TRANSLOCATE, NULL, '0 0 0', '0 0 0');
140 SET_NADE_EFFECT(NADE_TYPE_MONSTER, NULL, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
141 SET_NADE_EFFECT(NADE_TYPE_SPAWN, EFFECT_SPAWN, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
142 SET_NADE_EFFECT(NADE_TYPE_HEAL, EFFECT_SPAWN, '1 0 0', '1 0 0');
143 SET_NADE_EFFECT(NADE_TYPE_ENTRAP, EFFECT_SPAWN, '1 1 0', '1 1 0');
144 SET_NADE_EFFECT(NADE_TYPE_VEIL, EFFECT_SPAWN, '0 0 0', '0 0 0');
145 SET_NADE_EFFECT(NADE_TYPE_AMMO, EFFECT_SPAWN, '0.33 0.33 1', '0.33 0.33 1');
146 SET_NADE_EFFECT(NADE_TYPE_DARKNESS, EFFECT_EXPLOSION_MEDIUM, '0 0 0', '0 0 0');
147 SET_NADE_EFFECT(NADE_TYPE_NORMAL, EFFECT_NADE_EXPLODE, nades_PlayerColor(this.realowner, false), nades_PlayerColor(this.realowner, true));
148 }
149#undef SET_NADE_EFFECT
150
151 if (expef)
152 Send_Effect_Except(expef, findbetterlocation(this.origin, 8), '0 0 0', 1, expcol_min, expcol_max, NULL);
153
154 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, ATTEN_NORM);
155 sound(this, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
156
157 this.event_damage = func_null; // prevent somehow calling damage in the next call
158
159 switch (ntype)
160 {
161 case NADE_TYPE_NORMAL: nade_normal_boom(this); break;
162 case NADE_TYPE_NAPALM: nade_napalm_boom(this); break;
163 case NADE_TYPE_ICE: nade_ice_boom(this); break;
164 case NADE_TYPE_TRANSLOCATE: nade_translocate_boom(this); break;
165 case NADE_TYPE_SPAWN: nade_spawn_boom(this); break;
166 case NADE_TYPE_HEAL: nade_heal_boom(this); break;
167 case NADE_TYPE_MONSTER: nade_monster_boom(this); break;
168 case NADE_TYPE_ENTRAP: nade_entrap_boom(this); break;
169 case NADE_TYPE_VEIL: nade_veil_boom(this); break;
170 case NADE_TYPE_AMMO: nade_ammo_boom(this); break;
171 case NADE_TYPE_DARKNESS: nade_darkness_boom(this); break;
172 }
173
174 IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this, RemoveHook(it));
175 delete(this);
176}
Definition nades.qh:14
void nade_ammo_boom(entity this)
Definition ammo.qc:67
vector findbetterlocation(vector org, float mindist)
Definition util.qc:116
vector origin
void nade_darkness_boom(entity this)
Definition darkness.qc:66
void Send_Effect_Except(entity eff, vector eff_loc, vector eff_vel, int eff_cnt, vector eff_col_min, vector eff_col_max, entity ignore)
Definition all.qc:101
void nade_entrap_boom(entity this)
Definition entrap.qc:33
void nade_ice_boom(entity this)
Definition ice.qc:74
#define IL_EACH(this, cond, body)
void nade_monster_boom(entity this)
Definition monster.qc:7
void nade_heal_boom(entity this)
Definition heal.qc:53
void nade_spawn_boom(entity this)
Definition spawn.qc:4
void nade_napalm_boom(entity this)
Definition napalm.qc:134
var void func_null()
void nade_normal_boom(entity this)
Definition normal.qc:4
#define REGISTRY_GET(id, i)
Definition registry.qh:43
void RemoveHook(entity this)
Definition hook.qc:48
IntrusiveList g_projectiles
Definition common.qh:58
const int CH_SHOTS
Definition sound.qh:14
const float ATTEN_NORM
Definition sound.qh:30
float takedamage
Definition subs.qh:78
#define SET_NADE_EFFECT(nade_type, exp_effect, exp_color_min, exp_color_max)
vector nades_PlayerColor(entity this, bool isPants)
Definition sv_nades.qc:13
entity realowner
void nade_translocate_boom(entity this)
Definition translocate.qc:4
void nade_veil_boom(entity this)
Definition veil.qc:28

References ATTEN_NORM, CH_SHOTS, CH_SHOTS_SINGLE, entity(), findbetterlocation(), func_null(), g_projectiles, IL_EACH, nade_ammo_boom(), nade_darkness_boom(), nade_entrap_boom(), nade_heal_boom(), nade_ice_boom(), nade_monster_boom(), nade_napalm_boom(), nade_normal_boom(), nade_spawn_boom(), nade_translocate_boom(), nade_veil_boom(), nades_PlayerColor(), NULL, origin, realowner, REGISTRY_GET, RemoveHook(), Send_Effect_Except(), SET_NADE_EFFECT, sound, STAT, takedamage, vector, and VOL_BASE.

Referenced by nade_beep(), nade_damage(), nade_touch(), nade_translocate_DestroyDamage(), and toss_nade().

◆ nade_burn_spawn()

void nade_burn_spawn ( entity _nade)

Definition at line 35 of file sv_nades.qc.

36{
37 CSQCProjectile(_nade, true, REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, _nade)).m_projectile[1], true);
38}
void CSQCProjectile(entity e, float clientanimate, int type, float docull)

References CSQCProjectile(), entity(), REGISTRY_GET, and STAT.

Referenced by nade_damage().

◆ nade_choose_random()

int nade_choose_random ( )

Definition at line 502 of file sv_nades.qc.

503{
505 FOREACH(Nades, it != NADE_TYPE_Null,
506 {
507 if (nades_CheckTypes(it) == it) // this nade type is allowed
508 RandomSelection_AddEnt(it, 1, 1);
509 });
510 return RandomSelection_chosen_ent.m_id;
511}
#define FOREACH(list, cond, body)
Definition iter.qh:19
ERASEABLE void RandomSelection_Init()
Definition random.qc:4
#define RandomSelection_AddEnt(e, weight, priority)
Definition random.qh:14
entity RandomSelection_chosen_ent
Definition random.qh:5

References FOREACH, nades_CheckTypes(), RandomSelection_AddEnt, RandomSelection_chosen_ent, and RandomSelection_Init().

Referenced by Nades_GetType().

◆ nade_customize()

bool nade_customize ( entity this,
entity client )

Definition at line 477 of file sv_nades.qc.

478{
479 //if (IS_SPEC(client)) return false;
480 if (client == this.exteriormodeltoclient || (IS_SPEC(client) && client.enemy == this.exteriormodeltoclient))
481 {
482 // somewhat hide the model, but keep the glow
483 //this.effects = 0;
484 if (this.traileffectnum)
485 this.traileffectnum = 0;
486 this.alpha = -1;
487 }
488 else
489 {
490 //this.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
491 if (!this.traileffectnum)
492 {
493 entity nade = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
494 this.traileffectnum = _particleeffectnum(Nade_TrailEffect(nade.m_projectile[0], this.team).eent_eff_name);
495 }
496 this.alpha = 1;
497 }
498
499 return true;
500}
float alpha
Definition items.qc:13
float traileffectnum
entity exteriormodeltoclient
#define nade(name, colormin1, colormax1, colormin2, colormax2)
entity Nade_TrailEffect(int proj, int nade_team)
Definition nades.qc:17
#define IS_SPEC(v)
Definition utils.qh:10

References alpha, entity(), exteriormodeltoclient, IS_SPEC, nade, Nade_TrailEffect(), REGISTRY_GET, STAT, and traileffectnum.

Referenced by spawn_held_nade().

◆ nade_damage()

void nade_damage ( entity this,
entity inflictor,
entity attacker,
float damage,
int deathtype,
.entity weaponentity,
vector hitloc,
vector force )

Definition at line 246 of file sv_nades.qc.

247{
248 if (ITEM_DAMAGE_NEEDKILL(deathtype))
249 {
250 this.takedamage = DAMAGE_NO;
251 W_PrepareExplosionByDamage(this, attacker, nade_boom);
252 return;
253 }
254
255 if (STAT(NADE_BONUS_TYPE, this) == NADE_TYPE_TRANSLOCATE.m_id || STAT(NADE_BONUS_TYPE, this) == NADE_TYPE_SPAWN.m_id)
256 return; // can't launch these, to prevent teleporting across the map
257
258 // adjust damage & force to allow specific interactions (e.g. launching nades with Vortex)
259 if (MUTATOR_CALLHOOK(Nade_Damage, this, DEATH_WEAPONOF(deathtype), force, damage))
260 {}
261 else if (DEATH_ISWEAPON(deathtype, WEP_BLASTER))
262 {
263 force *= 1.5;
264 damage = 0;
265 }
266 else if (DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_NEX))
267 {
268 force *= 6;
269 damage = this.max_health * 0.55;
270 }
271 else if (DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_MACHINEGUN))
272 damage = this.max_health * 0.1;
273 else if (DEATH_ISWEAPON(deathtype, WEP_SHOTGUN) || DEATH_ISWEAPON(deathtype, WEP_OVERKILL_SHOTGUN)) // WEAPONTODO
274 {
275 if (!(deathtype & HITTYPE_SECONDARY))
276 damage = this.max_health * 1.15;
277 }
278
279 // melee slaps
280 entity death_weapon = DEATH_WEAPONOF(deathtype);
281 if (death_weapon.spawnflags & ((deathtype & HITTYPE_SECONDARY) ? WEP_TYPE_MELEE_SEC : WEP_TYPE_MELEE_PRI))
282 {
283 force *= 10;
284 damage = this.max_health * 0.1;
285 }
286
287 this.velocity += force;
289
290 if (damage <= 0 || (IS_ONGROUND(this) && IS_PLAYER(attacker)))
291 return;
292
293 float hp = GetResource(this, RES_HEALTH);
294 if (hp == this.max_health)
295 {
296 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 * (ATTEN_LARGE + ATTEN_MAX));
297 this.nextthink = max(time + this.nade_lifetime, time);
298 setthink(this, nade_beep);
299 }
300
301 hp -= damage;
302 SetResource(this, RES_HEALTH, hp);
303
304 if (IS_PLAYER(attacker)
305 && STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_TRANSLOCATE.m_id
306 && STAT(NADE_BONUS_TYPE, this) != NADE_TYPE_SPAWN.m_id)
307 this.realowner = attacker;
308
309 if (hp <= 0)
310 {
311 if (nade_spawn_DestroyDamage(this, attacker)
312 || nade_translocate_DestroyDamage(this, attacker))
313 return;
314
315 W_PrepareExplosionByDamage(this, attacker, nade_boom);
316 }
317 else
318 nade_burn_spawn(this);
319}
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
float max_health
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
vector velocity
void UpdateCSQCProjectile(entity e)
#define DEATH_ISWEAPON(t, w)
Definition all.qh:46
#define DEATH_WEAPONOF(t)
Definition all.qh:45
const int HITTYPE_SECONDARY
Definition all.qh:29
#define IS_ONGROUND(s)
Definition movetypes.qh:16
bool nade_spawn_DestroyDamage(entity this, entity attacker)
Definition spawn.qc:28
#define ITEM_DAMAGE_NEEDKILL(dt)
Definition items.qh:123
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode)
Definition common.qc:87
const int DAMAGE_NO
Definition subs.qh:79
void nade_burn_spawn(entity _nade)
Definition sv_nades.qc:35
void nade_beep(entity this)
Definition sv_nades.qc:239
float nade_lifetime
Definition sv_nades.qh:45
bool nade_translocate_DestroyDamage(entity this, entity attacker)
const int WEP_TYPE_MELEE_PRI
Definition weapon.qh:262
const int WEP_TYPE_MELEE_SEC
Definition weapon.qh:263

References ATTEN_LARGE, ATTEN_MAX, CH_SHOTS_SINGLE, DAMAGE_NO, DEATH_ISWEAPON, DEATH_WEAPONOF, entity(), GetResource(), HITTYPE_SECONDARY, IS_ONGROUND, IS_PLAYER, ITEM_DAMAGE_NEEDKILL, max(), max_health, MUTATOR_CALLHOOK, nade_beep(), nade_boom(), nade_burn_spawn(), nade_lifetime, nade_spawn_DestroyDamage(), nade_translocate_DestroyDamage(), nextthink, realowner, SetResource(), setthink, sound, STAT, takedamage, time, UpdateCSQCProjectile(), vector, velocity, VOL_BASE, W_PrepareExplosionByDamage(), WEP_TYPE_MELEE_PRI, and WEP_TYPE_MELEE_SEC.

Referenced by toss_nade().

◆ nade_pickup()

void nade_pickup ( entity this,
entity thenade )

Definition at line 179 of file sv_nades.qc.

180{
181 spawn_held_nade(this, thenade.realowner, autocvar_g_nades_pickup_time, REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, thenade)).netname, thenade.pokenade_type);
182
183 // set refire so player can't even
185 STAT(NADE_TIMER, this) = 0;
186
187 if (this.nade)
188 this.nade.nade_time_primed = thenade.nade_time_primed;
189}
string netname
Definition powerups.qc:20
void spawn_held_nade(entity player, entity nowner, float ntime, string ntype, string pntype)
Definition sv_nades.qc:530
float autocvar_g_nades_pickup_time
Definition sv_nades.qh:13
float nade_refire
Definition sv_nades.qh:46

References autocvar_g_nades_nade_refire, autocvar_g_nades_pickup_time, entity(), nade, nade_refire, netname, REGISTRY_GET, spawn_held_nade(), STAT, and time.

Referenced by nade_touch().

◆ nade_prime()

void nade_prime ( entity this)

Definition at line 576 of file sv_nades.qc.

577{
578 if (autocvar_g_nades_bonus_only && !STAT(NADE_BONUS, this))
579 return; // only allow bonus nades
580
581 // TODO: handle old nade if it exists?
582 if (this.nade)
583 delete(this.nade);
584 this.nade = NULL;
585
586 if (this.fake_nade)
587 delete(this.fake_nade);
588 this.fake_nade = NULL;
589
590 Nade ntype;
591 string pntype = this.pokenade_type;
592
593 if (StatusEffects_active(STATUSEFFECT_Strength, this) && autocvar_g_nades_bonus_onstrength)
594 ntype = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
595 else if (STAT(NADE_BONUS, this) >= 1)
596 {
597 ntype = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, this));
598 pntype = this.pokenade_type;
599 --STAT(NADE_BONUS, this);
600 }
601 else
602 {
604 {
606 pntype = CS_CVAR(this).cvar_cl_pokenade_type;
607 }
608 else
609 {
612 }
613 }
614
615 spawn_held_nade(this, this, autocvar_g_nades_nade_lifetime, ntype.netname, pntype);
616}
string netname
Definition nades.qh:21
string pokenade_type
Definition sv_nades.qh:48
float autocvar_g_nades_nade_lifetime
Definition sv_nades.qh:14
bool autocvar_g_nades_bonus_onstrength
Definition sv_nades.qh:30
bool autocvar_g_nades_bonus_only
Definition sv_nades.qh:31
entity fake_nade
Definition sv_nades.qh:44
bool autocvar_g_nades_client_select
Definition sv_nades.qh:25
string autocvar_g_nades_nade_type
Definition sv_nades.qh:24

References autocvar_g_nades_bonus_only, autocvar_g_nades_bonus_onstrength, autocvar_g_nades_client_select, autocvar_g_nades_nade_lifetime, autocvar_g_nades_nade_type, autocvar_g_nades_pokenade_monster_type, CS_CVAR, cvar_cl_nade_type, entity(), fake_nade, nade, nades_CheckTypes(), Nades_FromString(), Nade::netname, NULL, pokenade_type, REGISTRY_GET, spawn_held_nade(), STAT, and StatusEffects_active().

Referenced by nades_CheckThrow(), and NadeOffhand::offhand_think().

◆ nade_spawn()

void nade_spawn ( entity _nade)

Definition at line 40 of file sv_nades.qc.

41{
42 entity timer = new(nade_timer);
43 setmodel(timer, MDL_NADE_TIMER);
44 setattachment(timer, _nade, "");
45 timer.colormap = _nade.colormap;
46 timer.glowmod = _nade.glowmod;
48 timer.nextthink = time;
49 timer.wait = _nade.wait;
50 timer.nade_lifetime = _nade.nade_lifetime;
51 timer.owner = _nade;
52 timer.skin = 10;
53
54 _nade.effects |= EF_LOWPRECISION;
55
56 CSQCProjectile(_nade, true, REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, _nade)).m_projectile[0], true);
57}
#define setmodel(this, m)
Definition model.qh:26
float EF_LOWPRECISION
float timer
Definition hud.qh:125
void nade_timer_think(entity this)
Definition sv_nades.qc:27

References CSQCProjectile(), EF_LOWPRECISION, entity(), nade_timer_think(), REGISTRY_GET, setmodel, setthink, STAT, time, and timer.

Referenced by toss_nade().

◆ nade_timer_think()

void nade_timer_think ( entity this)

Definition at line 27 of file sv_nades.qc.

28{
29 this.skin = 8 - (this.wait - time) / (this.nade_lifetime / 10);
30 this.nextthink = time;
31 if (!this.owner || wasfreed(this.owner))
32 delete(this);
33}
entity owner
Definition main.qh:87
float skin

References entity(), nade_lifetime, nextthink, owner, skin, time, and wait.

Referenced by nade_darkness_boom(), nade_ice_boom(), and nade_spawn().

◆ nade_touch()

void nade_touch ( entity this,
entity toucher )

Definition at line 192 of file sv_nades.qc.

193{
194 if (toucher)
196
197 if (toucher == this.realowner)
198 return; // no this impacts
199
201 && time >= this.spawnshieldtime
202 && !toucher.nade && GetResource(this, RES_HEALTH) == this.max_health // no boosted shot pickups, thank you very much
203 && CanThrowNade(toucher) // prevent some obvious things, like dead players
204 && IS_REAL_CLIENT(toucher)) // above checks for IS_PLAYER, don't need to do it here
205 {
206 nade_pickup(toucher, this);
207 sound(this, CH_SHOTS_SINGLE, SND_Null, VOL_BASE, 0.5 * (ATTEN_LARGE + ATTEN_MAX));
208 delete(this);
209 return;
210 }
211 /*
212 bool is_weapclip = false;
213 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW)
214 if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID))
215 if (!(trace_dphitcontents & DPCONTENTS_OPAQUE))
216 is_weapclip = true;
217 */
218 if (ITEM_TOUCH_NEEDKILL()) // || is_weapclip)
219 {
220 IL_EACH(g_projectiles, it.classname == "grapplinghook" && it.aiment == this, RemoveHook(it));
221 delete(this);
222 return;
223 }
224
226
227 //setsize(this, '-2 -2 -2', '2 2 2');
228 //UpdateCSQCProjectile(this);
229 if (GetResource(this, RES_HEALTH) == this.max_health)
230 {
232 return;
233 }
234
235 this.enemy = toucher;
236 nade_boom(this);
237}
float spawnshieldtime
Definition damage.qh:61
entity entity toucher
Definition self.qh:72
#define ITEM_TOUCH_NEEDKILL()
Definition items.qh:122
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28
Sound SND_GRENADE_BOUNCE_RANDOM()
Definition all.inc:17
float spamsound(entity e, int chan, Sound samp, float vol, float _atten)
use this one if you might be causing spam (e.g.
Definition all.qc:124
entity enemy
Definition sv_ctf.qh:153
bool CanThrowNade(entity this)
Definition sv_nades.qc:618
void nade_pickup(entity this, entity thenade)
Definition sv_nades.qc:179
bool autocvar_g_nades_pickup
Definition sv_nades.qh:12
#define IS_REAL_CLIENT(v)
Definition utils.qh:17

References ATTEN_LARGE, ATTEN_MAX, ATTEN_NORM, autocvar_g_nades_pickup, CanThrowNade(), CH_SHOTS, CH_SHOTS_SINGLE, enemy, entity(), g_projectiles, GetResource(), IL_EACH, IS_REAL_CLIENT, ITEM_TOUCH_NEEDKILL, max_health, nade_boom(), nade_pickup(), PROJECTILE_TOUCH, realowner, RemoveHook(), SND_GRENADE_BOUNCE_RANDOM(), sound, spamsound(), spawnshieldtime, time, toucher, UpdateCSQCProjectile(), and VOL_BASE.

Referenced by toss_nade().

◆ nades_CheckThrow()

void nades_CheckThrow ( entity this)

Definition at line 625 of file sv_nades.qc.

626{
627 if (!CanThrowNade(this))
628 return;
629
630 entity held_nade = this.nade;
631 if (!held_nade)
632 {
633 this.nade_altbutton = true;
634 if (time > this.nade_refire)
635 {
636 nade_prime(this);
638 }
639 }
640 else
641 {
642 this.nade_altbutton = false;
643 if (time >= held_nade.nade_time_primed + 1)
644 {
645 makevectors(this.v_angle);
646 float _force = time - held_nade.nade_time_primed;
649 vector dir = v_forward * 0.75 + v_up * 0.2 + v_right * 0.05;
651 toss_nade(this, true, dir * _force, 0);
652 }
653 }
654}
vector W_CalculateSpread(vector dir, float spread, int spread_style, bool must_normalize)
vector v_angle
Definition player.qh:236
float autocvar_g_nades_spread
Definition nades.qc:7
int dir
Definition impulse.qc:89
bool nade_altbutton
Definition sv_nades.qc:623
void nade_prime(entity this)
Definition sv_nades.qc:576
float autocvar_g_nades_nade_minforce
Definition sv_nades.qh:15
float autocvar_g_nades_nade_maxforce
Definition sv_nades.qh:16
int autocvar_g_projectiles_spread_style
Definition tracing.qh:14

References autocvar_g_nades_nade_lifetime, autocvar_g_nades_nade_maxforce, autocvar_g_nades_nade_minforce, autocvar_g_nades_nade_refire, autocvar_g_nades_spread, autocvar_g_projectiles_spread_style, CanThrowNade(), dir, entity(), makevectors, nade, nade_altbutton, nade_prime(), nade_refire, time, toss_nade(), v_angle, v_forward, v_right, v_up, vector, and W_CalculateSpread().

Referenced by MUTATOR_HOOKFUNCTION().

◆ nades_CheckTypes()

Nade nades_CheckTypes ( Nade ntype)

Definition at line 419 of file sv_nades.qc.

420{
421#define NADE_TYPE_CHECK(nade_ent, nade_cvar) \
422 case nade_ent.m_id: \
423 if (nade_cvar) \
424 return ntype; \
425 break
426
427 switch (ntype.m_id)
428 {
429 case 0: return NADE_TYPE_Null; // use NADE_TYPE_Null to signify a random nade
430 NADE_TYPE_CHECK(NADE_TYPE_NAPALM, autocvar_g_nades_napalm);
432 NADE_TYPE_CHECK(NADE_TYPE_TRANSLOCATE, autocvar_g_nades_translocate);
433 NADE_TYPE_CHECK(NADE_TYPE_SPAWN, autocvar_g_nades_spawn);
434 NADE_TYPE_CHECK(NADE_TYPE_HEAL, autocvar_g_nades_heal);
435 NADE_TYPE_CHECK(NADE_TYPE_MONSTER, autocvar_g_nades_pokenade && autocvar_g_monsters); // if monsters disabled, this nade can't do anything, use instead normal nade
436 NADE_TYPE_CHECK(NADE_TYPE_ENTRAP, autocvar_g_nades_entrap);
437 NADE_TYPE_CHECK(NADE_TYPE_VEIL, autocvar_g_nades_veil);
438 NADE_TYPE_CHECK(NADE_TYPE_AMMO, autocvar_g_nades_ammo);
439 NADE_TYPE_CHECK(NADE_TYPE_DARKNESS, autocvar_g_nades_darkness);
440 }
441 return NADE_TYPE_NORMAL; // default to NADE_TYPE_NORMAL for unknown nade types
442#undef NADE_TYPE_CHECK
443}
bool autocvar_g_nades_ammo
Definition ammo.qh:6
bool autocvar_g_nades_darkness
Definition darkness.qh:6
bool autocvar_g_nades_entrap
Definition entrap.qh:6
bool autocvar_g_nades_ice
Definition ice.qh:6
bool autocvar_g_nades_heal
Definition heal.qh:6
bool autocvar_g_nades_pokenade
Definition monster.qh:7
bool autocvar_g_nades_spawn
Definition spawn.qh:6
bool autocvar_g_nades_napalm
Definition napalm.qh:6
#define NADE_TYPE_CHECK(nade_ent, nade_cvar)
bool autocvar_g_nades_translocate
Definition translocate.qh:6
bool autocvar_g_nades_veil
Definition veil.qh:6

References autocvar_g_monsters, autocvar_g_nades_ammo, autocvar_g_nades_darkness, autocvar_g_nades_entrap, autocvar_g_nades_heal, autocvar_g_nades_ice, autocvar_g_nades_napalm, autocvar_g_nades_pokenade, autocvar_g_nades_spawn, autocvar_g_nades_translocate, autocvar_g_nades_veil, Nade::m_id, and NADE_TYPE_CHECK.

Referenced by MUTATOR_HOOKFUNCTION(), nade_choose_random(), and nade_prime().

◆ nades_Clear()

void nades_Clear ( entity player)

Remove nades that are being thrown.

Definition at line 656 of file sv_nades.qc.

657{
658 if (player.nade)
659 delete(player.nade);
660 if (player.fake_nade)
661 delete(player.fake_nade);
662
663 player.nade = player.fake_nade = NULL;
664 STAT(NADE_TIMER, player) = 0;
665}

References entity(), NULL, and STAT.

Referenced by nades_RemovePlayer().

◆ Nades_FromString()

Nade Nades_FromString ( string ntype)

Definition at line 513 of file sv_nades.qc.

514{
515 FOREACH(Nades, it != NADE_TYPE_Null && (it.netname == ntype || ftos(it.impulse) == ntype), return it);
516 return NADE_TYPE_Null;
517}
string ftos(float f)

References FOREACH, and ftos().

Referenced by MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), nade_prime(), and Nades_GetType().

◆ Nades_GetType()

Nade Nades_GetType ( string ntype)

Definition at line 519 of file sv_nades.qc.

520{
521 Nade def;
522 if (ntype == "random" || ntype == "0")
523 def = REGISTRY_GET(Nades, nade_choose_random());
524 else
525 def = Nades_FromString(ntype);
526
527 return (def == NADE_TYPE_Null) ? NADE_TYPE_NORMAL : def;
528}
int nade_choose_random()
Definition sv_nades.qc:502

References nade_choose_random(), Nades_FromString(), and REGISTRY_GET.

Referenced by spawn_held_nade().

◆ nades_GiveBonus()

void nades_GiveBonus ( entity player,
float score )

Give a bonus grenade to a player.

Definition at line 445 of file sv_nades.qc.

446{
448 && IS_REAL_CLIENT(player) && IS_PLAYER(player) && STAT(NADE_BONUS, player) < autocvar_g_nades_bonus_max
449 && !IS_DEAD(player) && !STAT(FROZEN, player))
450 {
451 if (STAT(NADE_BONUS_SCORE, player) < 1)
452 STAT(NADE_BONUS_SCORE, player) += score / autocvar_g_nades_bonus_score_max;
453
454 if (STAT(NADE_BONUS_SCORE, player) >= 1)
455 {
456 Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
457 play2(player, SND(NADE_BONUS));
458 ++STAT(NADE_BONUS, player);
459 --STAT(NADE_BONUS_SCORE, player);
460 }
461 }
462}
void play2(entity e, string filename)
Definition all.qc:116
#define SND(id)
Definition all.qh:35
int autocvar_g_nades_bonus_max
Definition sv_nades.qh:32

References autocvar_g_nades, autocvar_g_nades_bonus, autocvar_g_nades_bonus_max, autocvar_g_nades_bonus_score_max, entity(), IS_DEAD, IS_PLAYER, IS_REAL_CLIENT, play2(), Send_Notification(), SND, and STAT.

Referenced by ctf_Handle_Capture(), ctf_Handle_Pickup(), ctf_Handle_Return(), kh_WinnerTeam(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and MUTATOR_HOOKFUNCTION().

◆ nades_orb_think()

void nades_orb_think ( entity this)

Definition at line 60 of file sv_nades.qc.

61{
62 if (time >= this.ltime)
63 {
64 delete(this);
65 return;
66 }
67
68 this.nextthink = time;
69
70 if (time >= this.nade_special_time)
71 {
72 this.nade_special_time = time + 0.05;
73 this.nade_show_particles = true;
74 }
75 else
76 this.nade_show_particles = false;
77}
float ltime
Definition net.qh:10
float nade_special_time
Definition sv_nades.qh:47
bool nade_show_particles
Definition sv_nades.qh:53

References entity(), ltime, nade_show_particles, nade_special_time, nextthink, and time.

Referenced by nades_spawn_orb().

◆ nades_PlayerColor()

vector nades_PlayerColor ( entity this,
bool isPants )

Definition at line 13 of file sv_nades.qc.

14{
15 if (teamplay)
16 return Team_ColorRGB(this.team);
17
18 // logic copied from Scoreboard_GetName
19 int col = (this.colormap >= 1024)
20 ? this.colormap - 1024
22 return (isPants)
23 ? colormapPaletteColor(col % 16, true)
24 : colormapPaletteColor(floor(col / 16), false);
25}
int team
Definition main.qh:188
#define colormapPaletteColor(c, isPants)
Definition color.qh:5
float colormap
#define false
Definition csprogsdefs.qh:6
clientcolors
Definition ent_cs.qc:147
float floor(float f)
entity this
Definition self.qh:72
vector Team_ColorRGB(int teamid)
Definition teams.qh:76
bool teamplay
Definition teams.qh:59

References clientcolors, colormap, colormapPaletteColor, entity(), floor(), team, Team_ColorRGB(), teamplay, and vector.

Referenced by nade_boom(), nade_darkness_think(), and nade_ice_think().

◆ nades_RemoveBonus()

void nades_RemoveBonus ( entity player)

Remove all bonus nades from a player.

Definition at line 465 of file sv_nades.qc.

466{
467 STAT(NADE_BONUS, player) = STAT(NADE_BONUS_SCORE, player) = 0;
468}

References entity(), and STAT.

Referenced by MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and nades_RemovePlayer().

◆ nades_RemovePlayer()

void nades_RemovePlayer ( entity this)

Remove nades and bonus nades from a player.

Definition at line 914 of file sv_nades.qc.

915{
916 nades_Clear(this);
917 nades_RemoveBonus(this);
918 delete(this.nade_spawnloc);
919 this.nade_spawnloc = NULL;
920}
void nades_Clear(entity player)
Remove nades that are being thrown.
Definition sv_nades.qc:656
entity nade_spawnloc
Definition sv_nades.qc:11

References entity(), nade_spawnloc, nades_Clear(), nades_RemoveBonus(), and NULL.

Referenced by CA_CheckWinner(), freezetag_CheckWinner(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), Onslaught_CheckWinner(), and Surv_CheckWinner().

◆ nades_spawn_orb()

entity nades_spawn_orb ( entity this,
float orb_lifetime,
float orb_rad )

Spawns an orb for some nade types.

Definition at line 79 of file sv_nades.qc.

80{
81 // NOTE: this function merely places an orb
82 // you must add a custom touch function to the returned entity if desired
83 entity orb = new(nades_spawn_orb);
84 orb.owner = this.owner;
85 orb.realowner = this.realowner;
86 setorigin(orb, this.origin);
87
88 orb.lifetime = orb_lifetime; // required for timers
89 orb.ltime = time + orb.lifetime;
90 orb.bot_dodge = false;
91 orb.team = this.realowner.team;
92 orb.solid = SOLID_TRIGGER;
93
94 setmodel(orb, MDL_NADE_ORB);
95 orb.skin = 1;
96 orb.radius = orb_rad; // required for fading
97 vector size = '0.5 0.5 0.5' * orb.radius;
98 setsize(orb, -size, size);
99
100 STAT(NADE_BONUS_TYPE, orb) = STAT(NADE_BONUS_TYPE, this);
101 orb.colormod = REGISTRY_GET(Nades, STAT(NADE_BONUS_TYPE, orb)).m_color;
102
103 Net_LinkEntity(orb, true, 0, orb_send);
104
105 orb.reset = SUB_Remove;
106
108 orb.nextthink = time;
109
110 return orb;
111}
const float SOLID_TRIGGER
vector size
void SUB_Remove(entity this)
Remove entity.
Definition defer.qh:13
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167
bool orb_send(entity this, entity to, int sf)
Definition net.qc:102
void nades_orb_think(entity this)
Definition sv_nades.qc:60
entity nades_spawn_orb(entity this, float orb_lifetime, float orb_rad)
Spawns an orb for some nade types.
Definition sv_nades.qc:79

References entity(), nades_orb_think(), nades_spawn_orb(), Net_LinkEntity(), orb_send(), origin, owner, realowner, REGISTRY_GET, setmodel, setthink, size, SOLID_TRIGGER, STAT, SUB_Remove(), time, and vector.

Referenced by nade_ammo_boom(), nade_entrap_boom(), nade_heal_boom(), nade_veil_boom(), and nades_spawn_orb().

◆ REGISTER_MUTATOR()

REGISTER_MUTATOR ( nades ,
autocvar_g_nades  )

Definition at line 706 of file sv_nades.qc.

707{
709 {
711 }
712 return 0;
713}
#define MUTATOR_ONADD
Definition base.qh:309
#define NEW(cname,...)
Definition oo.qh:117

References autocvar_g_nades, MUTATOR_ONADD, NEW, OFFHAND_NADE, and REGISTER_MUTATOR.

◆ spawn_held_nade()

void spawn_held_nade ( entity player,
entity nowner,
float ntime,
string ntype,
string pntype )

Definition at line 530 of file sv_nades.qc.

531{
532 entity n = new(nade), fn = new(fake_nade);
533
534 Nade def = Nades_GetType(ntype);
535
536 n.pokenade_type = pntype;
537
538 STAT(NADE_BONUS_TYPE, n) = def.m_id;
539
540 .entity weaponentity = weaponentities[0]; // TODO: unhardcode
541
542 setmodel(n, MDL_PROJECTILE_NADE);
543 //setattachment(n, player, "bip01 l hand");
544 n.exteriormodeltoclient = player;
546 n.traileffectnum = _particleeffectnum(Nade_TrailEffect(def.m_projectile[0], player.team).eent_eff_name);
547 n.colormod = def.m_color;
548 n.realowner = nowner;
549 n.colormap = player.colormap;
550 n.glowmod = player.glowmod;
551 n.wait = time + max(0, ntime);
552 n.nade_time_primed = time;
554 n.nextthink = max(n.wait - 3, time);
555 n.projectiledeathtype = DEATH_NADE.m_id;
556 n.weaponentity_fld = weaponentity;
557 n.nade_lifetime = ntime;
558 n.alpha = def.m_alpha;
559
560 setmodel(fn, MDL_NADE_VIEW);
561 //setattachment(fn, player.(weaponentity), "");
562 fn.viewmodelforclient = player;
563 fn.realowner = fn.owner = player;
564 fn.colormod = def.m_color;
565 fn.colormap = player.colormap;
566 fn.glowmod = player.glowmod;
567 setthink(fn, SUB_Remove);
568 fn.nextthink = n.wait;
569 fn.weaponentity_fld = weaponentity;
570 fn.alpha = def.m_alpha;
571
572 player.nade = n;
573 player.fake_nade = fn;
574}
float m_alpha
Definition nades.qh:19
vector m_color
Definition nades.qh:16
int m_projectile[2]
Definition nades.qh:41
#define setcefc(e, f)
bool nade_customize(entity this, entity client)
Definition sv_nades.qc:477
Nade Nades_GetType(string ntype)
Definition sv_nades.qc:519
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17

References entity(), fake_nade, Nade::m_alpha, Nade::m_color, Nade::m_id, Nade::m_projectile, max(), nade, nade_beep(), nade_customize(), Nade_TrailEffect(), Nades_GetType(), setcefc, setmodel, setthink, STAT, SUB_Remove(), time, and weaponentities.

Referenced by nade_pickup(), and nade_prime().

◆ toss_nade()

void toss_nade ( entity e,
bool set_owner,
vector _velocity,
float _time )

Definition at line 321 of file sv_nades.qc.

322{
323 if (e.nade == NULL)
324 return;
325
326 entity _nade = e.nade;
327 e.nade = NULL;
328
329 if (e.fake_nade)
330 delete(e.fake_nade);
331 e.fake_nade = NULL;
332
333 Kill_Notification(NOTIF_ONE_ONLY, e, MSG_CENTER, CPID_NADES);
334
335 makevectors(e.v_angle);
336
337 // NOTE: always throw from first weapon entity?
338 W_SetupShot(e, _nade.weaponentity_fld, false, false, SND_Null, CH_WEAPON_A, 0, DEATH_NADE.m_id);
339
343
344 setorigin(_nade, w_shotorg + offset);
345 //setmodel(_nade, MDL_PROJECTILE_NADE);
346 //setattachment(_nade, NULL, "");
348 float size;
349 if (STAT(NADES_SMALL, e))
350 size = 16;
351 else
352 size = 32;
353 setsize(_nade, '0.5 0.5 0.5' * -size, '0.5 0.5 0.5' * size);
355
356 tracebox(_nade.origin, _nade.mins, _nade.maxs, _nade.origin, MOVE_NOMONSTERS, _nade);
358 setorigin(_nade, e.origin);
359
360 if (e.v_angle.x >= 70 && e.v_angle.x <= 110 && PHYS_INPUT_BUTTON_CROUCH(e))
361 _nade.velocity = '0 0 100';
363 _nade.velocity = e.velocity + _velocity;
365 _nade.velocity = _velocity;
366 else
367 _nade.velocity = W_CalculateProjectileVelocity(e, e.velocity, _velocity, true);
368
369 if (set_owner)
370 _nade.realowner = e;
371
372 settouch(_nade, nade_touch);
373 _nade.spawnshieldtime = time + 0.1; // prevent instantly picking up again
374 SetResource(_nade, RES_HEALTH, autocvar_g_nades_nade_health);
375 _nade.max_health = GetResource(_nade, RES_HEALTH);
376 _nade.takedamage = DAMAGE_AIM;
377 _nade.event_damage = nade_damage;
378 setcefc(_nade, func_null);
379 _nade.exteriormodeltoclient = NULL;
380 _nade.traileffectnum = 0;
381 _nade.teleportable = true;
382 _nade.pushable = true;
383 _nade.gravity = 1;
384 _nade.missile_flags = MIF_SPLASH | MIF_ARC;
385 _nade.damagedbycontents = true;
387 _nade.angles = vectoangles(_nade.velocity);
388 _nade.flags = FL_PROJECTILE;
389 IL_PUSH(g_projectiles, _nade);
390 IL_PUSH(g_bot_dodge, _nade);
391 _nade.projectiledeathtype = DEATH_NADE.m_id;
392 _nade.toss_time = time;
393 _nade.solid = SOLID_CORPSE; //((STAT(NADE_BONUS_TYPE, _nade) == NADE_TYPE_TRANSLOCATE) ? SOLID_CORPSE : SOLID_BBOX);
394
395 switch (STAT(NADE_BONUS_TYPE, _nade))
396 {
397 case NADE_TYPE_TRANSLOCATE.m_id:
398 case NADE_TYPE_SPAWN.m_id:
399 case NADE_TYPE_MONSTER.m_id:
400 _nade.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
401 break;
402 default:
403 _nade.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY;
404 break;
405 }
406
407 nade_spawn(_nade);
408
409 if (_time)
410 {
411 setthink(_nade, nade_boom);
412 _nade.nextthink = _time;
413 }
414
415 e.nade_refire = time + autocvar_g_nades_nade_refire;
416 STAT(NADE_TIMER, e) = 0;
417}
IntrusiveList g_bot_dodge
Definition api.qh:150
#define PHYS_INPUT_BUTTON_CROUCH(s)
Definition player.qh:156
const int FL_PROJECTILE
Definition constants.qh:85
const float MOVE_NOMONSTERS
float DPCONTENTS_BOTCLIP
float DPCONTENTS_SOLID
const float SOLID_CORPSE
float DPCONTENTS_BODY
float DPCONTENTS_PLAYERCLIP
float trace_startsolid
IntrusiveList g_damagedbycontents
Definition damage.qh:143
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
vector vectoangles(vector v)
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
void Kill_Notification(NOTIF broadcast, entity client, MSG net_type, CPID net_cpid)
Definition all.qc:1537
#define settouch(e, f)
Definition self.qh:73
const int MIF_SPLASH
Definition common.qh:46
const int MIF_ARC
Definition common.qh:47
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
const int CH_WEAPON_A
Definition sound.qh:7
const int DAMAGE_AIM
Definition subs.qh:81
void nade_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition sv_nades.qc:246
void nade_touch(entity this, entity toucher)
Definition sv_nades.qc:192
void nade_spawn(entity _nade)
Definition sv_nades.qc:40
int autocvar_g_nades_nade_newton_style
Definition sv_nades.qh:23
float autocvar_g_nades_nade_health
Definition sv_nades.qh:17
vector autocvar_g_nades_throw_offset
Definition sv_nades.qh:7
vector W_CalculateProjectileVelocity(entity actor, vector pvelocity, vector mvelocity, float forceAbsolute)
Definition tracing.qc:174
vector w_shotorg
Definition tracing.qh:19
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:34

References autocvar_g_nades_nade_health, autocvar_g_nades_nade_newton_style, autocvar_g_nades_nade_refire, autocvar_g_nades_throw_offset, CH_WEAPON_A, DAMAGE_AIM, DPCONTENTS_BODY, DPCONTENTS_BOTCLIP, DPCONTENTS_PLAYERCLIP, DPCONTENTS_SOLID, entity(), FL_PROJECTILE, func_null(), g_bot_dodge, g_damagedbycontents, g_projectiles, GetResource(), IL_PUSH(), Kill_Notification(), makevectors, MIF_ARC, MIF_SPLASH, MOVE_NOMONSTERS, MOVETYPE_BOUNCE, nade_boom(), nade_damage(), nade_spawn(), nade_touch(), NULL, PHYS_INPUT_BUTTON_CROUCH, PROJECTILE_MAKETRIGGER, set_movetype(), setcefc, SetResource(), setthink, settouch, size, SOLID_CORPSE, STAT, time, trace_startsolid, v_forward, v_right, v_up, vectoangles(), vector, W_CalculateProjectileVelocity(), W_SetupShot, and w_shotorg.

Referenced by MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), MUTATOR_HOOKFUNCTION(), and nades_CheckThrow().

Variable Documentation

◆ nade_altbutton

bool nade_altbutton

Definition at line 623 of file sv_nades.qc.

Referenced by nades_CheckThrow().

◆ nade_spawnloc

entity nade_spawnloc

Definition at line 11 of file sv_nades.qc.

Referenced by nades_RemovePlayer().

◆ nade_time_primed

float nade_time_primed

Definition at line 9 of file sv_nades.qc.

◆ OFFHAND_NADE