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");
10 /* model */ ATTRIB(Blaster, m_model, Model, MDL_BLASTER_ITEM);
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, m_name, string, _("Blaster"));
18 #define X(BEGIN, P, END, class, prefix) \
20 P(class, prefix, animtime, float, BOTH) \
21 P(class, prefix, damage, float, BOTH) \
22 P(class, prefix, delay, float, BOTH) \
23 P(class, prefix, edgedamage, float, BOTH) \
24 P(class, prefix, force, float, BOTH) \
25 P(class, prefix, force_zscale, 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, secondary, float, NONE) \
30 P(class, prefix, shotangle, float, BOTH) \
31 P(class, prefix, speed, float, BOTH) \
32 P(class, prefix, spread, float, BOTH) \
33 P(class, prefix, switchdelay_drop, float, NONE) \
34 P(class, prefix, switchdelay_raise, float, NONE) \
35 P(class, prefix, weaponreplace, string, NONE) \
36 P(class, prefix, weaponstartoverride, float, NONE) \
37 P(class, prefix, weaponstart, float, NONE) \
38 P(class, prefix, weaponthrowable, float, NONE) \
40 W_PROPS(X, Blaster, blaster)
44 REGISTER_WEAPON(BLASTER, blaster, NEW(Blaster));
47 .float blaster_damage;
48 .float blaster_edgedamage;
49 .float blaster_radius;
51 .float blaster_lifetime;
56 spawnfunc(weapon_blaster) { weapon_defaultspawnfunc(this, WEP_BLASTER); }
57 spawnfunc(weapon_laser) { spawnfunc_weapon_blaster(this); }
59 void W_Blaster_Touch(entity this, entity toucher)
61 PROJECTILE_TOUCH(this, toucher);
63 this.event_damage = func_null;
69 this.blaster_edgedamage,
74 this.projectiledeathtype,
81 void W_Blaster_Think(entity this)
83 set_movetype(this, MOVETYPE_FLY);
84 setthink(this, SUB_Remove);
85 this.nextthink = time + this.blaster_lifetime;
86 CSQCProjectile(this, true, PROJECTILE_BLASTER, true);
89 void W_Blaster_Attack(
102 vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
104 W_SetupShot_Dir(actor, s_forward, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_B, atk_damage);
105 Send_Effect(EFFECT_BLASTER_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
107 entity missile = new(blasterbolt);
108 missile.owner = missile.realowner = actor;
109 missile.bot_dodge = true;
110 missile.bot_dodgerating = atk_damage;
111 PROJECTILE_MAKETRIGGER(missile);
113 missile.blaster_damage = atk_damage;
114 missile.blaster_edgedamage = atk_edgedamage;
115 missile.blaster_radius = atk_radius;
116 missile.blaster_force = atk_force;
117 missile.blaster_lifetime = atk_lifetime;
119 setorigin(missile, w_shotorg);
120 setsize(missile, '0 0 0', '0 0 0');
122 W_SetupProjVelocity_Explicit(
133 missile.angles = vectoangles(missile.velocity);
135 //missile.glow_color = 250; // 244, 250
136 //missile.glow_size = 120;
138 settouch(missile, W_Blaster_Touch);
139 missile.flags = FL_PROJECTILE;
140 missile.missile_flags = MIF_SPLASH;
141 missile.projectiledeathtype = atk_deathtype;
142 setthink(missile, W_Blaster_Think);
143 missile.nextthink = time + atk_delay;
145 MUTATOR_CALLHOOK(EditProjectile, actor, missile);
147 if (time >= missile.nextthink)
149 getthink(missile)(missile);
153 METHOD(Blaster, wr_aim, void(entity thiswep, entity actor))
155 if(WEP_CVAR(blaster, secondary))
157 if((random() * (WEP_CVAR_PRI(blaster, damage) + WEP_CVAR_SEC(blaster, damage))) > WEP_CVAR_PRI(blaster, damage))
158 { PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, WEP_CVAR_SEC(blaster, speed), 0, WEP_CVAR_SEC(blaster, lifetime), false); }
160 { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
163 { PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), false); }
166 METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponentity, int fire))
170 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(blaster, refire)))
175 WEP_CVAR_PRI(blaster, shotangle),
176 WEP_CVAR_PRI(blaster, damage),
177 WEP_CVAR_PRI(blaster, edgedamage),
178 WEP_CVAR_PRI(blaster, radius),
179 WEP_CVAR_PRI(blaster, force),
180 WEP_CVAR_PRI(blaster, speed),
181 WEP_CVAR_PRI(blaster, spread),
182 WEP_CVAR_PRI(blaster, delay),
183 WEP_CVAR_PRI(blaster, lifetime)
185 weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
190 switch(WEP_CVAR(blaster, secondary))
192 case 0: // switch to last used weapon
194 if(PS(actor).m_switchweapon == WEP_BLASTER) // don't do this if already switching
199 case 1: // normal projectile secondary
201 if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(blaster, refire)))
205 WEP_BLASTER.m_id | HITTYPE_SECONDARY,
206 WEP_CVAR_SEC(blaster, shotangle),
207 WEP_CVAR_SEC(blaster, damage),
208 WEP_CVAR_SEC(blaster, edgedamage),
209 WEP_CVAR_SEC(blaster, radius),
210 WEP_CVAR_SEC(blaster, force),
211 WEP_CVAR_SEC(blaster, speed),
212 WEP_CVAR_SEC(blaster, spread),
213 WEP_CVAR_SEC(blaster, delay),
214 WEP_CVAR_SEC(blaster, lifetime)
216 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
225 METHOD(Blaster, wr_setup, void(entity thiswep, entity actor))
227 actor.ammo_field = ammo_none;
230 METHOD(Blaster, wr_checkammo1, bool(entity thiswep, entity actor))
232 return true; // infinite ammo
235 METHOD(Blaster, wr_checkammo2, bool(entity thiswep, entity actor))
237 return true; // blaster has infinite ammo
240 METHOD(Blaster, wr_suicidemessage, Notification(entity thiswep))
242 return WEAPON_BLASTER_SUICIDE;
245 METHOD(Blaster, wr_killmessage, Notification(entity thiswep))
247 return WEAPON_BLASTER_MURDER;
253 METHOD(Blaster, wr_impacteffect, void(entity thiswep, entity actor))
256 org2 = w_org + w_backoff * 6;
257 pointparticles(EFFECT_BLASTER_IMPACT, org2, w_backoff * 1000, 1);
258 if(!w_issilent) { sound(actor, CH_SHOTS, SND_LASERIMPACT, VOL_BASE, ATTN_NORM); }