Add cvars for bouncefactor/bouncestop of GL secondary
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / csqcprojectile.qc
1 .float csqcprojectile_type;
2
3 float CSQCProjectile_SendEntity(entity to, float sf)
4 {
5         float ft, fr;
6         float s;
7
8         // note: flag 0x10 = no trail please
9         sf = sf & 0x1F;
10
11         if(self.csqcprojectile_clientanimate)
12                 sf |= 0x80; // client animated, not interpolated
13
14         if(self.flags & FL_ONGROUND)
15                 sf |= 0x40;
16
17         if(self.fade_time != 0 && self.fade_rate != 0)
18         {
19                 ft = (self.fade_time - time) / sys_frametime;
20                 fr = (1 / self.fade_rate) / sys_frametime;
21                 if(ft <= 255 && fr <= 255 && fr >= 1)
22                         sf |= 0x20;
23         }
24
25         // HACK: subflags for sendflags = 0x80
26
27         s = 0;
28
29         if (self.movetype == MOVETYPE_BOUNCEMISSILE || self.movetype == MOVETYPE_BOUNCE)
30                 s |= 1;
31
32         WriteByte(MSG_ENTITY, ENT_CLIENT_PROJECTILE);
33         WriteByte(MSG_ENTITY, sf);
34
35         if(sf & 1)
36         {
37                 WriteCoord(MSG_ENTITY, self.origin_x);
38                 WriteCoord(MSG_ENTITY, self.origin_y);
39                 WriteCoord(MSG_ENTITY, self.origin_z);
40
41                 if(sf & 0x80)
42                 {
43                         WriteCoord(MSG_ENTITY, self.velocity_x);
44                         WriteCoord(MSG_ENTITY, self.velocity_y);
45                         WriteCoord(MSG_ENTITY, self.velocity_z);
46                         WriteCoord(MSG_ENTITY, self.gravity);
47
48                         WriteByte(MSG_ENTITY, s);
49
50                         if (s & 1)
51                         {
52                                 WriteCoord(MSG_ENTITY, self.bouncefactor);
53                                 WriteCoord(MSG_ENTITY, self.bouncestop);
54                         }
55                 }
56
57                 if(sf & 0x20)
58                 {
59                         WriteByte(MSG_ENTITY, ft);
60                         WriteByte(MSG_ENTITY, fr);
61                 }
62         }
63
64         if(sf & 2)
65                 WriteByte(MSG_ENTITY, self.csqcprojectile_type); // TODO maybe put this into sf?
66         
67         return 1;
68 }
69
70 .vector csqcprojectile_oldorigin;
71 void CSQCProjectile_Check(entity e)
72 {
73         if(e.csqcprojectile_clientanimate)
74         if(e.flags & FL_ONGROUND)
75         if(e.origin != e.csqcprojectile_oldorigin)
76                 UpdateCSQCProjectile(e);
77         e.csqcprojectile_oldorigin = e.origin;
78 }
79
80 void CSQCProjectile(entity e, float clientanimate, float type, float docull)
81 {
82         Net_LinkEntity(e, docull, 0, CSQCProjectile_SendEntity);
83         
84         e.csqcprojectile_clientanimate = clientanimate;
85         
86         if(e.movetype == MOVETYPE_TOSS || e.movetype == MOVETYPE_BOUNCE)
87         {
88                 if(e.gravity == 0)
89                         e.gravity = 1;
90         }
91         else
92                 e.gravity = 0;
93
94         e.csqcprojectile_type = type;
95         if(!sound_allowed(MSG_BROADCAST, e))
96                 type |= 0x80;
97 }
98
99 void UpdateCSQCProjectile(entity e)
100 {
101         if(e.SendEntity == CSQCProjectile_SendEntity)
102         {
103                 // send new origin data
104                 e.SendFlags |= 1;
105         }
106 }
107
108 void UpdateCSQCProjectileAfterTeleport(entity e)
109 {
110         if(e.SendEntity == CSQCProjectile_SendEntity)
111         {
112                 // send new origin data and mark as teleported
113                 e.SendFlags |= 0x11;
114         }
115 }
116
117 .void(void) csqcprojectile_oldthink;
118 .float csqcprojectile_oldnextthink;
119
120 void CSQCProjectile_Update_Think()
121 {
122         UpdateCSQCProjectile(self);
123         self.think = self.csqcprojectile_oldthink;
124         self.nextthink = max(time, self.csqcprojectile_oldnextthink);
125 }
126
127 void UpdateCSQCProjectileNextFrame(entity e)
128 {
129         if(e.SendEntity == CSQCProjectile_SendEntity)
130         if(e.think != CSQCProjectile_Update_Think)
131         {
132                 e.csqcprojectile_oldthink = e.think;
133                 e.csqcprojectile_oldnextthink = e.nextthink;
134                 e.think = CSQCProjectile_Update_Think;
135                 e.nextthink = time;
136         }
137 }