Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
electro.qc File Reference
Include dependency graph for electro.qc:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void electro_orb_draw (entity this)
bool electro_orb_send (entity this, entity to, int sf)
void electro_orb_setup (entity e)
 NET_HANDLE (Electro_Orb, bool isNew)
void W_Electro_Attack_Bolt (Weapon thiswep, entity actor,.entity weaponentity)
void W_Electro_Attack_Orb (Weapon thiswep, entity actor,.entity weaponentity)
void W_Electro_Bolt_Think (entity this)
void W_Electro_CheckAttack (Weapon thiswep, entity actor,.entity weaponentity, int fire)
void W_Electro_Explode (entity this, entity directhitentity)
void W_Electro_Explode_use (entity this, entity actor, entity trigger)
void W_Electro_ExplodeCombo (entity this)
void W_Electro_ExplodeComboThink (entity this)
void W_Electro_Orb_Damage (entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
void W_Electro_Orb_ExplodeOverTime (entity this)
void W_Electro_Orb_Follow_Think (entity this)
void W_Electro_Orb_Stick (entity this, entity to)
void W_Electro_Orb_Touch (entity this, entity toucher)
void W_Electro_TouchExplode (entity this, entity toucher)
void W_Electro_TriggerCombo (vector org, float rad, entity own)

Variables

bool bot_secondary_electromooth
const float ELECTRO_COMBO_OVERTIME_DELAY = 0.0625
float ltime

Function Documentation

◆ electro_orb_draw()

void electro_orb_draw ( entity this)

Definition at line 8 of file electro.qc.

9{
10 float dt = time - this.move_time;
11 this.move_time = time;
12 if (dt <= 0)
13 return;
14
15 float myscale = bound(0, (this.ltime - time) * 4, 1);
16 this.scale = (WEP_CVAR(WEP_ELECTRO, combo_radius) * 0.05) * myscale;
17 this.angles += dt * this.avelocity;
18}
float ltime
Definition net.qh:10
vector avelocity
float time
ent angles
Definition ent_cs.qc:146
float bound(float min, float value, float max)
float move_time
Definition movetypes.qh:81
float scale
Definition projectile.qc:14
#define WEP_CVAR(wep, name)
Definition all.qh:337

References angles, avelocity, bound(), entity(), ltime, move_time, scale, time, and WEP_CVAR.

Referenced by electro_orb_setup().

◆ electro_orb_send()

bool electro_orb_send ( entity this,
entity to,
int sf )

Definition at line 56 of file electro.qc.

57{
58 int channel = MSG_ENTITY;
59 WriteHeader(channel, Electro_Orb);
60 WriteVector(channel, this.origin);
61 WriteByte(channel, etof(this.realowner));
62 // round time delta to a 1/10th of a second
63 WriteByte(channel, (this.ltime - time) * 10 + 0.5);
64 return true;
65}
vector origin
WriteByte(chan, ent.angles.y/DEC_FACTOR)
const int MSG_ENTITY
Definition net.qh:156
#define WriteHeader(to, id)
Definition net.qh:265
#define etof(e)
Definition misc.qh:25
entity realowner

References entity(), etof, ltime, MSG_ENTITY, origin, realowner, time, WriteByte(), and WriteHeader.

Referenced by W_Electro_Orb_ExplodeOverTime().

◆ electro_orb_setup()

void electro_orb_setup ( entity e)

Definition at line 20 of file electro.qc.

21{
22 setmodel(e, MDL_PROJECTILE_ELECTRO);
23 setsize(e, '-4 -4 -4', '4 4 4');
24
25 setorigin(e, e.origin);
26
27 e.draw = electro_orb_draw;
29 SetResourceExplicit(e, RES_HEALTH, 255);
31 e.solid = SOLID_NOT;
32 e.avelocity = '7 0 11';
33 e.drawmask = MASK_NORMAL;
34 e.alpha = 0.7;
35}
IntrusiveList g_drawables
Definition main.qh:91
#define setmodel(this, m)
Definition model.qh:26
const float MASK_NORMAL
const float SOLID_NOT
void electro_orb_draw(entity this)
Definition electro.qc:8
SetResourceExplicit(ent, RES_ARMOR, ReadByte() *DEC_FACTOR)) ENTCS_PROP(NAME
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_NONE
Definition movetypes.qh:133

References electro_orb_draw(), entity(), g_drawables, IL_PUSH(), MASK_NORMAL, MOVETYPE_NONE, set_movetype(), setmodel, SetResourceExplicit(), and SOLID_NOT.

Referenced by NET_HANDLE().

◆ NET_HANDLE()

NET_HANDLE ( Electro_Orb ,
bool isNew )

Definition at line 41 of file electro.qc.

42{
43 Net_Accept(Electro_Orb);
44 this.origin = ReadVector();
45 int myowner = ReadByte();
46 setorigin(this, this.origin);
47 this.colormap = entcs_GetClientColors(myowner - 1);
48 this.ltime = time + ReadByte() / 10.0;
49 // this.ltime = time + this.orb_lifetime;
51 return true;
52}
float colormap
void electro_orb_setup(entity e)
Definition electro.qc:20
int entcs_GetClientColors(int i)
Definition ent_cs.qh:111
#define ReadVector()
Definition net.qh:349
int ReadByte()

References colormap, electro_orb_setup(), entcs_GetClientColors(), ltime, origin, ReadByte(), ReadVector, and time.

◆ W_Electro_Attack_Bolt()

void W_Electro_Attack_Bolt ( Weapon thiswep,
entity actor,
.entity weaponentity )

Definition at line 319 of file electro.qc.

320{
321 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(WEP_ELECTRO, ammo), weaponentity);
322
324 actor,
325 weaponentity,
326 '0 0 -3',
327 '0 0 -3',
328 false,
329 2,
330 SND_ELECTRO_FIRE,
332 WEP_CVAR_PRI(WEP_ELECTRO, damage),
333 thiswep.m_id
334 );
335
336 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
337
338 entity proj = new(electro_bolt);
339 proj.owner = proj.realowner = actor;
340 proj.bot_dodge = true;
341 proj.bot_dodgerating = WEP_CVAR_PRI(WEP_ELECTRO, damage);
342 proj.use = W_Electro_Explode_use;
344 proj.nextthink = time;
345 proj.ltime = time + WEP_CVAR_PRI(WEP_ELECTRO, lifetime);
347 proj.projectiledeathtype = thiswep.m_id;
348 proj.weaponentity_fld = weaponentity;
349 setorigin(proj, w_shotorg);
350
351 // if (IS_CSQC)
353 W_SetupProjVelocity_PRI(proj, WEP_ELECTRO);
354 proj.angles = vectoangles(proj.velocity);
356 setsize(proj, '0 0 -3', '0 0 -3');
357 proj.flags = FL_PROJECTILE;
358 IL_PUSH(g_projectiles, proj);
359 IL_PUSH(g_bot_dodge, proj);
360 proj.missile_flags = MIF_SPLASH;
361
362 CSQCProjectile(proj, true, PROJECTILE_ELECTRO_BEAM, true);
363
364 MUTATOR_CALLHOOK(EditProjectile, actor, proj);
365 // proj.com_phys_pos = proj.origin;
366 // proj.com_phys_vel = proj.velocity;
367}
IntrusiveList g_bot_dodge
Definition api.qh:150
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
int m_id
Definition weapon.qh:43
float lifetime
Definition powerups.qc:23
const int FL_PROJECTILE
Definition constants.qh:76
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
void W_Electro_TouchExplode(entity this, entity toucher)
Definition electro.qc:247
void W_Electro_Explode_use(entity this, entity actor, entity trigger)
Definition electro.qc:242
void W_Electro_Bolt_Think(entity this)
Definition electro.qc:256
vector vectoangles(vector v)
const int MOVETYPE_FLY
Definition movetypes.qh:138
const int PROJECTILE_ELECTRO_BEAM
Definition projectiles.qh:7
#define setthink(e, f)
#define settouch(e, f)
Definition self.qh:77
const int MIF_SPLASH
Definition common.qh:46
IntrusiveList g_projectiles
Definition common.qh:58
#define PROJECTILE_MAKETRIGGER(e)
Definition common.qh:34
const int CH_WEAPON_A
Definition sound.qh:7
float ammo
Definition sv_turrets.qh:43
vector w_shotdir
Definition tracing.qh:20
#define W_SetupShot_ProjectileSize(ent, wepent, mi, ma, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:30
#define W_SetupProjVelocity_PRI(ent, wep)
Definition tracing.qh:67
vector w_shotorg
Definition tracing.qh:19
void W_MuzzleFlash(Weapon thiswep, entity actor,.entity weaponentity, vector shotorg, vector shotdir)
Definition all.qc:715
#define WEP_CVAR_PRI(wep, name)
Definition all.qh:338
void W_DecreaseAmmo(Weapon wep, entity actor, float ammo_use,.entity weaponentity)

References ammo, CH_WEAPON_A, CSQCProjectile(), entity(), FL_PROJECTILE, g_bot_dodge, g_projectiles, IL_PUSH(), lifetime, Weapon::m_id, MIF_SPLASH, MOVETYPE_FLY, MUTATOR_CALLHOOK, PROJECTILE_ELECTRO_BEAM, PROJECTILE_MAKETRIGGER, set_movetype(), setthink, settouch, time, vectoangles(), W_DecreaseAmmo(), W_Electro_Bolt_Think(), W_Electro_Explode_use(), W_Electro_TouchExplode(), W_MuzzleFlash(), W_SetupProjVelocity_PRI, W_SetupShot_ProjectileSize, w_shotdir, w_shotorg, and WEP_CVAR_PRI.

◆ W_Electro_Attack_Orb()

void W_Electro_Attack_Orb ( Weapon thiswep,
entity actor,
.entity weaponentity )

Definition at line 518 of file electro.qc.

519{
520 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(WEP_ELECTRO, ammo), weaponentity);
521
523 actor,
524 weaponentity,
525 '-4 -4 -4',
526 '4 4 4',
527 false,
528 2,
529 SND_ELECTRO_FIRE2,
531 WEP_CVAR_SEC(WEP_ELECTRO, damage),
532 thiswep.m_id | HITTYPE_SECONDARY
533 );
534
535 w_shotdir = v_forward; // no TrueAim for grenades please
536
537 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
538
539 entity proj = new(electro_orb);
540 proj.owner = proj.realowner = actor;
541 proj.use = W_Electro_Explode_use;
543 proj.bot_dodge = true;
544 proj.bot_dodgerating = WEP_CVAR_SEC(WEP_ELECTRO, damage);
545 proj.nextthink = time + WEP_CVAR_SEC(WEP_ELECTRO, lifetime);
546 proj.death_time = time + WEP_CVAR_SEC(WEP_ELECTRO, lifetime);
548 proj.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
549 proj.weaponentity_fld = weaponentity;
550 setorigin(proj, w_shotorg);
551
552 //proj.glow_size = 50;
553 //proj.glow_color = 45;
555 W_SetupProjVelocity_UP_SEC(proj, WEP_ELECTRO);
557 setsize(proj, '-4 -4 -4', '4 4 4');
558 proj.takedamage = DAMAGE_YES;
559 proj.damageforcescale = WEP_CVAR_SEC(WEP_ELECTRO, damageforcescale);
560 SetResourceExplicit(proj, RES_HEALTH, WEP_CVAR_SEC(WEP_ELECTRO, health));
561 proj.event_damage = W_Electro_Orb_Damage;
562 proj.flags = FL_PROJECTILE;
563 IL_PUSH(g_projectiles, proj);
564 IL_PUSH(g_bot_dodge, proj);
565 proj.damagedbycontents = (WEP_CVAR_SEC(WEP_ELECTRO, damagedbycontents));
566 if (proj.damagedbycontents)
568
569 proj.bouncefactor = WEP_CVAR_SEC(WEP_ELECTRO, bouncefactor);
570 proj.bouncestop = WEP_CVAR_SEC(WEP_ELECTRO, bouncestop);
571 proj.missile_flags = MIF_SPLASH | MIF_ARC;
572
573 if (WEP_CVAR_SEC(WEP_ELECTRO, limit) > 0)
574 {
579 }
580
581 CSQCProjectile(proj, true, PROJECTILE_ELECTRO, false); // no culling, it has sound
582
583 MUTATOR_CALLHOOK(EditProjectile, actor, proj);
584}
vector v_forward
float damagedbycontents
Definition damage.qh:45
IntrusiveList g_damagedbycontents
Definition damage.qh:143
float damageforcescale
const int HITTYPE_SECONDARY
Definition all.qh:31
void W_Electro_Orb_Touch(entity this, entity toucher)
Definition electro.qc:461
void W_Electro_Orb_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition electro.qc:482
IntrusiveList LimitedElectroBallRubbleList
Definition electro.qh:100
#define IL_NEW()
float bouncefactor
Definition movetypes.qh:45
float bouncestop
Definition movetypes.qh:44
const int MOVETYPE_BOUNCE
Definition movetypes.qh:143
const int PROJECTILE_ELECTRO
Definition projectiles.qh:3
float health
Legacy fields for the resources. To be removed.
Definition resources.qh:9
void LimitedChildrenRubble(IntrusiveList list, string cname, int limit, void(entity) deleteproc, entity parent)
Definition rubble.qc:5
entity ListNewChildRubble(IntrusiveList list, entity child)
Definition rubble.qc:46
void adaptor_think2use_hittype_splash(entity this)
Definition common.qc:106
const int MIF_ARC
Definition common.qh:47
const int DAMAGE_YES
Definition subs.qh:80
#define W_SetupProjVelocity_UP_SEC(ent, wep)
Definition tracing.qh:56
#define WEP_CVAR_SEC(wep, name)
Definition all.qh:339

References adaptor_think2use_hittype_splash(), ammo, bouncefactor, bouncestop, CH_WEAPON_A, CSQCProjectile(), DAMAGE_YES, damagedbycontents, damageforcescale, entity(), FL_PROJECTILE, g_bot_dodge, g_damagedbycontents, g_projectiles, health, HITTYPE_SECONDARY, IL_NEW, IL_PUSH(), lifetime, LimitedChildrenRubble(), LimitedElectroBallRubbleList, ListNewChildRubble(), Weapon::m_id, MIF_ARC, MIF_SPLASH, MOVETYPE_BOUNCE, MUTATOR_CALLHOOK, PROJECTILE_ELECTRO, PROJECTILE_MAKETRIGGER, set_movetype(), SetResourceExplicit(), setthink, settouch, time, v_forward, W_DecreaseAmmo(), W_Electro_Explode_use(), W_Electro_Orb_Damage(), W_Electro_Orb_Touch(), W_MuzzleFlash(), W_SetupProjVelocity_UP_SEC, W_SetupShot_ProjectileSize, w_shotdir, w_shotorg, and WEP_CVAR_SEC.

Referenced by W_Electro_CheckAttack().

◆ W_Electro_Bolt_Think()

void W_Electro_Bolt_Think ( entity this)

Definition at line 256 of file electro.qc.

257{
258 // sys_phys_update_single(this);
259 if (time >= this.ltime)
260 {
261 this.use(this, NULL, NULL);
262 return;
263 }
264
265 if (WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_radius))
266 {
267 int found = 0;
268 entity e = WarpZone_FindRadius(this.origin, WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_radius), true);
269
270 // loop through nearby orbs and trigger them
271 for (; e; e = e.chain)
272 if (e.classname == "electro_orb")
273 {
274 // check if the ball we are exploding is not owned by an
275 // independent player which is not the player who shot the ball
276 if (IS_INDEPENDENT_PLAYER(e.realowner) && this.realowner != e.realowner)
277 continue;
278
279 bool explode;
280 if (this.owner == e.owner)
281 explode = WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_own);
282 else if (SAME_TEAM(this.owner, e.owner))
283 explode = WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_teammate);
284 else
285 explode = WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_enemy);
286
287 if (explode)
288 {
289 // change owner to whoever caused the combo explosion
290 e.realowner = this.realowner;
291 e.takedamage = DAMAGE_NO;
292 e.classname = "electro_orb_chain";
293
294 // Only first orb explosion uses midaircombo_speed, others use the normal combo_speed.
295 // This allows to avoid the delay on the first explosion which looks better
296 // (the bolt and orb should explode together because they interacted together)
297 // while keeping the chaining delay.
299 float delay = (WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_speed))
300 ? vlen(e.WarpZone_findradius_dist) / WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_speed)
301 : 0;
302 e.nextthink = time + delay;
303
304 ++found;
305 }
306 }
307
308 // if we triggered an orb, should we explode? if not, lets try again next time
309 if (found && WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_explode))
310 this.use(this, NULL, NULL);
311 else
312 this.nextthink = min(time + WEP_CVAR_PRI(WEP_ELECTRO, midaircombo_interval), this.ltime);
313 }
314 else
315 this.nextthink = this.ltime;
316 // this.nextthink = time;
317}
float delay
Definition items.qc:17
entity owner
Definition main.qh:87
float nextthink
#define use
void W_Electro_ExplodeCombo(entity this)
Definition electro.qc:168
entity WarpZone_FindRadius(vector org, float rad, bool needlineofsight)
Definition common.qc:651
float vlen(vector v)
float min(float f,...)
#define NULL
Definition post.qh:14
#define IS_INDEPENDENT_PLAYER(e)
Definition client.qh:312
const int DAMAGE_NO
Definition subs.qh:79
#define SAME_TEAM(a, b)
Definition teams.qh:241

References DAMAGE_NO, delay, entity(), IS_INDEPENDENT_PLAYER, ltime, min(), nextthink, NULL, origin, owner, realowner, SAME_TEAM, setthink, time, use, vlen(), W_Electro_ExplodeCombo(), WarpZone_FindRadius(), and WEP_CVAR_PRI.

Referenced by W_Electro_Attack_Bolt().

◆ W_Electro_CheckAttack()

void W_Electro_CheckAttack ( Weapon thiswep,
entity actor,
.entity weaponentity,
int fire )

Definition at line 586 of file electro.qc.

587{
588 if (actor.(weaponentity).electro_count > 1
590 && weapon_prepareattack(thiswep, actor, weaponentity, true, -1))
591 {
592 W_Electro_Attack_Orb(thiswep, actor, weaponentity);
593 --actor.(weaponentity).electro_count;
594 actor.(weaponentity).electro_secondarytime = time;
595 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(WEP_ELECTRO, animtime), W_Electro_CheckAttack);
596 return;
597 }
598 w_ready(thiswep, actor, weaponentity, fire);
599}
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition player.qh:154
void W_Electro_Attack_Orb(Weapon thiswep, entity actor,.entity weaponentity)
Definition electro.qc:518
void W_Electro_CheckAttack(Weapon thiswep, entity actor,.entity weaponentity, int fire)
Definition electro.qc:586
float electro_count
Definition electro.qh:102
float electro_secondarytime
Definition electro.qh:103
void weapon_thinkf(entity actor,.entity weaponentity, WFRAME fr, float t, void(Weapon thiswep, entity actor,.entity weaponentity, int fire) func)
bool weapon_prepareattack(Weapon thiswep, entity actor,.entity weaponentity, bool secondary, float attacktime)
void w_ready(Weapon thiswep, entity actor,.entity weaponentity, int fire)

References electro_count, electro_secondarytime, entity(), PHYS_INPUT_BUTTON_ATCK2, time, W_Electro_Attack_Orb(), W_Electro_CheckAttack(), w_ready(), weapon_prepareattack(), weapon_thinkf(), and WEP_CVAR_SEC.

Referenced by W_Electro_CheckAttack().

◆ W_Electro_Explode()

void W_Electro_Explode ( entity this,
entity directhitentity )

Definition at line 199 of file electro.qc.

200{
201 if (directhitentity.takedamage == DAMAGE_AIM
202 && IS_PLAYER(directhitentity) && DIFF_TEAM(this.realowner, directhitentity) && !IS_DEAD(directhitentity)
203 && IsFlying(directhitentity))
204 Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_ELECTROBITCH);
205
206 this.event_damage = func_null;
207 this.takedamage = DAMAGE_NO;
208 if (!this.velocity)
209 this.velocity = this.movedir; // .velocity must be != '0 0 0' for particle fx and decal to work
210
211 if (this.move_movetype == MOVETYPE_BOUNCE || this.classname == "electro_orb") // TODO: classname is more reliable anyway?
212 RadiusDamage(this, this.realowner,
213 WEP_CVAR_SEC(WEP_ELECTRO, damage),
214 WEP_CVAR_SEC(WEP_ELECTRO, edgedamage),
215 WEP_CVAR_SEC(WEP_ELECTRO, radius),
216 NULL,
217 NULL,
218 WEP_CVAR_SEC(WEP_ELECTRO, force),
220 this.weaponentity_fld,
221 directhitentity
222 );
223 else
224 {
225 W_Electro_TriggerCombo(this.origin, WEP_CVAR_PRI(WEP_ELECTRO, comboradius), this.realowner);
226 RadiusDamage(this, this.realowner,
227 WEP_CVAR_PRI(WEP_ELECTRO, damage),
228 WEP_CVAR_PRI(WEP_ELECTRO, edgedamage),
229 WEP_CVAR_PRI(WEP_ELECTRO, radius),
230 NULL,
231 NULL,
232 WEP_CVAR_PRI(WEP_ELECTRO, force),
234 this.weaponentity_fld,
235 directhitentity
236 );
237 }
238
239 delete(this);
240}
float radius
Definition impulse.qh:11
bool IsFlying(entity this)
Definition player.qc:843
#define IS_DEAD(s)
Definition player.qh:244
#define IS_PLAYER(s)
Definition player.qh:242
string classname
vector velocity
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition damage.qc:934
void W_Electro_TriggerCombo(vector org, float rad, entity own)
Definition electro.qc:73
vector movedir
Definition viewloc.qh:18
float move_movetype
Definition movetypes.qh:80
var void func_null()
void Send_Notification(NOTIF broadcast, entity client, MSG net_type, Notification net_name,...count)
Definition all.qc:1500
int projectiledeathtype
Definition common.qh:21
const int DAMAGE_AIM
Definition subs.qh:81
float takedamage
Definition subs.qh:78
#define DIFF_TEAM(a, b)
Definition teams.qh:242
entity weaponentity_fld

References classname, DAMAGE_AIM, DAMAGE_NO, DIFF_TEAM, entity(), func_null(), IS_DEAD, IS_PLAYER, IsFlying(), move_movetype, movedir, MOVETYPE_BOUNCE, NULL, origin, projectiledeathtype, radius, RadiusDamage(), realowner, Send_Notification(), takedamage, velocity, W_Electro_TriggerCombo(), weaponentity_fld, WEP_CVAR_PRI, and WEP_CVAR_SEC.

Referenced by W_Electro_Explode_use(), W_Electro_Orb_Touch(), and W_Electro_TouchExplode().

◆ W_Electro_Explode_use()

void W_Electro_Explode_use ( entity this,
entity actor,
entity trigger )

Definition at line 242 of file electro.qc.

243{
244 W_Electro_Explode(this, trigger);
245}
void W_Electro_Explode(entity this, entity directhitentity)
Definition electro.qc:199

References entity(), and W_Electro_Explode().

Referenced by W_Electro_Attack_Bolt(), W_Electro_Attack_Orb(), and W_Electro_Orb_Damage().

◆ W_Electro_ExplodeCombo()

void W_Electro_ExplodeCombo ( entity this)

Definition at line 168 of file electro.qc.

169{
170 W_Electro_TriggerCombo(this.origin, WEP_CVAR(WEP_ELECTRO, combo_comboradius), this.realowner);
171
172 this.event_damage = func_null;
173 if (!this.velocity)
174 this.velocity = this.movedir; // .velocity must be != '0 0 0' for particle fx and decal to work
175
176 if (WEP_CVAR(WEP_ELECTRO, combo_duration))
177 {
179
180 delete(this);
181 return;
182 }
183
184 RadiusDamage(this, this.realowner,
185 WEP_CVAR(WEP_ELECTRO, combo_damage),
186 WEP_CVAR(WEP_ELECTRO, combo_edgedamage),
187 WEP_CVAR(WEP_ELECTRO, combo_radius),
188 NULL,
189 NULL,
190 WEP_CVAR(WEP_ELECTRO, combo_force),
191 WEP_ELECTRO.m_id | HITTYPE_BOUNCE, // use THIS type for a combo because primary can't bounce
192 this.weaponentity_fld,
193 NULL
194 );
195
196 delete(this);
197}
const int HITTYPE_BOUNCE
set manually after projectile has bounced
Definition all.qh:33
void W_Electro_Orb_ExplodeOverTime(entity this)
Definition electro.qc:145

References entity(), func_null(), HITTYPE_BOUNCE, movedir, NULL, origin, RadiusDamage(), realowner, velocity, W_Electro_Orb_ExplodeOverTime(), W_Electro_TriggerCombo(), and WEP_CVAR.

Referenced by W_Electro_Bolt_Think(), W_Electro_Orb_Damage(), and W_Electro_TriggerCombo().

◆ W_Electro_ExplodeComboThink()

void W_Electro_ExplodeComboThink ( entity this)

Definition at line 116 of file electro.qc.

117{
118 // NOTE: W_Hook_ExplodeThink uses similar code, please keep them in sync
119 float dt = time - this.teleport_time;
120
121 float dmg_remaining_next = bound(0, 1 - dt / WEP_CVAR(WEP_ELECTRO, combo_duration), 1);
122
123 float f = this.dmg_last - dmg_remaining_next;
124 this.dmg_last = dmg_remaining_next;
125
126 RadiusDamage(this, this.realowner,
127 f * WEP_CVAR(WEP_ELECTRO, combo_damage),
128 f * WEP_CVAR(WEP_ELECTRO, combo_edgedamage),
129 WEP_CVAR(WEP_ELECTRO, combo_radius),
130 NULL,
131 NULL,
132 0,
134 this.weaponentity_fld,
135 NULL
136 );
137 this.projectiledeathtype |= HITTYPE_SPAM; // ensure it doesn't spam its effect
138
139 if (dt < WEP_CVAR(WEP_ELECTRO, combo_duration))
141 else
142 delete(this);
143}
float teleport_time
Definition player.qh:218
const int HITTYPE_SPAM
set manually after first RadiusDamage, stops effect spam
Definition all.qh:36
const float ELECTRO_COMBO_OVERTIME_DELAY
Definition electro.qc:115
float dmg_last
Definition electro.qh:101

References bound(), dmg_last, ELECTRO_COMBO_OVERTIME_DELAY, entity(), HITTYPE_SPAM, nextthink, NULL, projectiledeathtype, RadiusDamage(), realowner, teleport_time, time, weaponentity_fld, and WEP_CVAR.

Referenced by W_Electro_Orb_ExplodeOverTime().

◆ W_Electro_Orb_Damage()

void W_Electro_Orb_Damage ( entity this,
entity inflictor,
entity attacker,
float damage,
int deathtype,
.entity weaponentity,
vector hitloc,
vector force )

Definition at line 482 of file electro.qc.

483{
484 if (GetResource(this, RES_HEALTH) <= 0)
485 return;
486
487 // note: combos are usually triggered by W_Electro_TriggerCombo, not damage
488 float is_combo = (inflictor.classname == "electro_orb_chain" || inflictor.classname == "electro_bolt");
489
490 if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, (is_combo ? 1 : -1)))
491 return; // g_projectiles_damage says to halt
492
493 TakeResource(this, RES_HEALTH, damage);
494 if (GetResource(this, RES_HEALTH) <= 0)
495 {
496 this.takedamage = DAMAGE_NO;
497 this.nextthink = time;
498 if (is_combo)
499 {
500 // change owner to whoever caused the combo explosion
501 this.realowner = inflictor.realowner;
502 this.classname = "electro_orb_chain";
504 // delay combo chains, looks cooler
505 // bound the length, inflictor may be in a galaxy far far away (warpzones)
506 float len = min(WEP_CVAR(WEP_ELECTRO, combo_radius), vlen(this.origin - inflictor.origin));
507 float delay = len / WEP_CVAR(WEP_ELECTRO, combo_speed);
508 this.nextthink = time + delay;
509 }
510 else
511 {
513 setthink(this, adaptor_think2use); // not _hittype_splash, as this runs "immediately"
514 }
515 }
516}
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
void TakeResource(entity receiver, Resource res_type, float amount)
Takes an entity some resource.
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception)
Definition common.qc:45

References classname, DAMAGE_NO, delay, entity(), GetResource(), min(), nextthink, origin, realowner, setthink, takedamage, TakeResource(), time, use, vector, vlen(), W_CheckProjectileDamage(), W_Electro_Explode_use(), W_Electro_ExplodeCombo(), and WEP_CVAR.

Referenced by W_Electro_Attack_Orb().

◆ W_Electro_Orb_ExplodeOverTime()

void W_Electro_Orb_ExplodeOverTime ( entity this)

Definition at line 145 of file electro.qc.

146{
147 entity newproj = spawn();
148 newproj.classname = this.classname;
149 newproj.solid = this.solid;
150 setorigin(newproj, this.origin);
151 setmodel(newproj, MDL_PROJECTILE_ELECTRO);
152 setsize(newproj, this.mins, this.maxs);
153 newproj.owner = this.owner;
154 newproj.realowner = this.realowner;
155 newproj.weaponentity_fld = this.weaponentity_fld;
156 newproj.projectiledeathtype = WEP_ELECTRO.m_id | HITTYPE_BOUNCE; // use THIS type for a combo because primary can't bounce
157
159 newproj.nextthink = time + ELECTRO_COMBO_OVERTIME_DELAY;
160 newproj.teleport_time = time;
161 newproj.dmg_last = 1;
162 set_movetype(newproj, MOVETYPE_NONE);
163
164 Net_LinkEntity(newproj, true, 0, electro_orb_send);
165 newproj.SendFlags = 0xFFFFFF;
166}
vector mins
vector maxs
float solid
#define spawn
bool electro_orb_send(entity this, entity to, int sf)
Definition electro.qc:56
void W_Electro_ExplodeComboThink(entity this)
Definition electro.qc:116
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167

References classname, ELECTRO_COMBO_OVERTIME_DELAY, electro_orb_send(), entity(), HITTYPE_BOUNCE, maxs, mins, MOVETYPE_NONE, Net_LinkEntity(), origin, owner, realowner, set_movetype(), setmodel, setthink, solid, spawn, time, W_Electro_ExplodeComboThink(), and weaponentity_fld.

Referenced by W_Electro_ExplodeCombo().

◆ W_Electro_Orb_Follow_Think()

void W_Electro_Orb_Follow_Think ( entity this)

Definition at line 369 of file electro.qc.

370{
371 if (time > this.death_time)
372 {
374 return;
375 }
376 if (this.move_movetype == MOVETYPE_FOLLOW)
377 {
378 int lost = LostMovetypeFollow(this);
379 if (lost == 2)
380 {
381 // FIXME if player disconnected, it isn't possible to drop the orb at player's origin
382 // see comment in LostMovetypeFollow implementation
383 delete(this);
384 return;
385 }
386 if (lost)
387 {
388 // drop the orb at the corpse's location
391
393 this.nextthink = this.death_time;
394 return;
395 }
396 }
397 this.nextthink = time;
398}
int LostMovetypeFollow(entity ent)
Definition util.qc:2171
float death_time
const int MOVETYPE_FOLLOW
Definition movetypes.qh:145
const int MOVETYPE_TOSS
Definition movetypes.qh:139

References adaptor_think2use_hittype_splash(), death_time, entity(), LostMovetypeFollow(), move_movetype, MOVETYPE_FOLLOW, MOVETYPE_TOSS, nextthink, PROJECTILE_MAKETRIGGER, set_movetype(), setthink, and time.

Referenced by W_Electro_Orb_Stick().

◆ W_Electro_Orb_Stick()

void W_Electro_Orb_Stick ( entity this,
entity to )

Definition at line 400 of file electro.qc.

401{
402 entity newproj = spawn();
403 newproj.classname = this.classname;
404
405 newproj.bot_dodge = this.bot_dodge;
406 newproj.bot_dodgerating = this.bot_dodgerating;
407
408 newproj.owner = this.owner;
409 newproj.realowner = this.realowner;
410 PROJECTILE_MAKETRIGGER(newproj);
411 setorigin(newproj, this.origin);
412 setmodel(newproj, MDL_PROJECTILE_ELECTRO);
413 setsize(newproj, this.mins, this.maxs);
414 newproj.angles = vectoangles(-trace_plane_normal); // face against the surface
415 newproj.traileffectnum = _particleeffectnum(EFFECT_TR_NEXUIZPLASMA.eent_eff_name);
416
417 newproj.movedir = -trace_plane_normal;
418
419 newproj.takedamage = this.takedamage;
420 newproj.damageforcescale = this.damageforcescale;
421 SetResourceExplicit(newproj, RES_HEALTH, GetResource(this, RES_HEALTH));
422 newproj.event_damage = this.event_damage;
423 newproj.spawnshieldtime = this.spawnshieldtime;
424 newproj.damagedbycontents = true;
426
427 set_movetype(newproj, MOVETYPE_NONE); // lock the orb in place
428 newproj.projectiledeathtype = this.projectiledeathtype;
429 newproj.weaponentity_fld = this.weaponentity_fld;
430
431 settouch(newproj, func_null);
432 if (WEP_CVAR_SEC(WEP_ELECTRO, stick_lifetime) > 0)
433 newproj.death_time = time + WEP_CVAR_SEC(WEP_ELECTRO, stick_lifetime);
434 else
435 newproj.death_time = this.death_time;
436 newproj.use = this.use;
437 newproj.flags = this.flags;
438 IL_PUSH(g_projectiles, newproj);
439 IL_PUSH(g_bot_dodge, newproj);
440
441 // check if limits are enabled (we can tell by checking if the original orb is listed) and push it to the list if so
444
445 delete(this);
446
447 if (to)
448 {
449 SetMovetypeFollow(newproj, to);
450
452 newproj.nextthink = time;
453 }
454 else
455 {
457 newproj.nextthink = newproj.death_time;
458 }
459}
float bot_dodge
Definition api.qh:40
float bot_dodgerating
Definition api.qh:39
void SetMovetypeFollow(entity ent, entity e)
Definition util.qc:2141
float flags
vector trace_plane_normal
float spawnshieldtime
Definition damage.qh:61
void W_Electro_Orb_Follow_Think(entity this)
Definition electro.qc:369
ERASEABLE bool IL_CONTAINS(IntrusiveList this, entity it)
entity ReplaceOldListedChildRubble(IntrusiveList list, entity child, entity oldChild)
Definition rubble.qc:39

References adaptor_think2use_hittype_splash(), bot_dodge, bot_dodgerating, classname, damageforcescale, death_time, entity(), flags, func_null(), g_bot_dodge, g_damagedbycontents, g_projectiles, GetResource(), IL_CONTAINS(), IL_PUSH(), LimitedElectroBallRubbleList, maxs, mins, MOVETYPE_NONE, origin, owner, PROJECTILE_MAKETRIGGER, projectiledeathtype, realowner, ReplaceOldListedChildRubble(), set_movetype(), setmodel, SetMovetypeFollow(), SetResourceExplicit(), setthink, settouch, spawn, spawnshieldtime, takedamage, time, trace_plane_normal, use, vectoangles(), W_Electro_Orb_Follow_Think(), weaponentity_fld, and WEP_CVAR_SEC.

Referenced by W_Electro_Orb_Touch().

◆ W_Electro_Orb_Touch()

void W_Electro_Orb_Touch ( entity this,
entity toucher )

Definition at line 461 of file electro.qc.

462{
464 if (toucher.takedamage == DAMAGE_AIM && WEP_CVAR_SEC(WEP_ELECTRO, touchexplode))
466 else if (toucher.owner != this.owner && toucher.classname != this.classname) // don't stick to player's other projectiles!
467 {
468 //UpdateCSQCProjectile(this);
469 spamsound(this, CH_SHOTS, SND_ELECTRO_BOUNCE, VOL_BASE, ATTEN_NORM);
471
472 if (WEP_CVAR_SEC(WEP_ELECTRO, stick))
473 {
474 if (WEP_CVAR_SEC(WEP_ELECTRO, stick_lifetime) == 0)
476 else
478 }
479 }
480}
void W_Electro_Orb_Stick(entity this, entity to)
Definition electro.qc:400
entity entity toucher
Definition self.qh:76
#define PROJECTILE_TOUCH(e, t)
Definition common.qh:28
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const float ATTEN_NORM
Definition sound.qh:30
float spamsound(entity e, int chan, Sound samp, float vol, float _atten)
use this one if you might be causing spam (e.g.
Definition all.qc:124

References ATTEN_NORM, CH_SHOTS, DAMAGE_AIM, entity(), HITTYPE_BOUNCE, PROJECTILE_TOUCH, projectiledeathtype, spamsound(), toucher, VOL_BASE, W_Electro_Explode(), W_Electro_Orb_Stick(), and WEP_CVAR_SEC.

Referenced by W_Electro_Attack_Orb().

◆ W_Electro_TouchExplode()

void W_Electro_TouchExplode ( entity this,
entity toucher )

Definition at line 247 of file electro.qc.

248{
251}

References entity(), PROJECTILE_TOUCH, toucher, and W_Electro_Explode().

Referenced by W_Electro_Attack_Bolt().

◆ W_Electro_TriggerCombo()

void W_Electro_TriggerCombo ( vector org,
float rad,
entity own )

Definition at line 73 of file electro.qc.

74{
75 entity e = WarpZone_FindRadius(org, rad, !WEP_CVAR(WEP_ELECTRO, combo_comboradius_thruwall));
76 for (; e; e = e.chain)
77 if (e.classname == "electro_orb")
78 {
79 // check if the ball we are exploding is not owned by an
80 // independent player which is not the player who shot the ball
81 if (IS_INDEPENDENT_PLAYER(e.realowner) && own != e.realowner)
82 continue;
83
84 // do we allow thruwall triggering?
85 if (WEP_CVAR(WEP_ELECTRO, combo_comboradius_thruwall))
86 {
87 // if distance is greater than thruwall distance, check to make sure it's not through a wall
88 if (vdist(e.WarpZone_findradius_dist, >, WEP_CVAR(WEP_ELECTRO, combo_comboradius_thruwall)))
89 {
91 if (trace_fraction != 1)
92 {
93 // trigger is through a wall and outside of thruwall range, abort
94 continue;
95 }
96 }
97 }
98
99 // change owner to whoever caused the combo explosion
100 e.realowner = own;
101 e.takedamage = DAMAGE_NO;
102 e.classname = "electro_orb_chain";
103
104 // now set the next one to trigger as well
106
107 // delay combo chains, looks cooler
108 float delay = (WEP_CVAR(WEP_ELECTRO, combo_speed))
109 ? vlen(e.WarpZone_findradius_dist) / WEP_CVAR(WEP_ELECTRO, combo_speed)
110 : 0;
111 e.nextthink = time + delay;
112 }
113}
const float MOVE_NOMONSTERS
float trace_fraction
void WarpZone_TraceLine(vector org, vector end, float nomonsters, entity forent)
Definition common.qc:328
vector org
Definition self.qh:96
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt().
Definition vector.qh:8

References DAMAGE_NO, delay, entity(), IS_INDEPENDENT_PLAYER, MOVE_NOMONSTERS, org, setthink, time, trace_fraction, vdist, vector, vlen(), W_Electro_ExplodeCombo(), WarpZone_FindRadius(), WarpZone_TraceLine(), and WEP_CVAR.

Referenced by W_Electro_Explode(), and W_Electro_ExplodeCombo().

Variable Documentation

◆ bot_secondary_electromooth

bool bot_secondary_electromooth

Definition at line 601 of file electro.qc.

◆ ELECTRO_COMBO_OVERTIME_DELAY

const float ELECTRO_COMBO_OVERTIME_DELAY = 0.0625

Definition at line 115 of file electro.qc.

Referenced by W_Electro_ExplodeComboThink(), and W_Electro_Orb_ExplodeOverTime().

◆ ltime

float ltime

Definition at line 7 of file electro.qc.