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
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 315 of file electro.qc.

316{
317 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(WEP_ELECTRO, ammo), weaponentity);
318
320 actor,
321 weaponentity,
322 '0 0 -3',
323 '0 0 -3',
324 false,
325 2,
326 SND_ELECTRO_FIRE,
328 WEP_CVAR_PRI(WEP_ELECTRO, damage),
329 thiswep.m_id
330 );
331
332 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
333
334 entity proj = new(electro_bolt);
335 proj.owner = proj.realowner = actor;
336 proj.bot_dodge = true;
337 proj.bot_dodgerating = WEP_CVAR_PRI(WEP_ELECTRO, damage);
338 proj.use = W_Electro_Explode_use;
340 proj.nextthink = time;
341 proj.ltime = time + WEP_CVAR_PRI(WEP_ELECTRO, lifetime);
343 proj.projectiledeathtype = thiswep.m_id;
344 proj.weaponentity_fld = weaponentity;
345 setorigin(proj, w_shotorg);
346
347 // if (IS_CSQC)
349 W_SetupProjVelocity_PRI(proj, WEP_ELECTRO);
350 proj.angles = vectoangles(proj.velocity);
352 setsize(proj, '0 0 -3', '0 0 -3');
353 proj.flags = FL_PROJECTILE;
354 IL_PUSH(g_projectiles, proj);
355 IL_PUSH(g_bot_dodge, proj);
356 proj.missile_flags = MIF_SPLASH;
357
358 CSQCProjectile(proj, true, PROJECTILE_ELECTRO_BEAM, true);
359
360 MUTATOR_CALLHOOK(EditProjectile, actor, proj);
361 // proj.com_phys_pos = proj.origin;
362 // proj.com_phys_vel = proj.velocity;
363}
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:85
void CSQCProjectile(entity e, float clientanimate, int type, float docull)
void W_Electro_TouchExplode(entity this, entity toucher)
Definition electro.qc:243
void W_Electro_Explode_use(entity this, entity actor, entity trigger)
Definition electro.qc:238
void W_Electro_Bolt_Think(entity this)
Definition electro.qc:252
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 514 of file electro.qc.

515{
516 W_DecreaseAmmo(thiswep, actor, WEP_CVAR_SEC(WEP_ELECTRO, ammo), weaponentity);
517
519 actor,
520 weaponentity,
521 '-4 -4 -4',
522 '4 4 4',
523 false,
524 2,
525 SND_ELECTRO_FIRE2,
527 WEP_CVAR_SEC(WEP_ELECTRO, damage),
528 thiswep.m_id | HITTYPE_SECONDARY
529 );
530
531 w_shotdir = v_forward; // no TrueAim for grenades please
532
533 W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir);
534
535 entity proj = new(electro_orb);
536 proj.owner = proj.realowner = actor;
537 proj.use = W_Electro_Explode_use;
539 proj.bot_dodge = true;
540 proj.bot_dodgerating = WEP_CVAR_SEC(WEP_ELECTRO, damage);
541 proj.nextthink = time + WEP_CVAR_SEC(WEP_ELECTRO, lifetime);
542 proj.death_time = time + WEP_CVAR_SEC(WEP_ELECTRO, lifetime);
544 proj.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY;
545 proj.weaponentity_fld = weaponentity;
546 setorigin(proj, w_shotorg);
547
548 //proj.glow_size = 50;
549 //proj.glow_color = 45;
551 W_SetupProjVelocity_UP_SEC(proj, WEP_ELECTRO);
553 setsize(proj, '-4 -4 -4', '4 4 4');
554 proj.takedamage = DAMAGE_YES;
555 proj.damageforcescale = WEP_CVAR_SEC(WEP_ELECTRO, damageforcescale);
556 SetResourceExplicit(proj, RES_HEALTH, WEP_CVAR_SEC(WEP_ELECTRO, health));
557 proj.event_damage = W_Electro_Orb_Damage;
558 proj.flags = FL_PROJECTILE;
559 IL_PUSH(g_projectiles, proj);
560 IL_PUSH(g_bot_dodge, proj);
561 proj.damagedbycontents = (WEP_CVAR_SEC(WEP_ELECTRO, damagedbycontents));
562 if (proj.damagedbycontents)
564
565 proj.bouncefactor = WEP_CVAR_SEC(WEP_ELECTRO, bouncefactor);
566 proj.bouncestop = WEP_CVAR_SEC(WEP_ELECTRO, bouncestop);
567 proj.missile_flags = MIF_SPLASH | MIF_ARC;
568
569 if (WEP_CVAR_SEC(WEP_ELECTRO, limit) > 0)
570 {
575 }
576
577 CSQCProjectile(proj, true, PROJECTILE_ELECTRO, false); // no culling, it has sound
578
579 MUTATOR_CALLHOOK(EditProjectile, actor, proj);
580}
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:457
void W_Electro_Orb_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype,.entity weaponentity, vector hitloc, vector force)
Definition electro.qc:478
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 252 of file electro.qc.

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

583{
584 if (actor.(weaponentity).electro_count > 1
586 && weapon_prepareattack(thiswep, actor, weaponentity, true, -1))
587 {
588 W_Electro_Attack_Orb(thiswep, actor, weaponentity);
589 --actor.(weaponentity).electro_count;
590 actor.(weaponentity).electro_secondarytime = time;
591 weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(WEP_ELECTRO, animtime), W_Electro_CheckAttack);
592 return;
593 }
594 w_ready(thiswep, actor, weaponentity, fire);
595}
#define PHYS_INPUT_BUTTON_ATCK2(s)
Definition player.qh:154
void W_Electro_Attack_Orb(Weapon thiswep, entity actor,.entity weaponentity)
Definition electro.qc:514
void W_Electro_CheckAttack(Weapon thiswep, entity actor,.entity weaponentity, int fire)
Definition electro.qc:582
float electro_count
Definition electro.qh:101
float electro_secondarytime
Definition electro.qh:102
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 195 of file electro.qc.

196{
197 if (directhitentity.takedamage == DAMAGE_AIM
198 && IS_PLAYER(directhitentity) && DIFF_TEAM(this.realowner, directhitentity) && !IS_DEAD(directhitentity)
199 && IsFlying(directhitentity))
200 Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_ELECTROBITCH);
201
202 this.event_damage = func_null;
203 this.takedamage = DAMAGE_NO;
204 if (!this.velocity)
205 this.velocity = this.movedir; // .velocity must be != '0 0 0' for particle fx and decal to work
206
207 if (this.move_movetype == MOVETYPE_BOUNCE || this.classname == "electro_orb") // TODO: classname is more reliable anyway?
208 RadiusDamage(this, this.realowner,
209 WEP_CVAR_SEC(WEP_ELECTRO, damage),
210 WEP_CVAR_SEC(WEP_ELECTRO, edgedamage),
211 WEP_CVAR_SEC(WEP_ELECTRO, radius),
212 NULL,
213 NULL,
214 WEP_CVAR_SEC(WEP_ELECTRO, force),
216 this.weaponentity_fld,
217 directhitentity
218 );
219 else
220 {
221 W_Electro_TriggerCombo(this.origin, WEP_CVAR_PRI(WEP_ELECTRO, comboradius), this.realowner);
222 RadiusDamage(this, this.realowner,
223 WEP_CVAR_PRI(WEP_ELECTRO, damage),
224 WEP_CVAR_PRI(WEP_ELECTRO, edgedamage),
225 WEP_CVAR_PRI(WEP_ELECTRO, radius),
226 NULL,
227 NULL,
228 WEP_CVAR_PRI(WEP_ELECTRO, force),
230 this.weaponentity_fld,
231 directhitentity
232 );
233 }
234
235 delete(this);
236}
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 238 of file electro.qc.

239{
240 W_Electro_Explode(this, trigger);
241}
void W_Electro_Explode(entity this, entity directhitentity)
Definition electro.qc:195

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 164 of file electro.qc.

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

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 115 of file electro.qc.

116{
117 if (time >= this.ltime)
118 {
119 delete(this);
120 return;
121 }
122
123 this.nextthink = time;
124
125 RadiusDamage(this, this.realowner,
126 PHYS_INPUT_TIMELENGTH * WEP_CVAR(WEP_ELECTRO, combo_damage),
127 PHYS_INPUT_TIMELENGTH * WEP_CVAR(WEP_ELECTRO, combo_edgedamage),
128 WEP_CVAR(WEP_ELECTRO, combo_radius),
129 NULL,
130 NULL,
131 0,
133 this.weaponentity_fld,
134 NULL
135 );
136 this.projectiledeathtype |= HITTYPE_SPAM; // ensure it doesn't spam its effect
137}
#define PHYS_INPUT_TIMELENGTH
Definition player.qh:253
const int HITTYPE_SPAM
set manually after first RadiusDamage, stops effect spam
Definition all.qh:36

References entity(), HITTYPE_SPAM, ltime, nextthink, NULL, PHYS_INPUT_TIMELENGTH, projectiledeathtype, RadiusDamage(), realowner, 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 478 of file electro.qc.

479{
480 if (GetResource(this, RES_HEALTH) <= 0)
481 return;
482
483 // note: combos are usually triggered by W_Electro_TriggerCombo, not damage
484 float is_combo = (inflictor.classname == "electro_orb_chain" || inflictor.classname == "electro_bolt");
485
486 if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, (is_combo ? 1 : -1)))
487 return; // g_projectiles_damage says to halt
488
489 TakeResource(this, RES_HEALTH, damage);
490 if (GetResource(this, RES_HEALTH) <= 0)
491 {
492 this.takedamage = DAMAGE_NO;
493 this.nextthink = time;
494 if (is_combo)
495 {
496 // change owner to whoever caused the combo explosion
497 this.realowner = inflictor.realowner;
498 this.classname = "electro_orb_chain";
500 // delay combo chains, looks cooler
501 // bound the length, inflictor may be in a galaxy far far away (warpzones)
502 float len = min(WEP_CVAR(WEP_ELECTRO, combo_radius), vlen(this.origin - inflictor.origin));
503 float delay = len / WEP_CVAR(WEP_ELECTRO, combo_speed);
504 this.nextthink = time + delay;
505 }
506 else
507 {
509 setthink(this, adaptor_think2use); // not _hittype_splash, as this runs "immediately"
510 }
511 }
512}
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 139 of file electro.qc.

140{
141 entity newproj = spawn();
142 newproj.classname = this.classname;
143 newproj.solid = this.solid;
144 setorigin(newproj, this.origin);
145 setmodel(newproj, MDL_PROJECTILE_ELECTRO);
146 setsize(newproj, this.mins, this.maxs);
147 newproj.owner = this.owner;
148 newproj.realowner = this.realowner;
149 newproj.weaponentity_fld = this.weaponentity_fld;
150 newproj.projectiledeathtype = WEP_ELECTRO.m_id | HITTYPE_BOUNCE; // use THIS type for a combo because primary can't bounce
151
153 newproj.nextthink = time;
154 newproj.ltime = time + WEP_CVAR(WEP_ELECTRO, combo_duration);
155 set_movetype(newproj, MOVETYPE_NONE);
156
157 Net_LinkEntity(newproj, true, 0, electro_orb_send);
158 newproj.SendFlags = 0xFFFFFF;
159
160 // fire the first damage tick immediately
161 getthink(newproj)(newproj);
162}
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:115
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
Definition net.qh:167
#define getthink(e)

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

Referenced by W_Electro_ExplodeCombo().

◆ W_Electro_Orb_Follow_Think()

void W_Electro_Orb_Follow_Think ( entity this)

Definition at line 365 of file electro.qc.

366{
367 if (time > this.death_time)
368 {
370 return;
371 }
372 if (this.move_movetype == MOVETYPE_FOLLOW)
373 {
374 int lost = LostMovetypeFollow(this);
375 if (lost == 2)
376 {
377 // FIXME if player disconnected, it isn't possible to drop the orb at player's origin
378 // see comment in LostMovetypeFollow implementation
379 delete(this);
380 return;
381 }
382 if (lost)
383 {
384 // drop the orb at the corpse's location
387
389 this.nextthink = this.death_time;
390 return;
391 }
392 }
393 this.nextthink = time;
394}
int LostMovetypeFollow(entity ent)
Definition util.qc:2159
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 396 of file electro.qc.

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

458{
460 if (toucher.takedamage == DAMAGE_AIM && WEP_CVAR_SEC(WEP_ELECTRO, touchexplode))
462 else if (toucher.owner != this.owner && toucher.classname != this.classname) // don't stick to player's other projectiles!
463 {
464 //UpdateCSQCProjectile(this);
465 spamsound(this, CH_SHOTS, SND_ELECTRO_BOUNCE, VOL_BASE, ATTEN_NORM);
467
468 if (WEP_CVAR_SEC(WEP_ELECTRO, stick))
469 {
470 if (WEP_CVAR_SEC(WEP_ELECTRO, stick_lifetime) == 0)
472 else
474 }
475 }
476}
void W_Electro_Orb_Stick(entity this, entity to)
Definition electro.qc:396
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 243 of file electro.qc.

244{
247}

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 597 of file electro.qc.

◆ ltime

float ltime

Definition at line 7 of file electro.qc.