5 void W_Blaster_Touch(entity this, entity toucher)
7 PROJECTILE_TOUCH(this, toucher);
9 this.event_damage = func_null;
10 bool isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
12 RadiusDamageForSource(
14 (this.origin + (this.mins + this.maxs) * 0.5),
17 WEP_CVAR_BOTH(this.real_weapon, isprimary, damage),
18 WEP_CVAR_BOTH(this.real_weapon, isprimary, edgedamage),
19 WEP_CVAR_BOTH(this.real_weapon, isprimary, radius),
23 WEP_CVAR_BOTH(this.real_weapon, isprimary, force),
24 WEP_CVAR_BOTH(this.real_weapon, isprimary, force_zscale),
25 this.projectiledeathtype,
26 this.weaponentity_fld,
33 void W_Blaster_Think(entity this)
35 set_movetype(this, MOVETYPE_FLY);
36 setthink(this, SUB_Remove);
37 bool isprimary = !(this.projectiledeathtype & HITTYPE_SECONDARY);
38 this.nextthink = time + WEP_CVAR_BOTH(WEP_BLASTER, isprimary, lifetime);
39 CSQCProjectile(this, true, PROJECTILE_BLASTER, true);
42 void W_Blaster_Attack(
48 bool isprimary = !(atk_deathtype & HITTYPE_SECONDARY);
49 float atk_shotangle = WEP_CVAR_BOTH(WEP_BLASTER, isprimary, shotangle);
50 float atk_damage = WEP_CVAR_BOTH(WEP_BLASTER, isprimary, damage);
51 vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
53 W_SetupShot_Dir(actor, weaponentity, s_forward, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, atk_damage, atk_deathtype);
54 W_MuzzleFlash(WEP_BLASTER, actor, weaponentity, w_shotorg, w_shotdir);
56 entity missile = new(blasterbolt);
57 missile.real_weapon = real_wpn;
58 missile.owner = missile.realowner = actor;
59 missile.bot_dodge = true;
60 missile.bot_dodgerating = atk_damage;
61 PROJECTILE_MAKETRIGGER(missile);
63 setorigin(missile, w_shotorg);
64 setsize(missile, '0 0 0', '0 0 0');
66 float atk_speed = WEP_CVAR_BOTH(WEP_BLASTER, isprimary, speed);
67 float atk_spread = WEP_CVAR_BOTH(WEP_BLASTER, isprimary, spread);
68 W_SetupProjVelocity_Explicit(missile, w_shotdir, v_up, atk_speed, 0, 0, atk_spread, false);
70 missile.angles = vectoangles(missile.velocity);
72 //missile.glow_color = 250; // 244, 250
73 //missile.glow_size = 120;
75 settouch(missile, W_Blaster_Touch);
76 missile.flags = FL_PROJECTILE;
77 IL_PUSH(g_projectiles, missile);
78 IL_PUSH(g_bot_dodge, missile);
79 missile.missile_flags = MIF_SPLASH;
80 missile.projectiledeathtype = atk_deathtype;
81 missile.weaponentity_fld = weaponentity;
82 setthink(missile, W_Blaster_Think);
83 missile.nextthink = time + WEP_CVAR_BOTH(WEP_BLASTER, isprimary, delay);
85 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
87 if (time >= missile.nextthink)
89 getthink(missile)(missile);
93 METHOD(Blaster, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
95 if(WEP_CVAR(WEP_BLASTER, secondary))
97 if((random() * (WEP_CVAR_PRI(WEP_BLASTER, damage) + WEP_CVAR_SEC(WEP_BLASTER, damage))) > WEP_CVAR_PRI(WEP_BLASTER, damage))
98 { PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, WEP_CVAR_SEC(WEP_BLASTER, speed), 0, WEP_CVAR_SEC(WEP_BLASTER, lifetime), false, true); }
100 { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(WEP_BLASTER, speed), 0, WEP_CVAR_PRI(WEP_BLASTER, lifetime), false, true); }
103 { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(WEP_BLASTER, speed), 0, WEP_CVAR_PRI(WEP_BLASTER, lifetime), false, true); }
106 METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponentity, int fire))
110 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(WEP_BLASTER, refire)))
112 W_Blaster_Attack(actor, thiswep, weaponentity, WEP_BLASTER.m_id);
113 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(WEP_BLASTER, animtime), w_ready);
118 switch(WEP_CVAR(WEP_BLASTER, secondary))
120 case 0: // switch to last used weapon
122 if(actor.(weaponentity).m_switchweapon == WEP_BLASTER) // don't do this if already switching
123 W_LastWeapon(actor, weaponentity);
127 case 1: // normal projectile secondary
129 if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(WEP_BLASTER, refire)))
131 W_Blaster_Attack(actor, thiswep, weaponentity, WEP_BLASTER.m_id | HITTYPE_SECONDARY);
132 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(WEP_BLASTER, animtime), w_ready);
141 METHOD(Blaster, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
143 return true; // infinite ammo
146 METHOD(Blaster, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
148 return true; // blaster has infinite ammo
151 METHOD(Blaster, wr_suicidemessage, Notification(entity thiswep))
153 return WEAPON_BLASTER_SUICIDE;
156 METHOD(Blaster, wr_killmessage, Notification(entity thiswep))
158 return WEAPON_BLASTER_MURDER;
161 METHOD(OffhandBlaster, offhand_think, void(OffhandBlaster this, entity actor, bool key_pressed))
163 if (!key_pressed || (time < actor.jump_interval))
167 actor.jump_interval = time + WEP_CVAR_SEC(WEP_BLASTER, refire) * W_WeaponRateFactor(actor);
168 .entity weaponentity = weaponentities[1];
169 makevectors(actor.v_angle);
170 W_Blaster_Attack(actor, this, weaponentity, WEP_BLASTER.m_id | HITTYPE_SECONDARY);
176 METHOD(Blaster, wr_impacteffect, void(entity thiswep, entity actor))
178 vector org2 = w_org + w_backoff * 2;
179 pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
180 if(!w_issilent) { sound(actor, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }