]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/weapons/weapon/hlac.qc
Remove legacy Quake bbox expansion: projectiles
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / weapons / weapon / hlac.qc
1 #include "hlac.qh"
2
3 #ifdef SVQC
4
5 void W_HLAC_Touch(entity this, entity toucher)
6 {
7         float isprimary;
8
9         PROJECTILE_TOUCH(this, toucher);
10
11         this.event_damage = func_null;
12
13         isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
14
15         RadiusDamage(this, this.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius),
16                                                 NULL, NULL, WEP_CVAR_BOTH(hlac, isprimary, force), this.projectiledeathtype, this.weaponentity_fld, toucher);
17
18         delete(this);
19 }
20
21 void W_HLAC_Attack(Weapon thiswep, entity actor, .entity weaponentity)
22 {
23         entity missile;
24
25         W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(hlac, ammo), weaponentity);
26
27         float spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * actor.(weaponentity).misc_bulletcounter);
28         spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
29         if(IS_DUCKED(actor))
30                 spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
31
32         W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage), thiswep.m_id);
33         W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
34         if(!autocvar_g_norecoil)
35         {
36                 actor.punchangle_x = random() - 0.5;
37                 actor.punchangle_y = random() - 0.5;
38         }
39
40         missile = new(hlacbolt);
41         missile.owner = missile.realowner = actor;
42         missile.bot_dodge = true;
43
44         missile.bot_dodgerating = WEP_CVAR_PRI(hlac, damage);
45
46         set_movetype(missile, MOVETYPE_FLY);
47         PROJECTILE_MAKETRIGGER(missile);
48         missile.clipgroup = CLIPGROUP_UNHITTABLEPROJ;
49
50         setorigin(missile, w_shotorg);
51         setsize(missile, UNHITTABLEPROJ_MINS, UNHITTABLEPROJ_MAXS);
52
53         W_SetupProjVelocity_Basic(missile, WEP_CVAR_PRI(hlac, speed), spread);
54         //missile.angles = vectoangles(missile.velocity); // csqc
55
56         settouch(missile, W_HLAC_Touch);
57         setthink(missile, SUB_Remove);
58
59         missile.nextthink = time + WEP_CVAR_PRI(hlac, lifetime);
60
61         missile.flags = FL_PROJECTILE;
62         IL_PUSH(g_projectiles, missile);
63         IL_PUSH(g_bot_dodge, missile);
64         missile.projectiledeathtype = thiswep.m_id;
65         missile.weaponentity_fld = weaponentity;
66
67         CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
68
69         MUTATOR_CALLHOOK(EditProjectile, actor, missile);
70 }
71
72 void W_HLAC_Attack2(Weapon thiswep, entity actor, .entity weaponentity)
73 {
74         entity missile;
75         float spread = WEP_CVAR_SEC(hlac, spread);
76
77         if(IS_DUCKED(actor))
78                 spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
79
80         W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage) * WEP_CVAR_SEC(hlac, shots), thiswep.m_id | HITTYPE_SECONDARY);
81         W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
82         W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(hlac, ammo), weaponentity);
83
84         for(int j = WEP_CVAR_SEC(hlac, shots); j > 0; --j)
85         {
86                 missile = new(hlacbolt);
87                 missile.owner = missile.realowner = actor;
88                 missile.bot_dodge = true;
89
90                 missile.bot_dodgerating = WEP_CVAR_SEC(hlac, damage);
91
92                 set_movetype(missile, MOVETYPE_FLY);
93                 PROJECTILE_MAKETRIGGER(missile);
94                 missile.clipgroup = CLIPGROUP_UNHITTABLEPROJ;
95
96                 setorigin(missile, w_shotorg);
97                 setsize(missile, UNHITTABLEPROJ_MINS, UNHITTABLEPROJ_MAXS);
98
99                 W_SetupProjVelocity_Basic(missile, WEP_CVAR_SEC(hlac, speed), spread);
100                 //missile.angles = vectoangles(missile.velocity); // csqc
101
102                 settouch(missile, W_HLAC_Touch);
103                 setthink(missile, SUB_Remove);
104
105                 missile.nextthink = time + WEP_CVAR_SEC(hlac, lifetime);
106
107                 missile.flags = FL_PROJECTILE;
108                 IL_PUSH(g_projectiles, missile);
109                 IL_PUSH(g_bot_dodge, missile);
110                 missile.missile_flags = MIF_SPLASH;
111                 missile.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
112                 missile.weaponentity_fld = weaponentity;
113
114                 CSQCProjectile(missile, true, PROJECTILE_HLAC, true);
115
116                 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
117         }
118
119         if(!autocvar_g_norecoil)
120         {
121                 actor.punchangle_x = random() - 0.5;
122                 actor.punchangle_y = random() - 0.5;
123         }
124 }
125
126 // weapon frames
127 void W_HLAC_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int fire)
128 {
129         if(actor.(weaponentity).m_weapon != actor.(weaponentity).m_switchweapon) // abort immediately if switching
130         {
131                 w_ready(thiswep, actor, weaponentity, fire);
132                 return;
133         }
134
135         if(PHYS_INPUT_BUTTON_ATCK(actor))
136         {
137                 if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
138                 if(!(actor.items & IT_UNLIMITED_AMMO))
139                 {
140                         W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
141                         w_ready(thiswep, actor, weaponentity, fire);
142                         return;
143                 }
144
145                 ATTACK_FINISHED(actor, weaponentity) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor(actor);
146                 W_HLAC_Attack(thiswep, actor, weaponentity);
147                 actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
148                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
149         }
150         else
151         {
152                 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready);
153         }
154 }
155
156 METHOD(HLAC, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
157 {
158     PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), false, true);
159 }
160 METHOD(HLAC, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
161 {
162     if(autocvar_g_balance_hlac_reload_ammo && actor.(weaponentity).clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) { // forced reload
163         thiswep.wr_reload(thiswep, actor, weaponentity);
164     } else if(fire & 1)
165     {
166         if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(hlac, refire)))
167         {
168             actor.(weaponentity).misc_bulletcounter = 0;
169             W_HLAC_Attack(thiswep, actor, weaponentity);
170             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
171         }
172     }
173
174     else if((fire & 2) && WEP_CVAR(hlac, secondary))
175     {
176         if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(hlac, refire)))
177         {
178             W_HLAC_Attack2(thiswep, actor, weaponentity);
179             weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
180         }
181     }
182 }
183 METHOD(HLAC, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
184 {
185     float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_PRI(hlac, ammo);
186     ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_PRI(hlac, ammo);
187     return ammo_amount;
188 }
189 METHOD(HLAC, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
190 {
191     float ammo_amount = GetResource(actor, thiswep.ammo_type) >= WEP_CVAR_SEC(hlac, ammo);
192     ammo_amount += actor.(weaponentity).(weapon_load[thiswep.m_id]) >= WEP_CVAR_SEC(hlac, ammo);
193     return ammo_amount;
194 }
195 METHOD(HLAC, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
196 {
197     W_Reload(actor, weaponentity, min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), SND_RELOAD);
198 }
199 METHOD(HLAC, wr_suicidemessage, Notification(entity thiswep))
200 {
201     return WEAPON_HLAC_SUICIDE;
202 }
203 METHOD(HLAC, wr_killmessage, Notification(entity thiswep))
204 {
205     return WEAPON_HLAC_MURDER;
206 }
207
208 #endif
209 #ifdef CSQC
210
211 METHOD(HLAC, wr_impacteffect, void(entity thiswep, entity actor))
212 {
213     vector org2 = w_org + w_backoff * 2;
214     pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
215     if(!w_issilent)
216         sound(actor, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM);
217 }
218
219 #endif