X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fcommon%2Fweapons%2Fweapon%2Fdevastator.qc;h=b75ca6f02aa0361f0da7397321406643aaefa8be;hb=cdcdcf9dfdaea11bd43312ceca679a6bfc9b7bf3;hp=1966509e6eb5aab8dfa298224f165cfe7b72a633;hpb=daab9330abb8952053b47239d1322cd029b08cd1;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/weapons/weapon/devastator.qc b/qcsrc/common/weapons/weapon/devastator.qc index 1966509e6..b75ca6f02 100644 --- a/qcsrc/common/weapons/weapon/devastator.qc +++ b/qcsrc/common/weapons/weapon/devastator.qc @@ -1,12 +1,13 @@ +#include "devastator.qh" #ifndef IMPLEMENTATION CLASS(Devastator, Weapon) -/* ammotype */ ATTRIB(Devastator, ammo_field, .int, ammo_rockets) -/* impulse */ ATTRIB(Devastator, impulse, int, 9) +/* ammotype */ ATTRIB(Devastator, ammo_field, .int, ammo_rockets); +/* impulse */ ATTRIB(Devastator, impulse, int, 9); /* flags */ ATTRIB(Devastator, spawnflags, int, WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH); /* rating */ ATTRIB(Devastator, bot_pickupbasevalue, float, BOT_PICKUP_RATING_HIGH); /* color */ ATTRIB(Devastator, wpcolor, vector, '1 1 0'); /* modelname */ ATTRIB(Devastator, mdl, string, "rl"); -#ifndef MENUQC +#ifdef GAMEQC /* model */ ATTRIB(Devastator, m_model, Model, MDL_DEVASTATOR_ITEM); #endif /* crosshair */ ATTRIB(Devastator, w_crosshair, string, "gfx/crosshairrocketlauncher"); @@ -72,77 +73,88 @@ spawnfunc(weapon_rocketlauncher) { spawnfunc_weapon_devastator(this); } .entity lastrocket; -void W_Devastator_Unregister() -{SELFPARAM(); - if(self.realowner && self.realowner.lastrocket == self) +void W_Devastator_Unregister(entity this) +{ + if(this.realowner && this.realowner.lastrocket == this) { - self.realowner.lastrocket = world; - // self.realowner.rl_release = 1; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if(this.realowner.(weaponentity).lastrocket == this) + this.realowner.(weaponentity).lastrocket = NULL; + } + // this.realowner.rl_release = 1; } } -void W_Devastator_Explode() -{SELFPARAM(); - W_Devastator_Unregister(); +void W_Devastator_Explode(entity this, entity directhitentity) +{ + W_Devastator_Unregister(this); - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(!IS_DEAD(other)) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); + if(directhitentity.takedamage == DAMAGE_AIM) + if(IS_PLAYER(directhitentity)) + if(DIFF_TEAM(this.realowner, directhitentity)) + if(!IS_DEAD(directhitentity)) + if(IsFlying(directhitentity)) + Send_Notification(NOTIF_ONE, this.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; + this.event_damage = func_null; + this.takedamage = DAMAGE_NO; RadiusDamage( - self, - self.realowner, + this, + this.realowner, WEP_CVAR(devastator, damage), WEP_CVAR(devastator, edgedamage), WEP_CVAR(devastator, radius), - world, - world, + NULL, + NULL, WEP_CVAR(devastator, force), - self.projectiledeathtype, - other + this.projectiledeathtype, + directhitentity ); Weapon thiswep = WEP_DEVASTATOR; - if(PS(self.realowner).m_weapon == thiswep) + .entity weaponentity = this.weaponentity_fld; + if(this.realowner.(weaponentity).m_weapon == thiswep) { - if(self.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo)) - if(!(self.realowner.items & IT_UNLIMITED_WEAPON_AMMO)) + if(this.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo)) + if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO)) { - self.realowner.cnt = WEP_DEVASTATOR.m_id; - int slot = 0; // TODO: unhardcode - ATTACK_FINISHED(self.realowner, slot) = time; - PS(self.realowner).m_switchweapon = w_getbestweapon(self.realowner); + this.realowner.cnt = WEP_DEVASTATOR.m_id; + int slot = weaponslot(weaponentity); + ATTACK_FINISHED(this.realowner, slot) = time; + this.realowner.(weaponentity).m_switchweapon = w_getbestweapon(this.realowner, weaponentity); } } - remove(self); + delete(this); } -void W_Devastator_DoRemoteExplode(.entity weaponentity) -{SELFPARAM(); - W_Devastator_Unregister(); +void W_Devastator_Explode_think(entity this) +{ + W_Devastator_Explode(this, NULL); +} + +void W_Devastator_DoRemoteExplode(entity this, .entity weaponentity) +{ + W_Devastator_Unregister(this); - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; + this.event_damage = func_null; + this.takedamage = DAMAGE_NO; float handled_as_rocketjump = false; entity head = WarpZone_FindRadius( - self.origin, + this.origin, WEP_CVAR(devastator, remote_jump_radius), false ); while(head) { - if(head.takedamage && (head == self.realowner)) + if(head.takedamage && (head == this.realowner)) { - float distance_to_head = vlen(self.origin - head.WarpZone_findradius_nearest); + float distance_to_head = vlen(this.origin - head.WarpZone_findradius_nearest); if(distance_to_head <= WEP_CVAR(devastator, remote_jump_radius)) { // we handled this as a rocketjump :) @@ -159,16 +171,16 @@ void W_Devastator_DoRemoteExplode(.entity weaponentity) // now do the damage RadiusDamage( - self, + this, head, WEP_CVAR(devastator, remote_jump_damage), WEP_CVAR(devastator, remote_jump_damage), WEP_CVAR(devastator, remote_jump_radius), - world, + NULL, head, 0, - self.projectiledeathtype | HITTYPE_BOUNCE, - world + this.projectiledeathtype | HITTYPE_BOUNCE, + NULL ); break; } @@ -177,44 +189,44 @@ void W_Devastator_DoRemoteExplode(.entity weaponentity) } RadiusDamage( - self, - self.realowner, + this, + this.realowner, WEP_CVAR(devastator, remote_damage), WEP_CVAR(devastator, remote_edgedamage), WEP_CVAR(devastator, remote_radius), - (handled_as_rocketjump ? head : world), - world, + (handled_as_rocketjump ? head : NULL), + NULL, WEP_CVAR(devastator, remote_force), - self.projectiledeathtype | HITTYPE_BOUNCE, - world + this.projectiledeathtype | HITTYPE_BOUNCE, + NULL ); Weapon thiswep = WEP_DEVASTATOR; - if(PS(self.realowner).m_weapon == thiswep) + if(this.realowner.(weaponentity).m_weapon == thiswep) { - if(self.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo)) - if(!(self.realowner.items & IT_UNLIMITED_WEAPON_AMMO)) + if(this.realowner.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo)) + if(!(this.realowner.items & IT_UNLIMITED_WEAPON_AMMO)) { - self.realowner.cnt = WEP_DEVASTATOR.m_id; + this.realowner.cnt = WEP_DEVASTATOR.m_id; int slot = weaponslot(weaponentity); - ATTACK_FINISHED(self.realowner, slot) = time; - PS(self.realowner).m_switchweapon = w_getbestweapon(self.realowner); + ATTACK_FINISHED(this.realowner, slot) = time; + this.realowner.(weaponentity).m_switchweapon = w_getbestweapon(this.realowner, weaponentity); } } - remove(self); + delete(this); } -void W_Devastator_RemoteExplode(.entity weaponentity) -{SELFPARAM(); - if(!IS_DEAD(self.realowner)) - if(self.realowner.lastrocket) +void W_Devastator_RemoteExplode(entity this, .entity weaponentity) +{ + if(!IS_DEAD(this.realowner)) + if(this.realowner.(weaponentity).lastrocket) { - if((self.spawnshieldtime >= 0) - ? (time >= self.spawnshieldtime) // timer - : (vdist(NearestPointOnBox(self.realowner, self.origin) - self.origin, >, WEP_CVAR(devastator, remote_radius))) // safety device + if((this.spawnshieldtime >= 0) + ? (time >= this.spawnshieldtime) // timer + : (vdist(NearestPointOnBox(this.realowner, this.origin) - this.origin, >, WEP_CVAR(devastator, remote_radius))) // safety device ) { - W_Devastator_DoRemoteExplode(weaponentity); + W_Devastator_DoRemoteExplode(this, weaponentity); } } } @@ -252,84 +264,83 @@ vector W_Devastator_SteerTo(vector thisdir, vector goaldir, float maxturn_cos) // normalize(thisdir + goaldir) // normalize(0) -void W_Devastator_Think() -{SELFPARAM(); +void W_Devastator_Think(entity this) +{ vector desireddir, olddir, newdir, desiredorigin, goal; float velspeed, f; - self.nextthink = time; - if(time > self.cnt) + this.nextthink = time; + if(time > this.cnt) { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_Devastator_Explode(); + this.projectiledeathtype |= HITTYPE_BOUNCE; + W_Devastator_Explode(this, NULL); return; } // accelerate - makevectors(self.angles.x * '-1 0 0' + self.angles.y * '0 1 0'); - velspeed = WEP_CVAR(devastator, speed) * W_WeaponSpeedFactor() - (self.velocity * v_forward); + makevectors(this.angles.x * '-1 0 0' + this.angles.y * '0 1 0'); + velspeed = WEP_CVAR(devastator, speed) * W_WeaponSpeedFactor(this.realowner) - (this.velocity * v_forward); if(velspeed > 0) - self.velocity = self.velocity + v_forward * min(WEP_CVAR(devastator, speedaccel) * W_WeaponSpeedFactor() * frametime, velspeed); + this.velocity = this.velocity + v_forward * min(WEP_CVAR(devastator, speedaccel) * W_WeaponSpeedFactor(this.realowner) * frametime, velspeed); // laser guided, or remote detonation - if(PS(self.realowner).m_weapon == WEP_DEVASTATOR) + .entity weaponentity = this.weaponentity_fld; + if(this.realowner.(weaponentity).m_weapon == WEP_DEVASTATOR) { - if(self == self.realowner.lastrocket) - if(!self.realowner.rl_release) - if(!PHYS_INPUT_BUTTON_ATCK2(self)) + if(this == this.realowner.(weaponentity).lastrocket) + if(!this.realowner.(weaponentity).rl_release) + if(!PHYS_INPUT_BUTTON_ATCK2(this)) if(WEP_CVAR(devastator, guiderate)) - if(time > self.pushltime) - if(!IS_DEAD(self.realowner)) + if(time > this.pushltime) + if(!IS_DEAD(this.realowner)) { f = WEP_CVAR(devastator, guideratedelay); if(f) - f = bound(0, (time - self.pushltime) / f, 1); + f = bound(0, (time - this.pushltime) / f, 1); else f = 1; - velspeed = vlen(self.velocity); + velspeed = vlen(this.velocity); - makevectors(self.realowner.v_angle); - desireddir = WarpZone_RefSys_TransformVelocity(self.realowner, self, v_forward); - desiredorigin = WarpZone_RefSys_TransformOrigin(self.realowner, self, self.realowner.origin + self.realowner.view_ofs); - olddir = normalize(self.velocity); + makevectors(this.realowner.v_angle); + desireddir = WarpZone_RefSys_TransformVelocity(this.realowner, this, v_forward); + desiredorigin = WarpZone_RefSys_TransformOrigin(this.realowner, this, this.realowner.origin + this.realowner.view_ofs); + olddir = normalize(this.velocity); // now it gets tricky... we want to move like some curve to approximate the target direction // but we are limiting the rate at which we can turn! - goal = desiredorigin + ((self.origin - desiredorigin) * desireddir + WEP_CVAR(devastator, guidegoal)) * desireddir; - newdir = W_Devastator_SteerTo(olddir, normalize(goal - self.origin), cos(WEP_CVAR(devastator, guiderate) * f * frametime * DEG2RAD)); + goal = desiredorigin + ((this.origin - desiredorigin) * desireddir + WEP_CVAR(devastator, guidegoal)) * desireddir; + newdir = W_Devastator_SteerTo(olddir, normalize(goal - this.origin), cos(WEP_CVAR(devastator, guiderate) * f * frametime * DEG2RAD)); - self.velocity = newdir * velspeed; - self.angles = vectoangles(self.velocity); + this.velocity = newdir * velspeed; + this.angles = vectoangles(this.velocity); - if(!self.count) + if(!this.count) { - Send_Effect(EFFECT_ROCKET_GUIDE, self.origin, self.velocity, 1); + Send_Effect(EFFECT_ROCKET_GUIDE, this.origin, this.velocity, 1); // TODO add a better sound here - sound(self.realowner, CH_WEAPON_B, SND_ROCKET_MODE, VOL_BASE, ATTN_NORM); - self.count = 1; + sound(this.realowner, CH_WEAPON_B, SND_ROCKET_MODE, VOL_BASE, ATTN_NORM); + this.count = 1; } } - .entity weaponentity = weaponentities[0]; // TODO: unhardcode - if(self.rl_detonate_later) - W_Devastator_RemoteExplode(weaponentity); + if(this.rl_detonate_later) + W_Devastator_RemoteExplode(this, weaponentity); } - if(self.csqcprojectile_clientanimate == 0) - UpdateCSQCProjectile(self); + if(this.csqcprojectile_clientanimate == 0) + UpdateCSQCProjectile(this); } -void W_Devastator_Touch() -{SELFPARAM(); - if(WarpZone_Projectile_Touch()) +void W_Devastator_Touch(entity this, entity toucher) +{ + if(WarpZone_Projectile_Touch(this, toucher)) { - if(wasfreed(self)) - W_Devastator_Unregister(); + if(wasfreed(this)) + W_Devastator_Unregister(this); return; } - W_Devastator_Unregister(); - W_Devastator_Explode(); + W_Devastator_Unregister(this); + W_Devastator_Explode(this, toucher); } void W_Devastator_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, vector hitloc, vector force) @@ -344,22 +355,20 @@ void W_Devastator_Damage(entity this, entity inflictor, entity attacker, float d this.angles = vectoangles(this.velocity); if(this.health <= 0) - W_PrepareExplosionByDamage(this, attacker, W_Devastator_Explode); + W_PrepareExplosionByDamage(this, attacker, W_Devastator_Explode_think); } -void W_Devastator_Attack(Weapon thiswep) -{SELFPARAM(); - entity missile; - entity flash; - - W_DecreaseAmmo(thiswep, self, WEP_CVAR(devastator, ammo)); +void W_Devastator_Attack(Weapon thiswep, entity actor, .entity weaponentity) +{ + W_DecreaseAmmo(thiswep, actor, WEP_CVAR(devastator, ammo), weaponentity); - W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(devastator, damage)); + W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(devastator, damage)); Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1); - missile = WarpZone_RefSys_SpawnSameRefSys(self); - missile.owner = missile.realowner = self; - self.lastrocket = missile; + entity missile = WarpZone_RefSys_SpawnSameRefSys(actor); + missile.weaponentity_fld = weaponentity; + missile.owner = missile.realowner = actor; + actor.(weaponentity).lastrocket = missile; if(WEP_CVAR(devastator, detonatedelay) >= 0) missile.spawnshieldtime = time + WEP_CVAR(devastator, detonatedelay); else @@ -375,7 +384,7 @@ void W_Devastator_Attack(Weapon thiswep) missile.event_damage = W_Devastator_Damage; missile.damagedbycontents = true; - missile.movetype = MOVETYPE_FLY; + set_movetype(missile, MOVETYPE_FLY); PROJECTILE_MAKETRIGGER(missile); missile.projectiledeathtype = WEP_DEVASTATOR.m_id; setsize(missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot @@ -389,59 +398,31 @@ void W_Devastator_Attack(Weapon thiswep) missile.nextthink = time; missile.cnt = time + WEP_CVAR(devastator, lifetime); missile.flags = FL_PROJECTILE; + IL_PUSH(g_projectiles, missile); + IL_PUSH(g_bot_dodge, missile); missile.missile_flags = MIF_SPLASH; CSQCProjectile(missile, WEP_CVAR(devastator, guiderate) == 0 && WEP_CVAR(devastator, speedaccel) == 0, PROJECTILE_ROCKET, false); // because of fly sound // muzzle flash for 1st person view - flash = spawn(); + entity flash = spawn(); setmodel(flash, MDL_DEVASTATOR_MUZZLEFLASH); // precision set below SUB_SetFade(flash, time, 0.1); flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; - W_AttachToShotorg(self, flash, '5 0 0'); + W_AttachToShotorg(actor, weaponentity, flash, '5 0 0'); // common properties - MUTATOR_CALLHOOK(EditProjectile, self, missile); + MUTATOR_CALLHOOK(EditProjectile, actor, missile); } -#if 0 -METHOD(Devastator, wr_aim, void(entity thiswep)) +METHOD(Devastator, wr_aim, void(entity thiswep, entity actor, .entity weaponentity)) { // aim and decide to fire if appropriate - PHYS_INPUT_BUTTON_ATCK(self) = bot_aim(self, WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false); + PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false); if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! { // decide whether to detonate rockets - entity missile, targetlist, targ; - targetlist = findchainfloat(bot_attack, true); - for(missile = world; (missile = find(missile, classname, "rocket")); ) if(missile.realowner == self) - { - targ = targetlist; - while(targ) - { - if(targ != missile.realowner && vlen(targ.origin - missile.origin) < WEP_CVAR(devastator, radius)) - { - PHYS_INPUT_BUTTON_ATCK2(self) = true; - break; - } - targ = targ.chain; - } - } - - if(PHYS_INPUT_BUTTON_ATCK2(self)) PHYS_INPUT_BUTTON_ATCK(self) = false; - } -} -#else -METHOD(Devastator, wr_aim, void(entity thiswep)) -{ - SELFPARAM(); - // aim and decide to fire if appropriate - PHYS_INPUT_BUTTON_ATCK(self) = bot_aim(self, WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), false); - if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! - { - // decide whether to detonate rockets - entity targetlist, targ; - float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; + float edgedamage, coredamage, edgeradius, recipricoledgeradius; float selfdamage, teamdamage, enemydamage; edgedamage = WEP_CVAR(devastator, edgedamage); coredamage = WEP_CVAR(devastator, damage); @@ -450,118 +431,109 @@ METHOD(Devastator, wr_aim, void(entity thiswep)) selfdamage = 0; teamdamage = 0; enemydamage = 0; - targetlist = findchainfloat(bot_attack, true); - FOREACH_ENTITY_ENT(realowner, self, + IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket", { - if(it.classname != "rocket") continue; - - targ = targetlist; - while(targ) + entity rocket = it; + IL_EACH(g_bot_targets, it.bot_attack, { - d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - it.origin); - d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000); - // count potential damage according to type of target - if(targ == self) - selfdamage = selfdamage + d; - else if(targ.team == self.team && teamplay) - teamdamage = teamdamage + d; - else if(bot_shouldattack(self, targ)) - enemydamage = enemydamage + d; - targ = targ.chain; - } + float d = vlen(it.origin + (it.mins + it.maxs) * 0.5 - rocket.origin); + d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000); + // count potential damage according to type of target + if(it == actor) + selfdamage = selfdamage + d; + else if(SAME_TEAM(it, actor)) + teamdamage = teamdamage + d; + else if(bot_shouldattack(actor, it)) + enemydamage = enemydamage + d; + }); }); float desirabledamage; desirabledamage = enemydamage; - if(time > self.invincible_finished && time > self.spawnshieldtime) + if(time > actor.invincible_finished && time > actor.spawnshieldtime) desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; - if(teamplay && self.team) + if(teamplay && actor.team) desirabledamage = desirabledamage - teamdamage; - FOREACH_ENTITY_ENT(realowner, self, + makevectors(actor.v_angle); + IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket", { - if(it.classname != "rocket") continue; - - makevectors(it.v_angle); - targ = targetlist; if(skill > 9) // normal players only do this for the target they are tracking { - targ = targetlist; - while(targ) - { - if( - (v_forward * normalize(it.origin - targ.origin)< 0.1) - && desirabledamage > 0.1*coredamage - ) PHYS_INPUT_BUTTON_ATCK2(self) = true; - targ = targ.chain; - } - } - else - { - float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000); + entity rocket = it; + IL_EACH(g_bot_targets, it.bot_attack, + { + if((v_forward * normalize(rocket.origin - it.origin) < 0.1) + && desirabledamage > 0.1 * coredamage + ) PHYS_INPUT_BUTTON_ATCK2(actor) = true; + }); + } + else + { //As the distance gets larger, a correct detonation gets near imposible //Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player - if(v_forward * normalize(it.origin - self.enemy.origin)< 0.1) - if(IS_PLAYER(self.enemy)) - if(desirabledamage >= 0.1*coredamage) - if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1)) - PHYS_INPUT_BUTTON_ATCK2(self) = true; - // dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n"); - } + if((v_forward * normalize(it.origin - actor.enemy.origin) < 0.1) + && IS_PLAYER(actor.enemy) + && (desirabledamage >= 0.1 * coredamage) + ) + { + float distance = bound(300, vlen(actor.origin - actor.enemy.origin), 30000); + if(random() / distance * 300 > frametime * bound(0, (10 - skill) * 0.2, 1)) + PHYS_INPUT_BUTTON_ATCK2(actor) = true; + } + } }); // if we would be doing at X percent of the core damage, detonate it // but don't fire a new shot at the same time! if(desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events - PHYS_INPUT_BUTTON_ATCK2(self) = true; - if((skill > 6.5) && (selfdamage > self.health)) - PHYS_INPUT_BUTTON_ATCK2(self) = false; - //if(PHYS_INPUT_BUTTON_ATCK2(self) == true) + PHYS_INPUT_BUTTON_ATCK2(actor) = true; + if((skill > 6.5) && (selfdamage > actor.health)) + PHYS_INPUT_BUTTON_ATCK2(actor) = false; + //if(PHYS_INPUT_BUTTON_ATCK2(actor) == true) // dprint(ftos(desirabledamage),"\n"); - if(PHYS_INPUT_BUTTON_ATCK2(self)) PHYS_INPUT_BUTTON_ATCK(self) = false; + if(PHYS_INPUT_BUTTON_ATCK2(actor)) PHYS_INPUT_BUTTON_ATCK(actor) = false; } } -#endif + METHOD(Devastator, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire)) { - if(WEP_CVAR(devastator, reload_ammo) && actor.clip_load < WEP_CVAR(devastator, ammo)) { // forced reload + if(WEP_CVAR(devastator, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(devastator, ammo)) { // forced reload thiswep.wr_reload(thiswep, actor, weaponentity); } else { if(fire & 1) { - if(actor.rl_release || WEP_CVAR(devastator, guidestop)) + if(actor.(weaponentity).rl_release || WEP_CVAR(devastator, guidestop)) if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(devastator, refire))) { - W_Devastator_Attack(thiswep); + W_Devastator_Attack(thiswep, actor, weaponentity); weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready); - actor.rl_release = 0; + actor.(weaponentity).rl_release = 0; } } else - actor.rl_release = 1; + actor.(weaponentity).rl_release = 1; if(fire & 2) - if(PS(actor).m_switchweapon == WEP_DEVASTATOR) + if(actor.(weaponentity).m_switchweapon == WEP_DEVASTATOR) { - entity rock; bool rockfound = false; - for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == actor) + IL_EACH(g_projectiles, it.realowner == actor && it.classname == "rocket", { - if(!rock.rl_detonate_later) + if(!it.rl_detonate_later) { - rock.rl_detonate_later = true; + it.rl_detonate_later = true; rockfound = true; } - } + }); if(rockfound) sound(actor, CH_WEAPON_B, SND_ROCKET_DET, VOL_BASE, ATTN_NORM); } } } -METHOD(Devastator, wr_setup, void(entity thiswep)) +METHOD(Devastator, wr_setup, void(entity thiswep, entity actor, .entity weaponentity)) { - SELFPARAM(); - self.rl_release = 1; + actor.(weaponentity).rl_release = 1; } -METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor)) +METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity)) { #if 0 // don't switch while guiding a missile @@ -570,7 +542,7 @@ METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor)) ammo_amount = false; if(WEP_CVAR(devastator, reload_ammo)) { - if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo) && actor.(weapon_load[WEP_DEVASTATOR.m_id]) < WEP_CVAR(devastator, ammo)) + if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo) && actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) < WEP_CVAR(devastator, ammo)) ammo_amount = true; } else if(actor.(thiswep.ammo_field) < WEP_CVAR(devastator, ammo)) @@ -587,30 +559,32 @@ METHOD(Devastator, wr_checkammo1, bool(entity thiswep, entity actor)) else { ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(devastator, ammo); - ammo_amount += actor.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo); + ammo_amount += actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo); LOG_INFOF("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s\n", actor.rl_release, actor.(thiswep.ammo_field), WEP_CVAR(devastator, ammo), (ammo_amount ? "TRUE" : "FALSE")); return ammo_amount; } #else float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(devastator, ammo); - ammo_amount += actor.(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo); + ammo_amount += actor.(weaponentity).(weapon_load[WEP_DEVASTATOR.m_id]) >= WEP_CVAR(devastator, ammo); return ammo_amount; #endif } -METHOD(Devastator, wr_checkammo2, bool(entity thiswep, entity actor)) +METHOD(Devastator, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity)) { return false; } -METHOD(Devastator, wr_resetplayer, void(entity thiswep)) +METHOD(Devastator, wr_resetplayer, void(entity thiswep, entity actor)) { - SELFPARAM(); - self.lastrocket = NULL; // stop rocket guiding, no revenge from the grave! - self.rl_release = 0; + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + actor.(weaponentity).lastrocket = NULL; // stop rocket guiding, no revenge from the grave! + actor.(weaponentity).rl_release = 0; + } } METHOD(Devastator, wr_reload, void(entity thiswep, entity actor, .entity weaponentity)) { - SELFPARAM(); - W_Reload(self, WEP_CVAR(devastator, ammo), SND_RELOAD); + W_Reload(actor, weaponentity, WEP_CVAR(devastator, ammo), SND_RELOAD); } METHOD(Devastator, wr_suicidemessage, Notification(entity thiswep)) { @@ -627,14 +601,13 @@ METHOD(Devastator, wr_killmessage, Notification(entity thiswep)) #endif #ifdef CSQC -METHOD(Devastator, wr_impacteffect, void(entity thiswep)) +METHOD(Devastator, wr_impacteffect, void(entity thiswep, entity actor)) { - SELFPARAM(); vector org2; org2 = w_org + w_backoff * 12; pointparticles(EFFECT_ROCKET_EXPLODE, org2, '0 0 0', 1); if(!w_issilent) - sound(self, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTN_NORM); + sound(actor, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTN_NORM); } #endif