]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/weapon/blaster.qc
Entity debugger
[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 spawnfunc(weapon_blaster) { weapon_defaultspawnfunc(WEP_BLASTER.m_id); }
54 spawnfunc(weapon_laser) { spawnfunc_weapon_blaster(this); }
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         entity actor,
88         float atk_deathtype,
89         float atk_shotangle,
90         float atk_damage,
91         float atk_edgedamage,
92         float atk_radius,
93         float atk_force,
94         float atk_speed,
95         float atk_spread,
96         float atk_delay,
97         float atk_lifetime)
98 {SELFPARAM();
99         vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
100
101         W_SetupShot_Dir(actor, s_forward, false, 3, SND(LASERGUN_FIRE), CH_WEAPON_B, atk_damage);
102         Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
103
104         entity missile = new(blasterbolt);
105         missile.owner = missile.realowner = actor;
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, actor, 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(Blaster thiswep, entity actor, int slot, int fire))
164                 {
165                         if(fire & 1)
166                         {
167                                 if(weapon_prepareattack(thiswep, actor, slot, false, WEP_CVAR_PRI(blaster, refire)))
168                                 {
169                                         W_Blaster_Attack(
170                                                 actor,
171                                                 WEP_BLASTER.m_id,
172                                                 WEP_CVAR_PRI(blaster, shotangle),
173                                                 WEP_CVAR_PRI(blaster, damage),
174                                                 WEP_CVAR_PRI(blaster, edgedamage),
175                                                 WEP_CVAR_PRI(blaster, radius),
176                                                 WEP_CVAR_PRI(blaster, force),
177                                                 WEP_CVAR_PRI(blaster, speed),
178                                                 WEP_CVAR_PRI(blaster, spread),
179                                                 WEP_CVAR_PRI(blaster, delay),
180                                                 WEP_CVAR_PRI(blaster, lifetime)
181                                         );
182                                         weapon_thinkf(actor, slot, WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
183                                 }
184                         }
185                         else if(fire & 2)
186                         {
187                                 switch(WEP_CVAR(blaster, secondary))
188                                 {
189                                         case 0: // switch to last used weapon
190                                         {
191                                                 if(actor.switchweapon == WEP_BLASTER.m_id) // don't do this if already switching
192                                                         W_LastWeapon();
193                                                 break;
194                                         }
195
196                                         case 1: // normal projectile secondary
197                                         {
198                                                 if(weapon_prepareattack(thiswep, actor, slot, true, WEP_CVAR_SEC(blaster, refire)))
199                                                 {
200                                                         W_Blaster_Attack(
201                                                                 actor,
202                                                                 WEP_BLASTER.m_id | HITTYPE_SECONDARY,
203                                                                 WEP_CVAR_SEC(blaster, shotangle),
204                                                                 WEP_CVAR_SEC(blaster, damage),
205                                                                 WEP_CVAR_SEC(blaster, edgedamage),
206                                                                 WEP_CVAR_SEC(blaster, radius),
207                                                                 WEP_CVAR_SEC(blaster, force),
208                                                                 WEP_CVAR_SEC(blaster, speed),
209                                                                 WEP_CVAR_SEC(blaster, spread),
210                                                                 WEP_CVAR_SEC(blaster, delay),
211                                                                 WEP_CVAR_SEC(blaster, lifetime)
212                                                         );
213                                                         weapon_thinkf(actor, slot, WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
214                                                 }
215
216                                                 break;
217                                         }
218                                 }
219                         }
220                 }
221
222                 METHOD(Blaster, wr_init, void(entity thiswep))
223                 {
224                         BLASTER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP);
225                 }
226
227                 METHOD(Blaster, wr_setup, void(entity thiswep))
228                 {
229                         self.ammo_field = ammo_none;
230                 }
231
232                 METHOD(Blaster, wr_checkammo1, bool(entity thiswep))
233                 {
234                         return true; // infinite ammo
235                 }
236
237                 METHOD(Blaster, wr_checkammo2, bool(entity thiswep))
238                 {
239                         return true; // blaster has infinite ammo
240                 }
241
242                 METHOD(Blaster, wr_config, void(entity thiswep))
243                 {
244                         BLASTER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS);
245                 }
246
247                 METHOD(Blaster, wr_suicidemessage, int(entity thiswep))
248                 {
249                         return WEAPON_BLASTER_SUICIDE;
250                 }
251
252                 METHOD(Blaster, wr_killmessage, int(entity thiswep))
253                 {
254                         return WEAPON_BLASTER_MURDER;
255                 }
256
257 #endif
258 #ifdef CSQC
259
260                 METHOD(Blaster, wr_impacteffect, void(entity thiswep))
261                 {
262                         vector org2;
263                         org2 = w_org + w_backoff * 6;
264                         pointparticles(particleeffectnum(EFFECT_BLASTER_IMPACT), org2, w_backoff * 1000, 1);
265                         if(!w_issilent) { sound(self, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }
266                 }
267
268 #endif
269 #endif