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