]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/w_arc.qc
Now make the Devastator compile and run (mostly)
[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         if (req == WR_AIM)
159         {
160                 self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
161                 /*
162                 self.BUTTON_ATCK=FALSE;
163                 self.BUTTON_ATCK2=FALSE;
164                 if(vlen(self.origin-self.enemy.origin) > 1000)
165                         self.bot_aim_whichfiretype = 0;
166                 if(self.bot_aim_whichfiretype == 0)
167                 {
168                         float shoot;
169
170                         if(autocvar_g_balance_arc_primary_speed)
171                                 shoot = bot_aim(autocvar_g_balance_arc_primary_speed, 0, autocvar_g_balance_arc_primary_lifetime, FALSE);
172                         else
173                                 shoot = bot_aim(1000000, 0, 0.001, FALSE);
174
175                         if(shoot)
176                         {
177                                 self.BUTTON_ATCK = TRUE;
178                                 if(random() < 0.01) self.bot_aim_whichfiretype = 1;
179                         }
180                 }
181                 else // todo
182                 {
183                         //if(bot_aim(autocvar_g_balance_arc_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_arc_secondary_lifetime, TRUE))
184                         //{
185                         //      self.BUTTON_ATCK2 = TRUE;
186                         //      if(random() < 0.03) self.bot_aim_whichfiretype = 0;
187                         //}
188                 }
189                 */
190         }
191         else if (req == WR_THINK)
192         {
193                 if (self.BUTTON_ATCK)
194                 {
195                         if(self.BUTTON_ATCK_prev) // TODO: Find another way to implement this!
196                                 /*if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y)
197                                         weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
198                                 else*/
199                                         weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(arc, animtime), w_ready);
200                         
201                         if (weapon_prepareattack(0, 0))
202                         {
203                                 if ((!self.arc_beam) || wasfreed(self.arc_beam))
204                                         W_Arc_Attack1();
205                                 
206                                 if(!self.BUTTON_ATCK_prev)
207                                 {
208                                         weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(arc, animtime), w_ready);
209                                         self.BUTTON_ATCK_prev = 1;
210                                 }
211                         }
212                 } 
213                 else // todo
214                 {
215                         if (self.BUTTON_ATCK_prev != 0)
216                         {
217                                 weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(arc, animtime), w_ready);
218                                 ATTACK_FINISHED(self) = time + WEP_CVAR_PRI(arc, refire) * W_WeaponRateFactor();
219                         }
220                         self.BUTTON_ATCK_prev = 0;
221                 }
222
223                 //if (self.BUTTON_ATCK2)
224                         //if (weapon_prepareattack(1, autocvar_g_balance_arc_secondary_refire))
225                         //{
226                         //      W_Arc_Attack2();
227                         //      self.arc_count = autocvar_g_balance_arc_secondary_count;
228                         //      weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
229                         //      self.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor();
230                         //}
231         }
232         else if (req == WR_PRECACHE)
233         {
234                 precache_model ("models/weapons/g_arc.md3");
235                 precache_model ("models/weapons/v_arc.md3");
236                 precache_model ("models/weapons/h_arc.iqm");
237                 //precache_sound ("weapons/arc_bounce.wav");
238                 precache_sound ("weapons/arc_fire.wav");
239                 precache_sound ("weapons/arc_fire2.wav");
240                 precache_sound ("weapons/arc_impact.wav");
241                 //precache_sound ("weapons/arc_impact_combo.wav");
242                 //precache_sound ("weapons/W_Arc_Beam_fire.wav");
243         }
244         else if (req == WR_SETUP)
245                 weapon_setup(WEP_ARC);
246         else if (req == WR_CHECKAMMO1)
247         {
248                 return !WEP_CVAR_PRI(arc, ammo) || (self.ammo_cells > 0);
249         }
250         else if (req == WR_CHECKAMMO2)
251                 return self.ammo_cells >= WEP_CVAR_SEC(arc, ammo);
252         else if (req == WR_KILLMESSAGE)
253         {
254                 if(w_deathtype & HITTYPE_SECONDARY)
255                 {
256                         return WEAPON_ELECTRO_MURDER_ORBS;
257                 }
258                 else
259                 {
260                         if(w_deathtype & HITTYPE_BOUNCE)
261                                 return WEAPON_ELECTRO_MURDER_COMBO;
262                         else
263                                 return WEAPON_ELECTRO_MURDER_BOLT;
264                 }
265         }
266         else if (req == WR_RESETPLAYER)
267         {
268                 //self.arc_secondarytime = time;
269         }
270         return TRUE;
271 };
272
273 void ArcInit()
274 {
275         weapon_action(WEP_ARC, WR_PRECACHE);
276         arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 1);
277         arc_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 2);
278         arc_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 3);
279         arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 4);
280
281         #define WEP_ADD_CVAR(weapon,mode,name) /*nothing*/
282         #define WEP_ADD_PROP(weapon,prop,name) get_weaponinfo(WEP_ARC).##prop = autocvar_g_balance_##weapon##_##name;
283         ARC_SETTINGS(arc)
284         #undef WEP_ADD_CVAR
285         #undef WEP_ADD_PROP
286 }
287
288 void spawnfunc_weapon_arc (void) // should this really be here?
289 {
290         weapon_defaultspawnfunc(WEP_ARC);
291 }
292 #endif
293 #ifdef CSQC
294 float w_arc(float req)
295 {
296         if(req == WR_IMPACTEFFECT)
297         {
298                 vector org2;
299                 org2 = w_org + w_backoff * 6;
300                 
301                 if(w_deathtype & HITTYPE_SECONDARY)
302                 {
303                         pointparticles(particleeffectnum("arc_ballexplode"), org2, '0 0 0', 1);
304                         if(!w_issilent)
305                                 sound(self, CH_SHOTS, "weapons/arc_impact.wav", VOL_BASE, ATTN_NORM);
306                 }
307                 else
308                 {
309                         pointparticles(particleeffectnum("arc_impact"), org2, '0 0 0', 1);
310                         if(!w_issilent)
311                                 sound(self, CH_SHOTS, "weapons/arc_impact.wav", VOL_BASE, ATTN_NORM);
312                 }
313         }
314         else if(req == WR_PRECACHE)
315         {
316                 precache_sound("weapons/arc_impact.wav");
317                 precache_sound("weapons/arc_impact_combo.wav");
318         }
319         return TRUE;
320 }
321 #endif
322 #endif