Weapons: remove useless weapon return values and implementations
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapon / blaster.qc
1 #ifndef IMPLEMENTATION
2 CLASS(Blaster, Weapon)
3 /* ammotype  */ //ATTRIB(Blaster, ammo_field, .int, ammo_none)
4 /* impulse   */ ATTRIB(Blaster, impulse, int, 1)
5 /* flags     */ ATTRIB(Blaster, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH);
6 /* rating    */ ATTRIB(Blaster, bot_pickupbasevalue, float, 0);
7 /* color     */ ATTRIB(Blaster, wpcolor, vector, '1 0.5 0.5');
8 /* modelname */ ATTRIB(Blaster, mdl, string, "laser");
9 #ifndef MENUQC
10 /* model     */ ATTRIB(Blaster, m_model, Model, MDL_BLASTER_ITEM);
11 #endif
12 /* crosshair */ ATTRIB(Blaster, w_crosshair, string, "gfx/crosshairlaser");
13 /* crosshair */ ATTRIB(Blaster, w_crosshair_size, float, 0.5);
14 /* wepimg    */ ATTRIB(Blaster, model2, string, "weaponlaser");
15 /* refname   */ ATTRIB(Blaster, netname, string, "blaster");
16 /* wepname   */ ATTRIB(Blaster, message, string, _("Blaster"));
17 ENDCLASS(Blaster)
18 REGISTER_WEAPON(BLASTER, NEW(Blaster));
19
20 #define BLASTER_SETTINGS(w_cvar,w_prop) BLASTER_SETTINGS_LIST(w_cvar, w_prop, BLASTER, blaster)
21 #define BLASTER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
22         w_cvar(id, sn, BOTH, animtime) \
23         w_cvar(id, sn, BOTH, damage) \
24         w_cvar(id, sn, BOTH, delay) \
25         w_cvar(id, sn, BOTH, edgedamage) \
26         w_cvar(id, sn, BOTH, force) \
27         w_cvar(id, sn, BOTH, force_zscale) \
28         w_cvar(id, sn, BOTH, lifetime) \
29         w_cvar(id, sn, BOTH, radius) \
30         w_cvar(id, sn, BOTH, refire) \
31         w_cvar(id, sn, BOTH, shotangle) \
32         w_cvar(id, sn, BOTH, speed) \
33         w_cvar(id, sn, BOTH, spread) \
34         w_cvar(id, sn, NONE, secondary) \
35         w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
36         w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
37         w_prop(id, sn, string, weaponreplace, weaponreplace) \
38         w_prop(id, sn, float,  weaponstart, weaponstart) \
39         w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
40         w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
41
42 #ifdef SVQC
43 BLASTER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
44 .float blaster_damage;
45 .float blaster_edgedamage;
46 .float blaster_radius;
47 .float blaster_force;
48 .float blaster_lifetime;
49 #endif
50 #endif
51 #ifdef IMPLEMENTATION
52 #ifdef SVQC
53 void spawnfunc_weapon_blaster(void) { weapon_defaultspawnfunc(WEP_BLASTER.m_id); }
54 void spawnfunc_weapon_laser(void) { spawnfunc_weapon_blaster(); }
55
56 void W_Blaster_Touch(void)
57 {SELFPARAM();
58         PROJECTILE_TOUCH;
59
60         self.event_damage = func_null;
61
62         RadiusDamage(
63                 self,
64                 self.realowner,
65                 self.blaster_damage,
66                 self.blaster_edgedamage,
67                 self.blaster_radius,
68                 world,
69                 world,
70                 self.blaster_force,
71                 self.projectiledeathtype,
72                 other
73         );
74
75         remove(self);
76 }
77
78 void W_Blaster_Think(void)
79 {SELFPARAM();
80         self.movetype = MOVETYPE_FLY;
81         self.think = SUB_Remove;
82         self.nextthink = time + self.blaster_lifetime;
83         CSQCProjectile(self, true, PROJECTILE_BLASTER, true);
84 }
85
86 void W_Blaster_Attack(
87         float atk_deathtype,
88         float atk_shotangle,
89         float atk_damage,
90         float atk_edgedamage,
91         float atk_radius,
92         float atk_force,
93         float atk_speed,
94         float atk_spread,
95         float atk_delay,
96         float atk_lifetime)
97 {SELFPARAM();
98         vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
99
100         W_SetupShot_Dir(self, s_forward, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_B, atk_damage);
101         Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
102
103         entity missile = spawn();
104         missile.owner = missile.realowner = self;
105         missile.classname = "blasterbolt";
106         missile.bot_dodge = true;
107         missile.bot_dodgerating = atk_damage;
108         PROJECTILE_MAKETRIGGER(missile);
109
110         missile.blaster_damage = atk_damage;
111         missile.blaster_edgedamage = atk_edgedamage;
112         missile.blaster_radius = atk_radius;
113         missile.blaster_force = atk_force;
114         missile.blaster_lifetime = atk_lifetime;
115
116         setorigin(missile, w_shotorg);
117         setsize(missile, '0 0 0', '0 0 0');
118
119         W_SetupProjVelocity_Explicit(
120                 missile,
121                 w_shotdir,
122                 v_up,
123                 atk_speed,
124                 0,
125                 0,
126                 atk_spread,
127                 false
128         );
129
130         missile.angles = vectoangles(missile.velocity);
131
132         //missile.glow_color = 250; // 244, 250
133         //missile.glow_size = 120;
134
135         missile.touch = W_Blaster_Touch;
136         missile.flags = FL_PROJECTILE;
137         missile.missile_flags = MIF_SPLASH;
138         missile.projectiledeathtype = atk_deathtype;
139         missile.think = W_Blaster_Think;
140         missile.nextthink = time + atk_delay;
141
142         MUTATOR_CALLHOOK(EditProjectile, self, missile);
143
144         if(time >= missile.nextthink)
145         {
146                 WITH(entity, self, missile, missile.think());
147         }
148 }
149
150                 METHOD(Blaster, wr_aim, void(entity thiswep))
151                 {
152                         if(WEP_CVAR(blaster, secondary))
153                         {
154                                 if((random() * (WEP_CVAR_PRI(blaster, damage) + WEP_CVAR_SEC(blaster, damage))) > WEP_CVAR_PRI(blaster, damage))
155                                         { self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(blaster, speed), 0, WEP_CVAR_SEC(blaster, lifetime), false); }
156                                 else
157                                         { self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
158                         }
159                         else
160                                 { self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
161                 }
162
163                 METHOD(Blaster, wr_think, void(entity thiswep, bool fire1, bool fire2))
164                 {
165                         if(fire1)
166                         {
167                                 if(weapon_prepareattack(false, WEP_CVAR_PRI(blaster, refire)))
168                                 {
169                                         W_Blaster_Attack(
170                                                 WEP_BLASTER.m_id,
171                                                 WEP_CVAR_PRI(blaster, shotangle),
172                                                 WEP_CVAR_PRI(blaster, damage),
173                                                 WEP_CVAR_PRI(blaster, edgedamage),
174                                                 WEP_CVAR_PRI(blaster, radius),
175                                                 WEP_CVAR_PRI(blaster, force),
176                                                 WEP_CVAR_PRI(blaster, speed),
177                                                 WEP_CVAR_PRI(blaster, spread),
178                                                 WEP_CVAR_PRI(blaster, delay),
179                                                 WEP_CVAR_PRI(blaster, lifetime)
180                                         );
181                                         weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
182                                 }
183                         }
184                         else if(fire2)
185                         {
186                                 switch(WEP_CVAR(blaster, secondary))
187                                 {
188                                         case 0: // switch to last used weapon
189                                         {
190                                                 if(self.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
191                                                         W_LastWeapon();
192                                                 break;
193                                         }
194
195                                         case 1: // normal projectile secondary
196                                         {
197                                                 if(weapon_prepareattack(true, WEP_CVAR_SEC(blaster, refire)))
198                                                 {
199                                                         W_Blaster_Attack(
200                                                                 WEP_BLASTER.m_id | HITTYPE_SECONDARY,
201                                                                 WEP_CVAR_SEC(blaster, shotangle),
202                                                                 WEP_CVAR_SEC(blaster, damage),
203                                                                 WEP_CVAR_SEC(blaster, edgedamage),
204                                                                 WEP_CVAR_SEC(blaster, radius),
205                                                                 WEP_CVAR_SEC(blaster, force),
206                                                                 WEP_CVAR_SEC(blaster, speed),
207                                                                 WEP_CVAR_SEC(blaster, spread),
208                                                                 WEP_CVAR_SEC(blaster, delay),
209                                                                 WEP_CVAR_SEC(blaster, lifetime)
210                                                         );
211                                                         weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
212                                                 }
213
214                                                 break;
215                                         }
216                                 }
217                         }
218                 }
219
220                 METHOD(Blaster, wr_init, void(entity thiswep))
221                 {
222                         BLASTER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
223                 }
224
225                 METHOD(Blaster, wr_setup, void(entity thiswep))
226                 {
227                         self.ammo_field = ammo_none;
228                 }
229
230                 METHOD(Blaster, wr_checkammo1, bool(entity thiswep))
231                 {
232                         return true; // infinite ammo
233                 }
234
235                 METHOD(Blaster, wr_checkammo2, bool(entity thiswep))
236                 {
237                         return true; // blaster has infinite ammo
238                 }
239
240                 METHOD(Blaster, wr_config, void(entity thiswep))
241                 {
242                         BLASTER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
243                 }
244
245                 METHOD(Blaster, wr_suicidemessage, int(entity thiswep))
246                 {
247                         return WEAPON_BLASTER_SUICIDE;
248                 }
249
250                 METHOD(Blaster, wr_killmessage, int(entity thiswep))
251                 {
252                         return WEAPON_BLASTER_MURDER;
253                 }
254
255 #endif
256 #ifdef CSQC
257
258                 METHOD(Blaster, wr_impacteffect, void(entity thiswep))
259                 {
260                         vector org2;
261                         org2 = w_org + w_backoff * 6;
262                         pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
263                         if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
264                 }
265
266 #endif
267 #endif