]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/w_arc.qc
Replace if statements with switches in the weapon request functions
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / w_arc.qc
1 #ifdef REGISTER_WEAPON
2 REGISTER_WEAPON(
3 /* WEP_##id  */ ARC,
4 /* function  */ w_arc,
5 /* ammotype  */ IT_CELLS,
6 /* impulse   */ 5,
7 /* flags     */ WEP_FLAG_NORMAL,
8 /* rating    */ BOT_PICKUP_RATING_HIGH,
9 /* model     */ "arc",
10 /* shortname */ "arc",
11 /* fullname  */ _("Arc")
12 );
13
14 #define ARC_SETTINGS(weapon) \
15         WEP_ADD_CVAR(weapon, MO_BOTH, ammo) \
16         WEP_ADD_CVAR(weapon, MO_PRI,  animtime) \
17         WEP_ADD_CVAR(weapon, MO_PRI,  damage) \
18         WEP_ADD_CVAR(weapon, MO_PRI,  falloff_halflifedist) \
19         WEP_ADD_CVAR(weapon, MO_PRI,  falloff_maxdist) \
20         WEP_ADD_CVAR(weapon, MO_PRI,  falloff_mindist) \
21         WEP_ADD_CVAR(weapon, MO_PRI,  force) \
22         WEP_ADD_CVAR(weapon, MO_PRI,  range) \
23         WEP_ADD_CVAR(weapon, MO_PRI,  refire) \
24         WEP_ADD_PROP(weapon, reloading_ammo, reload_ammo) \
25         WEP_ADD_PROP(weapon, reloading_time, reload_time) \
26         WEP_ADD_PROP(weapon, switchdelay_raise, switchdelay_raise) \
27         WEP_ADD_PROP(weapon, switchdelay_drop, switchdelay_drop)
28
29 #ifndef MENUQC
30 vector arc_shotorigin[4];
31 #endif
32 #ifdef SVQC
33 ARC_SETTINGS(arc)
34 void ArcInit();
35 .vector hook_start, hook_end; // used for beam
36 .entity arc_beam; // used for beam
37 .float BUTTON_ATCK_prev; // for better animation control
38 .float lg_fire_prev; // for better animation control
39 #endif
40 #else
41 #ifdef SVQC
42
43 float W_Arc_Beam_Send(entity to, float sf)
44 {
45         WriteByte(MSG_ENTITY, ENT_CLIENT_ARC_BEAM);
46         sf = sf & 0x7F;
47         if(sound_allowed(MSG_BROADCAST, self.owner))
48                 sf |= 0x80;
49         WriteByte(MSG_ENTITY, sf);
50         if(sf & 1)
51         {
52                 WriteByte(MSG_ENTITY, num_for_edict(self.owner));
53                 WriteCoord(MSG_ENTITY, WEP_CVAR_PRI(arc, range));
54         }
55         if(sf & 2)
56         {
57                 WriteCoord(MSG_ENTITY, self.hook_start_x);
58                 WriteCoord(MSG_ENTITY, self.hook_start_y);
59                 WriteCoord(MSG_ENTITY, self.hook_start_z);
60         }
61         if(sf & 4)
62         {
63                 WriteCoord(MSG_ENTITY, self.hook_end_x);
64                 WriteCoord(MSG_ENTITY, self.hook_end_y);
65                 WriteCoord(MSG_ENTITY, self.hook_end_z);
66         }
67         return TRUE;
68 }
69
70 void W_Arc_Beam_Think()
71 {
72         self.owner.lg_fire_prev = time;
73         if (self != self.owner.arc_beam)
74         {
75                 remove(self);
76                 return;
77         }
78         if (self.owner.weaponentity.state != WS_INUSE || (self.owner.ammo_cells <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)) || self.owner.deadflag != DEAD_NO || !self.owner.BUTTON_ATCK || self.owner.freezetag_frozen)
79         {
80                 if(self == self.owner.arc_beam)
81                         self.owner.arc_beam = world;
82                 remove(self);
83                 return;
84         }
85
86         self.nextthink = time;
87
88         makevectors(self.owner.v_angle);
89
90         float dt, f;
91         dt = frametime;
92         if not(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
93         {
94                 if(WEP_CVAR_PRI(arc, ammo))
95                 {
96                         dt = min(dt, self.owner.ammo_cells / WEP_CVAR_PRI(arc, ammo));
97                         self.owner.ammo_cells = max(0, self.owner.ammo_cells - WEP_CVAR_PRI(arc, ammo) * frametime);
98                 }
99         }
100
101         W_SetupShot_Range(self.owner, TRUE, 0, "", 0, WEP_CVAR_PRI(arc, damage) * dt, WEP_CVAR_PRI(arc, range));
102         WarpZone_traceline_antilag(self.owner, w_shotorg, w_shotend, MOVE_NORMAL, self.owner, ANTILAG_LATENCY(self.owner));
103
104         // apply the damage
105         if(trace_ent)
106         {
107                 vector force;
108                 force = w_shotdir * WEP_CVAR_PRI(arc, force);
109
110                 f = ExponentialFalloff(WEP_CVAR_PRI(arc, falloff_mindist), WEP_CVAR_PRI(arc, falloff_maxdist), WEP_CVAR_PRI(arc, falloff_halflifedist), vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - w_shotorg));
111
112                 if(accuracy_isgooddamage(self.owner, trace_ent))
113                         accuracy_add(self.owner, WEP_ARC, 0, WEP_CVAR_PRI(arc, damage) * dt * f);
114                 Damage (trace_ent, self.owner, self.owner, WEP_CVAR_PRI(arc, damage) * dt * f, WEP_ARC, trace_endpos, force * dt);
115         }
116
117         // draw effect
118         if(w_shotorg != self.hook_start)
119         {
120                 self.SendFlags |= 2;
121                 self.hook_start = w_shotorg;
122         }
123         if(w_shotend != self.hook_end)
124         {
125                 self.SendFlags |= 4;
126                 self.hook_end = w_shotend;
127         }
128 }
129
130 // Attack functions ========================= 
131 void W_Arc_Attack1 (void)
132 {
133         // only play fire sound if 0.5 sec has passed since player let go the fire button
134         if(time - self.lg_fire_prev > 0.5)
135                 sound (self, CH_WEAPON_A, "weapons/lgbeam_fire.wav", VOL_BASE, ATTN_NORM);
136
137         entity beam, oldself;
138
139         self.arc_beam = beam = spawn();
140         beam.classname = "W_Arc_Beam";
141         beam.solid = SOLID_NOT;
142         beam.think = W_Arc_Beam_Think;
143         beam.owner = self;
144         beam.movetype = MOVETYPE_NONE;
145         beam.shot_spread = 1;
146         beam.bot_dodge = TRUE;
147         beam.bot_dodgerating = WEP_CVAR_PRI(arc, damage);
148         Net_LinkEntity(beam, FALSE, 0, W_Arc_Beam_Send);
149
150         oldself = self;
151         self = beam;
152         self.think();
153         self = oldself;
154 }
155
156 float w_arc(float req)
157 {
158         switch(req)
159         {
160                 case WR_AIM:
161                 {
162                         self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
163                         /*
164                         self.BUTTON_ATCK=FALSE;
165                         self.BUTTON_ATCK2=FALSE;
166                         if(vlen(self.origin-self.enemy.origin) > 1000)
167                                 self.bot_aim_whichfiretype = 0;
168                         if(self.bot_aim_whichfiretype == 0)
169                         {
170                                 float shoot;
171
172                                 if(autocvar_g_balance_arc_primary_speed)
173                                         shoot = bot_aim(autocvar_g_balance_arc_primary_speed, 0, autocvar_g_balance_arc_primary_lifetime, FALSE);
174                                 else
175                                         shoot = bot_aim(1000000, 0, 0.001, FALSE);
176
177                                 if(shoot)
178                                 {
179                                         self.BUTTON_ATCK = TRUE;
180                                         if(random() < 0.01) self.bot_aim_whichfiretype = 1;
181                                 }
182                         }
183                         else // todo
184                         {
185                                 //if(bot_aim(autocvar_g_balance_arc_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_arc_secondary_lifetime, TRUE))
186                                 //{
187                                 //      self.BUTTON_ATCK2 = TRUE;
188                                 //      if(random() < 0.03) self.bot_aim_whichfiretype = 0;
189                                 //}
190                         }
191                         */
192                         
193                         return TRUE;
194                 }
195                 case WR_THINK:
196                 {
197                         if (self.BUTTON_ATCK)
198                         {
199                                 if(self.BUTTON_ATCK_prev) // TODO: Find another way to implement this!
200                                         /*if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y)
201                                                 weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
202                                         else*/
203                                                 weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(arc, animtime), w_ready);
204                                 
205                                 if (weapon_prepareattack(0, 0))
206                                 {
207                                         if ((!self.arc_beam) || wasfreed(self.arc_beam))
208                                                 W_Arc_Attack1();
209                                         
210                                         if(!self.BUTTON_ATCK_prev)
211                                         {
212                                                 weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(arc, animtime), w_ready);
213                                                 self.BUTTON_ATCK_prev = 1;
214                                         }
215                                 }
216                         } 
217                         else // todo
218                         {
219                                 if (self.BUTTON_ATCK_prev != 0)
220                                 {
221                                         weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(arc, animtime), w_ready);
222                                         ATTACK_FINISHED(self) = time + WEP_CVAR_PRI(arc, refire) * W_WeaponRateFactor();
223                                 }
224                                 self.BUTTON_ATCK_prev = 0;
225                         }
226
227                         //if (self.BUTTON_ATCK2)
228                                 //if (weapon_prepareattack(1, autocvar_g_balance_arc_secondary_refire))
229                                 //{
230                                 //      W_Arc_Attack2();
231                                 //      self.arc_count = autocvar_g_balance_arc_secondary_count;
232                                 //      weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
233                                 //      self.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor();
234                                 //}
235                                 
236                         return TRUE;
237                 }
238                 case WR_PRECACHE:
239                 {
240                         precache_model ("models/weapons/g_arc.md3");
241                         precache_model ("models/weapons/v_arc.md3");
242                         precache_model ("models/weapons/h_arc.iqm");
243                         //precache_sound ("weapons/arc_bounce.wav");
244                         precache_sound ("weapons/arc_fire.wav");
245                         precache_sound ("weapons/arc_fire2.wav");
246                         precache_sound ("weapons/arc_impact.wav");
247                         //precache_sound ("weapons/arc_impact_combo.wav");
248                         //precache_sound ("weapons/W_Arc_Beam_fire.wav");
249                         return TRUE;
250                 }
251                 case WR_SETUP:
252                 {
253                         weapon_setup(WEP_ARC);
254                         return TRUE;
255                 }
256                 case WR_CHECKAMMO1:
257                 {
258                         return !WEP_CVAR_PRI(arc, ammo) || (self.ammo_cells > 0);
259                 }
260                 case WR_CHECKAMMO2:
261                 {
262                         return self.ammo_cells >= WEP_CVAR_SEC(arc, ammo);
263                 }
264                 case WR_KILLMESSAGE:
265                 {
266                         if(w_deathtype & HITTYPE_SECONDARY)
267                         {
268                                 return WEAPON_ELECTRO_MURDER_ORBS;
269                         }
270                         else
271                         {
272                                 if(w_deathtype & HITTYPE_BOUNCE)
273                                         return WEAPON_ELECTRO_MURDER_COMBO;
274                                 else
275                                         return WEAPON_ELECTRO_MURDER_BOLT;
276                         }
277                 }
278                 case WR_RESETPLAYER:
279                 {
280                         //self.arc_secondarytime = time;
281                         return TRUE;
282                 }
283         }
284         return TRUE;
285 }
286
287 void ArcInit()
288 {
289         weapon_action(WEP_ARC, WR_PRECACHE);
290         arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 1);
291         arc_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 2);
292         arc_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 3);
293         arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 4);
294
295         #define WEP_ADD_CVAR(weapon,mode,name) /*nothing*/
296         #define WEP_ADD_PROP(weapon,prop,name) get_weaponinfo(WEP_ARC).##prop = autocvar_g_balance_##weapon##_##name;
297         ARC_SETTINGS(arc)
298         #undef WEP_ADD_CVAR
299         #undef WEP_ADD_PROP
300 }
301
302 void spawnfunc_weapon_arc (void) // should this really be here?
303 {
304         weapon_defaultspawnfunc(WEP_ARC);
305 }
306 #endif
307 #ifdef CSQC
308 float w_arc(float req)
309 {
310         switch(req)
311         {
312                 case WR_IMPACTEFFECT:
313                 {
314                         vector org2;
315                         org2 = w_org + w_backoff * 6;
316                         
317                         if(w_deathtype & HITTYPE_SECONDARY)
318                         {
319                                 pointparticles(particleeffectnum("arc_ballexplode"), org2, '0 0 0', 1);
320                                 if(!w_issilent)
321                                         sound(self, CH_SHOTS, "weapons/arc_impact.wav", VOL_BASE, ATTN_NORM);
322                         }
323                         else
324                         {
325                                 pointparticles(particleeffectnum("arc_impact"), org2, '0 0 0', 1);
326                                 if(!w_issilent)
327                                         sound(self, CH_SHOTS, "weapons/arc_impact.wav", VOL_BASE, ATTN_NORM);
328                         }
329                         
330                         return TRUE;
331                 }
332                 case WR_PRECACHE:
333                 {
334                         precache_sound("weapons/arc_impact.wav");
335                         precache_sound("weapons/arc_impact_combo.wav");
336                         return TRUE;
337                 }
338         }
339         return TRUE;
340 }
341 #endif
342 #endif