Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
casings.qc
Go to the documentation of this file.
1#include "casings.qh"
2
3#include <common/replicate.qh>
4#include <common/util.qh>
5
6#ifdef CSQC
8#include "rubble.qh"
9#endif
10
11REGISTER_NET_TEMP(casings)
12
13REPLICATE(cvar_cl_casings, bool, "cl_casings");
14REPLICATE(cvar_r_drawviewmodel, int, "r_drawviewmodel");
15
16#ifdef SVQC
17void SpawnCasing(vector vel, vector ang, int casingtype, entity casingowner, .entity weaponentity)
18{
19 vector org = casingowner.(weaponentity).spawnorigin;
20 org = casingowner.origin + casingowner.view_ofs + org.x * v_forward - org.y * v_right + org.z * v_up;
21
22 FOREACH_CLIENT(true, {
23 if (!(CS_CVAR(it).cvar_cl_casings))
24 continue;
25
26 casingtype &= 0x3F; // reset any bitflags that were set for the previous client
27
28 if (it == casingowner || (IS_SPEC(it) && it.enemy == casingowner))
29 {
30 if (!(CS_CVAR(it).cvar_r_drawviewmodel))
31 continue;
32
33 casingtype |= 0x40; // client will apply autocvar_cl_gunoffset in first person
34 }
35 else if (1 & ~checkpvs(it.origin + it.view_ofs, casingowner)) // 1 or 3 means visible
36 continue;
37
38 msg_entity = it; // sound_allowed checks this
39 if (!sound_allowed(MSG_ONE, it))
40 casingtype |= 0x80; // silent
41
42 WriteHeader(MSG_ONE, casings);
43 WriteByte(MSG_ONE, casingtype);
44 WriteVector(MSG_ONE, org);
45 WriteShort(MSG_ONE, compressShortVector(vel)); // actually compressed velocity
46 WriteByte(MSG_ONE, ang.x * 256 / 360);
47 WriteByte(MSG_ONE, ang.y * 256 / 360);
48 // weapons only have pitch and yaw, so no need to send ang.z
49 });
50}
51#endif
52
53#ifdef CSQC
55classfield(Casing) .float alpha;
56classfield(Casing) .bool silent;
57classfield(Casing) .int state;
58classfield(Casing) .float cnt;
59
60// this is only needed because LimitedChildrenRubble() takes a func pointer
62{
63 delete(this);
64}
65
67{
68 if (IS_ONGROUND(this))
69 {
70 this.angles_x = 0;
71 this.angles_z = 0;
72 //UNSET_ONGROUND(this);
73 }
74
75 this.renderflags = 0;
76 this.alpha = bound(0, this.cnt - time, 1);
77
78 if (this.alpha < ALPHA_MIN_VISIBLE)
79 {
80 delete(this);
81 this.drawmask = 0;
82 return;
83 }
84
85 trace_startsolid = 0; // due to cl_casings_ticrate, traces are not always performed
87 //if (wasfreed(this))
88 // return; // deleted by touch function
89
90 // prevent glitchy casings when the gun model is poking into a wall
91 // doing this here is cheaper than doing it on the server as the client performs the trace anyway
93 {
94 delete(this);
95 this.drawmask = 0;
96 return;
97 }
98}
99
100SOUND(BRASS1, W_Sound("brass1"));
101SOUND(BRASS2, W_Sound("brass2"));
102SOUND(BRASS3, W_Sound("brass3"));
104 return REGISTRY_GET(Sounds, SND_BRASS1.m_id + floor(prandom() * 3));
105}
106SOUND(CASINGS1, W_Sound("casings1"));
107SOUND(CASINGS2, W_Sound("casings2"));
108SOUND(CASINGS3, W_Sound("casings3"));
110 return REGISTRY_GET(Sounds, SND_CASINGS1.m_id + floor(prandom() * 3));
111}
112
114{
116 {
117 delete(this);
118 return;
119 }
120
121 if (!this.silent)
122 if (!trace_ent || trace_ent.solid == SOLID_BSP)
123 {
124 if(vdist(this.velocity, >, 50))
125 {
126 if (time >= this.nextthink)
127 {
128 Sound s;
129 switch (this.state)
130 {
131 case 1:
132 s = SND_CASINGS_RANDOM();
133 break;
134 default:
135 s = SND_BRASS_RANDOM();
136 break;
137 }
138
139 sound (this, CH_SHOTS, s, VOL_BASE, ATTEN_LARGE);
140 }
141 }
142 }
143
144 this.nextthink = time + 0.2;
145}
146
147void Casing_Damage(entity this, float thisdmg, int hittype, vector org, vector thisforce)
148{
149 if (thisforce.z < 0)
150 thisforce.z = 0;
151 this.velocity = this.velocity + thisforce + '0 0 100';
152 UNSET_ONGROUND(this);
153}
154
155NET_HANDLE(casings, bool isNew)
156{
157 Casing casing = ListNewChildRubble(CasingsNGibs, new(casing));
158
159 casing.state = ReadByte();
160 casing.origin = ReadVector();
161 casing.velocity = decompressShortVector(ReadShort());
162 casing.angles_x = ReadByte() * 360 / 256;
163 casing.angles_y = ReadByte() * 360 / 256;
164
165 return = true;
166
167 casing.silent = casing.state & 0x80;
168 if ((casing.state & 0x40) && !autocvar_chase_active)
169 casing.origin += autocvar_cl_gunoffset.x * v_forward
172 casing.state &= 0x3F; // the 2 most significant bits are reserved for the silent and casingowner bitflags
173
174 setorigin(casing, casing.origin);
175 casing.drawmask = MASK_NORMAL;
176 casing.draw = Casing_Draw;
177 if (isNew) IL_PUSH(g_drawables, casing);
178 casing.velocity += 2 * prandomvec();
179 casing.avelocity = '0 10 0' + 100 * prandomvec();
181 settouch(casing, Casing_Touch);
182 casing.move_time = time;
183 casing.event_damage = Casing_Damage;
184 casing.solid = SOLID_TRIGGER;
185
186 switch (casing.state)
187 {
188 case 1:
189 setmodel(casing, MDL_CASING_SHELL);
190 casing.bouncefactor = 0.25;
192 break;
193 default:
194 setmodel(casing, MDL_CASING_BULLET);
195 casing.bouncefactor = 0.5;
197 break;
198 }
199
201}
202
203#endif
void Casing_Draw(entity this)
Definition casings.qc:66
void Casing_Touch(entity this, entity toucher)
Definition casings.qc:113
Sound SND_CASINGS_RANDOM()
Definition casings.qc:109
void Casing_Delete(entity this)
Definition casings.qc:61
void SpawnCasing(vector vel, vector ang, int casingtype, entity casingowner,.entity weaponentity)
Definition casings.qc:17
void Casing_Damage(entity this, float thisdmg, int hittype, vector org, vector thisforce)
Definition casings.qc:147
Sound SND_BRASS_RANDOM()
Definition casings.qc:103
int autocvar_cl_casings_maxcount
Definition casings.qh:5
bool autocvar_cl_casings_sloppy
Definition casings.qh:7
float autocvar_cl_casings_ticrate
Definition casings.qh:8
float autocvar_cl_casings_shell_time
Definition casings.qh:6
float autocvar_cl_casings_bronze_time
Definition casings.qh:4
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
float cnt
Definition powerups.qc:24
float alpha
Definition items.qc:13
IntrusiveList g_drawables
Definition main.qh:91
float renderflags
Definition main.qh:111
const float ALPHA_MIN_VISIBLE
Definition main.qh:158
#define setmodel(this, m)
Definition model.qh:26
float compressShortVector(vector vec)
Definition util.qc:521
vector decompressShortVector(int data)
Definition util.qc:486
vector v_up
float drawmask
entity trace_ent
const float SOLID_TRIGGER
const float MASK_NORMAL
vector velocity
float time
vector v_right
float checkpvs(vector viewpos, entity viewee)
float trace_startsolid
float nextthink
float trace_dphitq3surfaceflags
vector v_forward
float Q3SURFACEFLAG_NOIMPACT
const float SOLID_BSP
int state
bool silent
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define NET_HANDLE(id, param)
Definition net.qh:15
#define ReadVector()
Definition net.qh:367
#define WriteHeader(to, id)
Definition net.qh:221
int ReadByte()
#define REGISTER_NET_TEMP(id)
Definition net.qh:28
#define REPLICATE(...)
Replicates a client cvar into a server field.
Definition replicate.qh:23
float MSG_ONE
Definition menudefs.qc:56
float bound(float min, float value, float max)
void WriteShort(float data, float dest, float desto)
void WriteByte(float data, float dest, float desto)
float floor(float f)
void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)
Definition movetypes.qc:835
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
#define UNSET_ONGROUND(s)
Definition movetypes.qh:18
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
#define IS_ONGROUND(s)
Definition movetypes.qh:16
#define entityclass(...)
Definition oo.qh:52
#define classfield(name)
Definition oo.qh:57
#define NULL
Definition post.qh:14
entity msg_entity
Definition progsdefs.qc:63
float prandom()
Predictable random number generator (not seeded yet)
Definition random.qc:108
vector prandomvec()
Definition random.qc:121
#define REGISTRY_GET(id, i)
Definition registry.qh:43
void LimitedChildrenRubble(IntrusiveList list, string cname, int limit, void(entity) deleteproc, entity parent)
Definition rubble.qc:5
entity ListNewChildRubble(IntrusiveList list, entity child)
Definition rubble.qc:46
IntrusiveList CasingsNGibs
Definition rubble.qh:8
vector
Definition self.qh:92
vector org
Definition self.qh:92
entity entity toucher
Definition self.qh:72
vector vector ang
Definition self.qh:92
#define settouch(e, f)
Definition self.qh:73
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
#define sound(e, c, s, v, a)
Definition sound.qh:52
const float ATTEN_LARGE
Definition sound.qh:31
string W_Sound(string w_snd)
Definition all.qc:225
bool sound_allowed(int to, entity e)
Definition all.qc:9
#define SOUND(name, path)
Definition all.qh:30
#define CS_CVAR(this)
Definition state.qh:51
#define IS_SPEC(v)
Definition utils.qh:10
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:50
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
int autocvar_chase_active
Definition view.qh:17
vector autocvar_cl_gunoffset
Definition view.qh:98
vector spawnorigin
Definition all.qh:391