]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/w_arc.qc
Remove individual weapon.qh files, make it compile
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / w_arc.qc
1 #ifdef REGISTER_WEAPON
2 REGISTER_WEAPON(
3 /* WEP_##id  */ LIGHTNING,
4 /* function  */ w_lightning,
5 /* ammotype  */ IT_CELLS,
6 /* impulse   */ 5,
7 /* flags     */ WEP_FLAG_NORMAL | WEP_TYPE_SPLASH,
8 /* rating    */ BOT_PICKUP_RATING_MID,
9 /* model     */ "lightning",
10 /* shortname */ "lightning",
11 /* fullname  */ _("Lightning")
12 );
13
14 #ifdef SVQC
15 void LightningInit();
16 vector lightning_shotorigin[4];
17 #endif
18 #else
19 #ifdef SVQC
20
21 // Declarations ========================= 
22 .vector hook_start, hook_end; // used for beam
23 .entity lightning_beam; // used for beam
24 .float BUTTON_ATCK_prev; // for better animation control
25 .float lg_fire_prev; // for better animation control
26
27 // Lightning functions ========================= 
28 float W_Lightning_Beam_Send(entity to, float sf)
29 {
30         WriteByte(MSG_ENTITY, ENT_CLIENT_LIGHTNING_BEAM);
31         sf = sf & 0x7F;
32         if(sound_allowed(MSG_BROADCAST, self.owner))
33                 sf |= 0x80;
34         WriteByte(MSG_ENTITY, sf);
35         if(sf & 1)
36         {
37                 WriteByte(MSG_ENTITY, num_for_edict(self.owner));
38                 WriteCoord(MSG_ENTITY, autocvar_g_balance_lightning_primary_range);
39         }
40         if(sf & 2)
41         {
42                 WriteCoord(MSG_ENTITY, self.hook_start_x);
43                 WriteCoord(MSG_ENTITY, self.hook_start_y);
44                 WriteCoord(MSG_ENTITY, self.hook_start_z);
45         }
46         if(sf & 4)
47         {
48                 WriteCoord(MSG_ENTITY, self.hook_end_x);
49                 WriteCoord(MSG_ENTITY, self.hook_end_y);
50                 WriteCoord(MSG_ENTITY, self.hook_end_z);
51         }
52         return TRUE;
53 }
54
55 void W_Lightning_Beam_Think()
56 {
57         self.owner.lg_fire_prev = time;
58         if (self != self.owner.lightning_beam)
59         {
60                 remove(self);
61                 return;
62         }
63         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)
64         {
65                 if(self == self.owner.lightning_beam)
66                         self.owner.lightning_beam = world;
67                 remove(self);
68                 return;
69         }
70
71         self.nextthink = time;
72
73         makevectors(self.owner.v_angle);
74
75         float dt, f;
76         dt = frametime;
77         if not(self.owner.items & IT_UNLIMITED_WEAPON_AMMO)
78         {
79                 if(autocvar_g_balance_lightning_primary_ammo)
80                 {
81                         dt = min(dt, self.owner.ammo_cells / autocvar_g_balance_lightning_primary_ammo);
82                         self.owner.ammo_cells = max(0, self.owner.ammo_cells - autocvar_g_balance_lightning_primary_ammo * frametime);
83                 }
84         }
85
86         W_SetupShot_Range(self.owner, TRUE, 0, "", 0, autocvar_g_balance_lightning_primary_damage * dt, autocvar_g_balance_lightning_primary_range);
87         WarpZone_traceline_antilag(self.owner, w_shotorg, w_shotend, MOVE_NORMAL, self.owner, ANTILAG_LATENCY(self.owner));
88
89         // apply the damage
90         if(trace_ent)
91         {
92                 vector force;
93                 force = w_shotdir * autocvar_g_balance_lightning_primary_force;
94
95                 f = ExponentialFalloff(autocvar_g_balance_lightning_primary_falloff_mindist, autocvar_g_balance_lightning_primary_falloff_maxdist, autocvar_g_balance_lightning_primary_falloff_halflifedist, vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - w_shotorg));
96
97                 if(accuracy_isgooddamage(self.owner, trace_ent))
98                         accuracy_add(self.owner, WEP_LIGHTNING, 0, autocvar_g_balance_lightning_primary_damage * dt * f);
99                 Damage (trace_ent, self.owner, self.owner, autocvar_g_balance_lightning_primary_damage * dt * f, WEP_LIGHTNING, trace_endpos, force * dt);
100         }
101
102         // draw effect
103         if(w_shotorg != self.hook_start)
104         {
105                 self.SendFlags |= 2;
106                 self.hook_start = w_shotorg;
107         }
108         if(w_shotend != self.hook_end)
109         {
110                 self.SendFlags |= 4;
111                 self.hook_end = w_shotend;
112         }
113 }
114
115 // Attack functions ========================= 
116 void W_Lightning_Attack1 (void)
117 {
118         // only play fire sound if 0.5 sec has passed since player let go the fire button
119         if(time - self.lg_fire_prev > 0.5)
120                 sound (self, CH_WEAPON_A, "weapons/lgbeam_fire.wav", VOL_BASE, ATTN_NORM);
121
122         entity beam, oldself;
123
124         self.lightning_beam = beam = spawn();
125         beam.classname = "W_Lightning_Beam";
126         beam.solid = SOLID_NOT;
127         beam.think = W_Lightning_Beam_Think;
128         beam.owner = self;
129         beam.movetype = MOVETYPE_NONE;
130         beam.shot_spread = 1;
131         beam.bot_dodge = TRUE;
132         beam.bot_dodgerating = autocvar_g_balance_lightning_primary_damage;
133         Net_LinkEntity(beam, FALSE, 0, W_Lightning_Beam_Send);
134
135         oldself = self;
136         self = beam;
137         self.think();
138         self = oldself;
139 }
140
141 float w_lightning(float req)
142 {
143         if (req == WR_AIM)
144         {
145                 self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
146                 /*
147                 self.BUTTON_ATCK=FALSE;
148                 self.BUTTON_ATCK2=FALSE;
149                 if(vlen(self.origin-self.enemy.origin) > 1000)
150                         self.bot_aim_whichfiretype = 0;
151                 if(self.bot_aim_whichfiretype == 0)
152                 {
153                         float shoot;
154
155                         if(autocvar_g_balance_lightning_primary_speed)
156                                 shoot = bot_aim(autocvar_g_balance_lightning_primary_speed, 0, autocvar_g_balance_lightning_primary_lifetime, FALSE);
157                         else
158                                 shoot = bot_aim(1000000, 0, 0.001, FALSE);
159
160                         if(shoot)
161                         {
162                                 self.BUTTON_ATCK = TRUE;
163                                 if(random() < 0.01) self.bot_aim_whichfiretype = 1;
164                         }
165                 }
166                 else // todo
167                 {
168                         //if(bot_aim(autocvar_g_balance_lightning_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_lightning_secondary_lifetime, TRUE))
169                         //{
170                         //      self.BUTTON_ATCK2 = TRUE;
171                         //      if(random() < 0.03) self.bot_aim_whichfiretype = 0;
172                         //}
173                 }
174                 */
175         }
176         else if (req == WR_THINK)
177         {
178                 if (self.BUTTON_ATCK)
179                 {
180                         if(self.BUTTON_ATCK_prev) // TODO: Find another way to implement this!
181                                 /*if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y)
182                                         weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_lightning_primary_animtime, w_ready);
183                                 else*/
184                                         weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_lightning_primary_animtime, w_ready);
185                         
186                         if (weapon_prepareattack(0, 0))
187                         {
188                                 if ((!self.lightning_beam) || wasfreed(self.lightning_beam))
189                                         W_Lightning_Attack1();
190                                 
191                                 if(!self.BUTTON_ATCK_prev)
192                                 {
193                                         weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_lightning_primary_animtime, w_ready);
194                                         self.BUTTON_ATCK_prev = 1;
195                                 }
196                         }
197                 } 
198                 else // todo
199                 {
200                         if (self.BUTTON_ATCK_prev != 0)
201                         {
202                                 weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_lightning_primary_animtime, w_ready);
203                                 ATTACK_FINISHED(self) = time + autocvar_g_balance_lightning_primary_refire * W_WeaponRateFactor();
204                         }
205                         self.BUTTON_ATCK_prev = 0;
206                 }
207
208                 //if (self.BUTTON_ATCK2)
209                         //if (weapon_prepareattack(1, autocvar_g_balance_lightning_secondary_refire))
210                         //{
211                         //      W_Lightning_Attack2();
212                         //      self.lightning_count = autocvar_g_balance_lightning_secondary_count;
213                         //      weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_lightning_secondary_animtime, w_lightning_checkattack);
214                         //      self.lightning_secondarytime = time + autocvar_g_balance_lightning_secondary_refire2 * W_WeaponRateFactor();
215                         //}
216         }
217         else if (req == WR_PRECACHE)
218         {
219                 precache_model ("models/weapons/g_lightning.md3");
220                 precache_model ("models/weapons/v_lightning.md3");
221                 precache_model ("models/weapons/h_lightning.iqm");
222                 //precache_sound ("weapons/lightning_bounce.wav");
223                 precache_sound ("weapons/lightning_fire.wav");
224                 precache_sound ("weapons/lightning_fire2.wav");
225                 precache_sound ("weapons/lightning_impact.wav");
226                 //precache_sound ("weapons/lightning_impact_combo.wav");
227                 //precache_sound ("weapons/W_Lightning_Beam_fire.wav");
228         }
229         else if (req == WR_SETUP)
230                 weapon_setup(WEP_LIGHTNING);
231         else if (req == WR_CHECKAMMO1)
232         {
233                 return !autocvar_g_balance_lightning_primary_ammo || (self.ammo_cells > 0);
234         }
235         else if (req == WR_CHECKAMMO2)
236                 return self.ammo_cells >= autocvar_g_balance_lightning_secondary_ammo;
237         else if (req == WR_KILLMESSAGE)
238         {
239                 if(w_deathtype & HITTYPE_SECONDARY)
240                 {
241                         return WEAPON_ELECTRO_MURDER_ORBS;
242                 }
243                 else
244                 {
245                         if(w_deathtype & HITTYPE_BOUNCE)
246                                 return WEAPON_ELECTRO_MURDER_COMBO;
247                         else
248                                 return WEAPON_ELECTRO_MURDER_BOLT;
249                 }
250         }
251         else if (req == WR_RESETPLAYER)
252         {
253                 //self.lightning_secondarytime = time;
254         }
255         return TRUE;
256 };
257
258 void LightningInit()
259 {
260         weapon_action(WEP_LIGHTNING, WR_PRECACHE);
261         lightning_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LIGHTNING), FALSE, FALSE, 1);
262         lightning_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LIGHTNING), FALSE, FALSE, 2);
263         lightning_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LIGHTNING), FALSE, FALSE, 3);
264         lightning_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LIGHTNING), FALSE, FALSE, 4);
265 }
266
267 void spawnfunc_weapon_lightning (void) // should this really be here?
268 {
269         weapon_defaultspawnfunc(WEP_LIGHTNING);
270 }
271 #endif
272 #ifdef CSQC
273 float w_lightning(float req)
274 {
275         if(req == WR_IMPACTEFFECT)
276         {
277                 vector org2;
278                 org2 = w_org + w_backoff * 6;
279                 
280                 if(w_deathtype & HITTYPE_SECONDARY)
281                 {
282                         pointparticles(particleeffectnum("lightning_ballexplode"), org2, '0 0 0', 1);
283                         if(!w_issilent)
284                                 sound(self, CH_SHOTS, "weapons/lightning_impact.wav", VOL_BASE, ATTN_NORM);
285                 }
286                 else
287                 {
288                         pointparticles(particleeffectnum("lightning_impact"), org2, '0 0 0', 1);
289                         if(!w_issilent)
290                                 sound(self, CH_SHOTS, "weapons/lightning_impact.wav", VOL_BASE, ATTN_NORM);
291                 }
292         }
293         else if(req == WR_PRECACHE)
294         {
295                 precache_sound("weapons/lightning_impact.wav");
296                 precache_sound("weapons/lightning_impact_combo.wav");
297         }
298         return TRUE;
299 }
300 #endif
301 #endif