X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fweapons%2Fweapon%2Felectro.qc;h=cd577e1e45103118fc1929caeab091981d8d1700;hb=b88055b3d2a8bda473630931824c65839d2b139d;hp=61acc0dd75eec382c186983fb98cd6923c0ee3db;hpb=e9ecd2b73f8332531578e76c10df263c7a29717a;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/weapons/weapon/electro.qc b/qcsrc/common/weapons/weapon/electro.qc index 61acc0dd7..cd577e1e4 100644 --- a/qcsrc/common/weapons/weapon/electro.qc +++ b/qcsrc/common/weapons/weapon/electro.qc @@ -1,6 +1,7 @@ #include "electro.qh" #ifdef SVQC +#include void W_Electro_TriggerCombo(vector org, float rad, entity own) { @@ -34,16 +35,10 @@ void W_Electro_TriggerCombo(vector org, float rad, entity own) setthink(e, W_Electro_ExplodeCombo); // delay combo chains, looks cooler - e.nextthink = - ( - time - + - (WEP_CVAR(electro, combo_speed) ? - (vlen(e.WarpZone_findradius_dist) / WEP_CVAR(electro, combo_speed)) - : - 0 - ) - ); + float delay = 0; + if (WEP_CVAR(electro, combo_speed)) + delay = vlen(e.WarpZone_findradius_dist) / WEP_CVAR(electro, combo_speed); + e.nextthink = time + delay; } e = e.chain; } @@ -54,6 +49,7 @@ void W_Electro_ExplodeCombo(entity this) W_Electro_TriggerCombo(this.origin, WEP_CVAR(electro, combo_comboradius), this.realowner); this.event_damage = func_null; + this.velocity = this.movedir; // particle fx and decals need .velocity RadiusDamage( this, @@ -83,6 +79,7 @@ void W_Electro_Explode(entity this, entity directhitentity) this.event_damage = func_null; this.takedamage = DAMAGE_NO; + this.velocity = this.movedir; // particle fx and decals need .velocity if(this.move_movetype == MOVETYPE_BOUNCE || this.classname == "electro_orb") // TODO: classname is more reliable anyway? { @@ -133,7 +130,7 @@ void W_Electro_TouchExplode(entity this, entity toucher) } -void sys_phys_update_single(entity this); +//void sys_phys_update_single(entity this); void W_Electro_Bolt_Think(entity this) { @@ -180,17 +177,10 @@ void W_Electro_Bolt_Think(entity this) // (the bolt and orb should explode together because they interacted together) // while keeping the chaining delay. setthink(e, W_Electro_ExplodeCombo); - e.nextthink = - ( - time - + - (WEP_CVAR_PRI(electro, midaircombo_speed) ? - (vlen(e.WarpZone_findradius_dist) / WEP_CVAR_PRI(electro, midaircombo_speed)) - : - 0 - ) - ); - + float delay = 0; + if (WEP_CVAR_PRI(electro, midaircombo_speed)) + delay = vlen(e.WarpZone_findradius_dist) / WEP_CVAR_PRI(electro, midaircombo_speed); + e.nextthink = time + delay; ++found; } @@ -227,7 +217,7 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity) thiswep.m_id ); - W_MuzzleFlash(actor, weaponentity, EFFECT_ELECTRO_MUZZLEFLASH, MDL_Null, w_shotorg, w_shotdir); + W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir); proj = new(electro_bolt); proj.owner = proj.realowner = actor; @@ -260,6 +250,37 @@ void W_Electro_Attack_Bolt(Weapon thiswep, entity actor, .entity weaponentity) // proj.com_phys_vel = proj.velocity; } +void W_Electro_Orb_Follow_Think(entity this) +{ + if (time > this.death_time) + { + adaptor_think2use_hittype_splash(this); + return; + } + if (this.move_movetype == MOVETYPE_FOLLOW) + { + int lost = LostMovetypeFollow(this); + if (lost == 2) + { + // FIXME if player disconnected, it isn't possible to drop the orb at player's origin + // see comment in LostMovetypeFollow implementation + delete(this); + return; + } + if (lost) + { + // drop the orb at the corpse's location + PROJECTILE_MAKETRIGGER(this); + set_movetype(this, MOVETYPE_TOSS); + + setthink(this, adaptor_think2use_hittype_splash); + this.nextthink = this.death_time; + return; + } + } + this.nextthink = time; +} + void W_Electro_Orb_Stick(entity this, entity to) { entity newproj = spawn(); @@ -270,10 +291,13 @@ void W_Electro_Orb_Stick(entity this, entity to) newproj.owner = this.owner; newproj.realowner = this.realowner; - setsize(newproj, this.mins, this.maxs); setorigin(newproj, this.origin); setmodel(newproj, MDL_PROJECTILE_ELECTRO); + setsize(newproj, this.mins, this.maxs); newproj.angles = vectoangles(-trace_plane_normal); // face against the surface + newproj.traileffectnum = _particleeffectnum(EFFECT_TR_NEXUIZPLASMA.eent_eff_name); + + newproj.movedir = -trace_plane_normal; newproj.takedamage = this.takedamage; newproj.damageforcescale = this.damageforcescale; @@ -288,17 +312,32 @@ void W_Electro_Orb_Stick(entity this, entity to) newproj.weaponentity_fld = this.weaponentity_fld; settouch(newproj, func_null); - setthink(newproj, getthink(this)); - newproj.nextthink = this.nextthink; + newproj.death_time = this.death_time; newproj.use = this.use; newproj.flags = this.flags; IL_PUSH(g_projectiles, newproj); IL_PUSH(g_bot_dodge, newproj); + // check if limits are enabled (we can tell by checking if the original orb is listed) and push it to the list if so + if(LimitedElectroBallRubbleList && IL_CONTAINS(LimitedElectroBallRubbleList, this)) + { + ReplaceOldListedChildRubble(LimitedElectroBallRubbleList, newproj, this); + } + delete(this); if(to) + { SetMovetypeFollow(newproj, to); + + setthink(newproj, W_Electro_Orb_Follow_Think); + newproj.nextthink = time; + } + else + { + setthink(newproj, adaptor_think2use_hittype_splash); + newproj.nextthink = newproj.death_time; + } } void W_Electro_Orb_Touch(entity this, entity toucher) @@ -339,17 +378,11 @@ void W_Electro_Orb_Damage(entity this, entity inflictor, entity attacker, float this.realowner = inflictor.realowner; this.classname = "electro_orb_chain"; setthink(this, W_Electro_ExplodeCombo); - this.nextthink = time + - ( - // bound the length, inflictor may be in a galaxy far far away (warpzones) - min( - WEP_CVAR(electro, combo_radius), - vlen(this.origin - inflictor.origin) - ) - / - // delay combo chains, looks cooler - WEP_CVAR(electro, combo_speed) - ); + // delay combo chains, looks cooler + // bound the length, inflictor may be in a galaxy far far away (warpzones) + float len = min(WEP_CVAR(electro, combo_radius), vlen(this.origin - inflictor.origin)); + float delay = len / WEP_CVAR(electro, combo_speed); + this.nextthink = time + delay; } else { @@ -378,7 +411,7 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity) w_shotdir = v_forward; // no TrueAim for grenades please - W_MuzzleFlash(actor, weaponentity, EFFECT_ELECTRO_MUZZLEFLASH, MDL_Null, w_shotorg, w_shotdir); + W_MuzzleFlash(thiswep, actor, weaponentity, w_shotorg, w_shotdir); entity proj = new(electro_orb); proj.owner = proj.realowner = actor; @@ -387,6 +420,7 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity) proj.bot_dodge = true; proj.bot_dodgerating = WEP_CVAR_SEC(electro, damage); proj.nextthink = time + WEP_CVAR_SEC(electro, lifetime); + proj.death_time = time + WEP_CVAR_SEC(electro, lifetime); PROJECTILE_MAKETRIGGER(proj); proj.projectiledeathtype = thiswep.m_id | HITTYPE_SECONDARY; proj.weaponentity_fld = weaponentity; @@ -413,6 +447,14 @@ void W_Electro_Attack_Orb(Weapon thiswep, entity actor, .entity weaponentity) proj.bouncestop = WEP_CVAR_SEC(electro, bouncestop); proj.missile_flags = MIF_SPLASH | MIF_ARC; + if(WEP_CVAR_SEC(electro, limit) > 0) + { + if (!LimitedElectroBallRubbleList) + LimitedElectroBallRubbleList = IL_NEW(); + ListNewChildRubble(LimitedElectroBallRubbleList, proj); + LimitedChildrenRubble(LimitedElectroBallRubbleList, "electro_orb", WEP_CVAR_SEC(electro, limit), adaptor_think2use_hittype_splash, actor); + } + CSQCProjectile(proj, true, PROJECTILE_ELECTRO, false); // no culling, it has sound MUTATOR_CALLHOOK(EditProjectile, actor, proj); @@ -426,10 +468,10 @@ void W_Electro_CheckAttack(Weapon thiswep, entity actor, .entity weaponentity, i { W_Electro_Attack_Orb(thiswep, actor, weaponentity); actor.(weaponentity).electro_count -= 1; + actor.(weaponentity).electro_secondarytime = time; weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack); return; } - // WEAPONTODO: when the player releases the button, cut down the length of refire2? w_ready(thiswep, actor, weaponentity, fire); } @@ -482,6 +524,7 @@ METHOD(Electro, wr_think, void(entity thiswep, entity actor, .entity weaponentit if(fire & 1) { + if(time >= actor.(weaponentity).electro_secondarytime + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor(actor)) if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(electro, refire))) { W_Electro_Attack_Bolt(thiswep, actor, weaponentity); @@ -490,13 +533,13 @@ METHOD(Electro, wr_think, void(entity thiswep, entity actor, .entity weaponentit } else if(fire & 2) { - if(time >= actor.(weaponentity).electro_secondarytime) - if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(electro, refire))) + if(time >= actor.(weaponentity).electro_secondarytime + WEP_CVAR_SEC(electro, refire) * W_WeaponRateFactor(actor)) + if(weapon_prepareattack(thiswep, actor, weaponentity, true, -1)) { W_Electro_Attack_Orb(thiswep, actor, weaponentity); actor.(weaponentity).electro_count = WEP_CVAR_SEC(electro, count); + actor.(weaponentity).electro_secondarytime = time; weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack); - actor.(weaponentity).electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor(actor); } } }