]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/weapon/hlac.qc
Merge branch 'master' into Mario/weaponentities
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapon / hlac.qc
1 #ifndef IMPLEMENTATION
2 CLASS(HLAC, Weapon)
3 /* ammotype  */ ATTRIB(HLAC, ammo_field, .int, ammo_cells)
4 /* impulse   */ ATTRIB(HLAC, impulse, int, 6)
5 /* flags     */ ATTRIB(HLAC, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH);
6 /* rating    */ ATTRIB(HLAC, bot_pickupbasevalue, float, BOT_PICKUP_RATING_MID);
7 /* color     */ ATTRIB(HLAC, wpcolor, vector, '0 1 0');
8 /* modelname */ ATTRIB(HLAC, mdl, string, "hlac");
9 #ifndef MENUQC
10 /* model     */ ATTRIB(HLAC, m_model, Model, MDL_HLAC_ITEM);
11 #endif
12 /* crosshair */ ATTRIB(HLAC, w_crosshair, string, "gfx/crosshairhlac");
13 /* crosshair */ ATTRIB(HLAC, w_crosshair_size, float, 0.6);
14 /* wepimg    */ ATTRIB(HLAC, model2, string, "weaponhlac");
15 /* refname   */ ATTRIB(HLAC, netname, string, "hlac");
16 /* wepname   */ ATTRIB(HLAC, m_name, string, _("Heavy Laser Assault Cannon"));
17
18 #define X(BEGIN, P, END, class, prefix) \
19         BEGIN(class) \
20                 P(class, prefix, ammo, float, BOTH) \
21                 P(class, prefix, animtime, float, BOTH) \
22                 P(class, prefix, damage, float, BOTH) \
23                 P(class, prefix, edgedamage, float, BOTH) \
24                 P(class, prefix, force, float, BOTH) \
25                 P(class, prefix, lifetime, float, BOTH) \
26                 P(class, prefix, radius, float, BOTH) \
27                 P(class, prefix, refire, float, BOTH) \
28                 P(class, prefix, reload_ammo, float, NONE) \
29                 P(class, prefix, reload_time, float, NONE) \
30                 P(class, prefix, secondary, float, NONE) \
31                 P(class, prefix, shots, float, SEC) \
32                 P(class, prefix, speed, float, BOTH) \
33                 P(class, prefix, spread, float, SEC) \
34                 P(class, prefix, spread_add, float, PRI) \
35                 P(class, prefix, spread_crouchmod, float, BOTH) \
36                 P(class, prefix, spread_max, float, PRI) \
37                 P(class, prefix, spread_min, float, PRI) \
38                 P(class, prefix, switchdelay_drop, float, NONE) \
39                 P(class, prefix, switchdelay_raise, float, NONE) \
40                 P(class, prefix, weaponreplace, string,NONE) \
41                 P(class, prefix, weaponstartoverride, float, NONE) \
42                 P(class, prefix, weaponstart, float, NONE) \
43                 P(class, prefix, weaponthrowable, float, NONE) \
44         END()
45     W_PROPS(X, HLAC, hlac)
46 #undef X
47
48 ENDCLASS(HLAC)
49 REGISTER_WEAPON(HLAC, hlac, NEW(HLAC));
50
51
52 #endif
53 #ifdef IMPLEMENTATION
54 #ifdef SVQC
55 spawnfunc(weapon_hlac) { weapon_defaultspawnfunc(this, WEP_HLAC); }
56
57 void W_HLAC_Touch(entity this, entity toucher)
58 {
59         float isprimary;
60
61         PROJECTILE_TOUCH(this, toucher);
62
63         this.event_damage = func_null;
64
65         isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
66
67         RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius), NULL, NULL, WEP_CVAR_BOTH(hlac, isprimary, force), this.projectiledeathtype, toucher);
68
69         delete(this);
70 }
71
72 void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
73 {
74         entity missile;
75     float spread;
76
77         W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hlac, ammo));
78
79     spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * actor.misc_bulletcounter);
80     spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
81     if(actor.crouch)
82         spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
83
84         W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
85         Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
86         if(!autocvar_g_norecoil)
87         {
88                 actor.punchangle_x = random() - 0.5;
89                 actor.punchangle_y = random() - 0.5;
90         }
91
92         missile = new(hlacbolt);
93         missile.owner = missile.realowner = actor;
94         missile.bot_dodge = true;
95
96     missile.bot_dodgerating = WEP_CVAR_PRI(hlac, damage);
97
98         set_movetype(missile, MOVETYPE_FLY);
99         PROJECTILE_MAKETRIGGER(missile);
100
101         setorigin(missile, w_shotorg);
102         setsize(missile, '0 0 0', '0 0 0');
103
104         W_SetupProjVelocity_Basic(missile, WEP_CVAR_PRI(hlac, speed), spread);
105         //missile.angles = vectoangles(missile.velocity); // csqc
106
107         settouch(missile, W_HLAC_Touch);
108         setthink(missile, SUB_Remove);
109
110     missile.nextthink = time + WEP_CVAR_PRI(hlac, lifetime);
111
112         missile.flags = FL_PROJECTILE;
113         IL_PUSH(g_projectiles, missile);
114         missile.projectiledeathtype = WEP_HLAC.m_id;
115
116         CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
117
118         MUTATOR_CALLHOOK(EditProjectile, actor, missile);
119 }
120
121 void W_HLAC_Attack2(entity actor, .entity weaponentity)
122 {
123         entity missile;
124     float spread;
125
126     spread = WEP_CVAR_SEC(hlac, spread);
127
128
129     if(actor.crouch)
130         spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
131
132         W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
133         Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
134
135         missile = new(hlacbolt);
136         missile.owner = missile.realowner = actor;
137         missile.bot_dodge = true;
138
139     missile.bot_dodgerating = WEP_CVAR_SEC(hlac, damage);
140
141         set_movetype(missile, MOVETYPE_FLY);
142         PROJECTILE_MAKETRIGGER(missile);
143
144         setorigin(missile, w_shotorg);
145         setsize(missile, '0 0 0', '0 0 0');
146
147         W_SetupProjVelocity_Basic(missile, WEP_CVAR_SEC(hlac, speed), spread);
148         //missile.angles = vectoangles(missile.velocity); // csqc
149
150         settouch(missile, W_HLAC_Touch);
151         setthink(missile, SUB_Remove);
152
153     missile.nextthink = time + WEP_CVAR_SEC(hlac, lifetime);
154
155         missile.flags = FL_PROJECTILE;
156         IL_PUSH(g_projectiles, missile);
157         missile.missile_flags = MIF_SPLASH;
158         missile.projectiledeathtype = WEP_HLAC.m_id | HITTYPE_SECONDARY;
159
160         CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
161
162         MUTATOR_CALLHOOK(EditProjectile, actor, missile);
163 }
164
165 // weapon frames
166 void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int fire)
167 {
168         if(PS(actor).m_weapon != PS(actor).m_switchweapon) // abort immediately if switching
169         {
170                 w_ready(thiswep, actor, weaponentity, fire);
171                 return;
172         }
173
174         if(PHYS_INPUT_BUTTON_ATCK(actor))
175         {
176                 if(!thiswep.wr_checkammo1(thiswep, actor))
177                 if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
178                 {
179                         W_SwitchWeapon_Force(actor, w_getbestweapon(actor));
180                         w_ready(thiswep, actor, weaponentity, fire);
181                         return;
182                 }
183
184                 int slot = weaponslot(weaponentity);
185                 ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor(actor);
186                 W_HLAC_Attack(WEP_HLAC, actor, weaponentity);
187                 actor.misc_bulletcounter = actor.misc_bulletcounter + 1;
188         weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
189         }
190         else
191         {
192                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready);
193         }
194 }
195
196 void W_HLAC_Attack2_Frame(Weapon thiswep, entity actor, .entity weaponentity)
197 {
198     float i;
199
200         W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hlac, ammo));
201
202     for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i)
203         W_HLAC_Attack2(actor, weaponentity);
204
205         if(!autocvar_g_norecoil)
206         {
207                 actor.punchangle_x = random() - 0.5;
208                 actor.punchangle_y = random() - 0.5;
209         }
210 }
211
212 METHOD(HLAC, wr_aim, void(entity thiswep, entity actor))
213 {
214     PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), false);
215 }
216 METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
217 {
218     if(autocvar_g_balance_hlac_reload_ammo && actor.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
219         thiswep.wr_reload(thiswep, actor, weaponentity);
220     } else if(fire & 1)
221     {
222         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hlac, refire)))
223         {
224             actor.misc_bulletcounter = 0;
225             W_HLAC_Attack(thiswep, actor, weaponentity);
226             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
227         }
228     }
229
230     else if((fire & 2) && WEP_CVAR(hlac, secondary))
231     {
232         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hlac, refire)))
233         {
234             W_HLAC_Attack2_Frame(thiswep, actor, weaponentity);
235             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
236         }
237     }
238 }
239 METHOD(HLAC, wr_checkammo1, bool(entity thiswep, entity actor))
240 {
241     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(hlac, ammo);
242     ammo_amount += actor.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
243     return ammo_amount;
244 }
245 METHOD(HLAC, wr_checkammo2, bool(entity thiswep, entity actor))
246 {
247     float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(hlac, ammo);
248     ammo_amount += actor.(weapon_load[WEP_HLAC.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
249     return ammo_amount;
250 }
251 METHOD(HLAC, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
252 {
253     W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), SND_RELOAD);
254 }
255 METHOD(HLAC, wr_suicidemessage, Notification(entity thiswep))
256 {
257     return WEAPON_HLAC_SUICIDE;
258 }
259 METHOD(HLAC, wr_killmessage, Notification(entity thiswep))
260 {
261     return WEAPON_HLAC_MURDER;
262 }
263
264 #endif
265 #ifdef CSQC
266
267 METHOD(HLAC, wr_impacteffect, void(entity thiswep, entity actor))
268 {
269     vector org2;
270     org2 = w_org + w_backoff * 6;
271     pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
272     if(!w_issilent)
273         sound(actor, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM);
274 }
275
276 #endif
277 #endif