From: Samual Lenks Date: Sun, 8 Dec 2013 04:34:20 +0000 (-0500) Subject: Remove some files that got left over by merge accidentally X-Git-Tag: xonotic-v0.8.0~152^2~304 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=9d656e2e2c32a525ff8d5b21c2e465f2eccf9e1d;p=xonotic%2Fxonotic-data.pk3dir.git Remove some files that got left over by merge accidentally --- diff --git a/qcsrc/server/cl_weapons.qc b/qcsrc/server/cl_weapons.qc deleted file mode 100644 index 88397a880..000000000 --- a/qcsrc/server/cl_weapons.qc +++ /dev/null @@ -1,537 +0,0 @@ -void W_TriggerReload() -{ - weapon_action(self.weapon, WR_RELOAD); -} - -// switch between weapons -void W_SwitchWeapon(float imp) -{ - if (self.switchweapon != imp) - { - if (client_hasweapon(self, imp, TRUE, TRUE)) - W_SwitchWeapon_Force(self, imp); - else - self.selectweapon = imp; // update selectweapon ANYWAY - } - else - { - W_TriggerReload(); - } -} - -.float weaponcomplainindex; -float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing) -{ - // We cannot tokenize in this function, as GiveItems calls this - // function. Thus we must use car/cdr. - float weaponwant, first_valid, prev_valid, switchtonext, switchtolast, c; - string rest; - switchtonext = switchtolast = 0; - first_valid = prev_valid = 0; - float weaponcur; - - if(skipmissing || pl.selectweapon == 0) - weaponcur = pl.switchweapon; - else - weaponcur = pl.selectweapon; - - if(dir == 0) - switchtonext = 1; - - c = 0; - - rest = weaponorder; - while(rest != "") - { - weaponwant = stof(car(rest)); rest = cdr(rest); - if(imp >= 0) - if((get_weaponinfo(weaponwant)).impulse != imp) - continue; - - ++c; - - if(!skipmissing || client_hasweapon(pl, weaponwant, TRUE, FALSE)) - { - if(switchtonext) - return weaponwant; - if(!first_valid) - first_valid = weaponwant; - if(weaponwant == weaponcur) - { - if(dir >= 0) - switchtonext = 1; - else if(prev_valid) - return prev_valid; - else - switchtolast = 1; - } - prev_valid = weaponwant; - } - } - if(first_valid) - { - if(switchtolast) - return prev_valid; - else - return first_valid; - } - // complain (but only for one weapon on the button that has been pressed) - if(complain) - { - self.weaponcomplainindex += 1; - c = mod(self.weaponcomplainindex, c) + 1; - rest = weaponorder; - while(rest != "") - { - weaponwant = stof(car(rest)); rest = cdr(rest); - if(imp >= 0) - if((get_weaponinfo(weaponwant)).impulse != imp) - continue; - - --c; - if(c == 0) - { - client_hasweapon(pl, weaponwant, TRUE, TRUE); - break; - } - } - } - return 0; -} - -void W_CycleWeapon(string weaponorder, float dir) -{ - float w; - w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, TRUE); - if(w > 0) - W_SwitchWeapon(w); -} - -void W_NextWeaponOnImpulse(float imp) -{ - float w; - w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0)); - if(w > 0) - W_SwitchWeapon(w); -} - -// next weapon -void W_NextWeapon(float list) -{ - if(list == 0) - W_CycleWeapon(weaponorder_byid, -1); - else if(list == 1) - W_CycleWeapon(self.weaponorder_byimpulse, -1); - else if(list == 2) - W_CycleWeapon(self.cvar_cl_weaponpriority, -1); -} - -// prev weapon -void W_PreviousWeapon(float list) -{ - if(list == 0) - W_CycleWeapon(weaponorder_byid, +1); - else if(list == 1) - W_CycleWeapon(self.weaponorder_byimpulse, +1); - else if(list == 2) - W_CycleWeapon(self.cvar_cl_weaponpriority, +1); -} - -// previously used if exists and has ammo, (second) best otherwise -void W_LastWeapon() -{ - if(client_hasweapon(self, self.cnt, TRUE, FALSE)) - W_SwitchWeapon(self.cnt); - else - W_SwitchToOtherWeapon(self); -} - -float w_getbestweapon(entity e) -{ - return W_GetCycleWeapon(e, e.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE); -} - -// generic weapons table -// TODO should they be macros instead? -float weapon_action(float wpn, float wrequest) -{ - return (get_weaponinfo(wpn)).weapon_func(wrequest); -} - -.float savenextthink; -void thrown_wep_think() -{ - self.owner = world; - float timeleft = self.savenextthink - time; - if(timeleft > 1) - SUB_SetFade(self, self.savenextthink - 1, 1); - else if(timeleft > 0) - SUB_SetFade(self, time, timeleft); - else - SUB_VanishOrRemove(self); -} - -// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count -string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo) -{ - entity oldself, wep; - float wa, thisammo, i, j; - string s; - var .float ammofield; - - wep = spawn(); - - setorigin(wep, org); - wep.classname = "droppedweapon"; - wep.velocity = velo; - wep.owner = wep.enemy = own; - wep.flags |= FL_TOSSED; - wep.colormap = own.colormap; - - if(WepSet_FromWeapon(wpn) & WEPSET_SUPERWEAPONS) - { - if(own.items & IT_UNLIMITED_SUPERWEAPONS) - { - wep.superweapons_finished = time + autocvar_g_balance_superweapons_time; - } - else - { - float superweapons = 1; - for(i = WEP_FIRST; i <= WEP_LAST; ++i) - if(WepSet_FromWeapon(i) & WEPSET_SUPERWEAPONS) - if(own.weapons & WepSet_FromWeapon(i)) - ++superweapons; - if(superweapons <= 1) - { - wep.superweapons_finished = own.superweapons_finished; - own.superweapons_finished = 0; - } - else - { - float timeleft = own.superweapons_finished - time; - float weptimeleft = timeleft / superweapons; - wep.superweapons_finished = time + weptimeleft; - own.superweapons_finished -= weptimeleft; - } - } - } - - wa = W_AmmoItemCode(wpn); - if(wa == 0) - { - oldself = self; - self = wep; - weapon_defaultspawnfunc(wpn); - self = oldself; - if(startitem_failed) - return string_null; - wep.glowmod = own.weaponentity_glowmod; - wep.think = thrown_wep_think; - wep.savenextthink = wep.nextthink; - wep.nextthink = min(wep.nextthink, time + 0.5); - wep.pickup_anyway = TRUE; // these are ALWAYS pickable - return ""; - } - else - { - s = ""; - oldself = self; - self = wep; - weapon_defaultspawnfunc(wpn); - self = oldself; - if(startitem_failed) - return string_null; - if(doreduce && g_weapon_stay == 2) - { - for(i = 0, j = 1; i < 24; ++i, j *= 2) - { - if(wa & j) - { - ammofield = Item_CounterField(j); - - // if our weapon is loaded, give its load back to the player - if(self.(weapon_load[self.weapon]) > 0) - { - own.ammofield += self.(weapon_load[self.weapon]); - self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading - } - - wep.ammofield = 0; - } - } - } - else if(doreduce) - { - for(i = 0, j = 1; i < 24; ++i, j *= 2) - { - if(wa & j) - { - ammofield = Item_CounterField(j); - - // if our weapon is loaded, give its load back to the player - if(self.(weapon_load[self.weapon]) > 0) - { - own.ammofield += self.(weapon_load[self.weapon]); - self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading - } - - thisammo = min(own.ammofield, wep.ammofield); - wep.ammofield = thisammo; - own.ammofield -= thisammo; - s = strcat(s, " and ", ftos(thisammo), " ", Item_CounterFieldName(j)); - } - } - s = substring(s, 5, -1); - } - wep.glowmod = own.weaponentity_glowmod; - wep.think = thrown_wep_think; - wep.savenextthink = wep.nextthink; - wep.nextthink = min(wep.nextthink, time + 0.5); - wep.pickup_anyway = TRUE; // these are ALWAYS pickable - - return s; - } -} - -float W_IsWeaponThrowable(float w) -{ - float wa; - - if (!autocvar_g_pickup_items) - return 0; - if (g_weaponarena) - return 0; - if (g_cts) - return 0; - if (g_nexball && w == WEP_GRENADE_LAUNCHER) - return 0; - if(w == 0) - return 0; - - wa = W_AmmoItemCode(w); - if(start_weapons & WepSet_FromWeapon(w)) - { - // start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo) - if(start_items & IT_UNLIMITED_WEAPON_AMMO) - return 0; - if(wa == 0) - return 0; - } - - return 1; -} - -// toss current weapon -void W_ThrowWeapon(vector velo, vector delta, float doreduce) -{ - float w; - string a; - - w = self.weapon; - if (w == 0) - return; // just in case - if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon)) - return; - if(!autocvar_g_weapon_throwable) - return; - if(self.weaponentity.state != WS_READY) - return; - if(!W_IsWeaponThrowable(w)) - return; - - if(!(self.weapons & WepSet_FromWeapon(w))) - return; - self.weapons &= ~WepSet_FromWeapon(w); - - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo); - - if (!a) return; - Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_WEAPON_DROP, a, w); -} - -float forbidWeaponUse() -{ - if(time < game_starttime && !autocvar_sv_ready_restart_after_countdown) - return 1; - if(round_handler_IsActive() && !round_handler_IsRoundStarted()) - return 1; - if(self.player_blocked) - return 1; - if(self.freezetag_frozen) - return 1; - return 0; -} - -void W_WeaponFrame() -{ - vector fo, ri, up; - - if (frametime) - self.weapon_frametime = frametime; - - if (!self.weaponentity || self.health < 1) - return; // Dead player can't use weapons and injure impulse commands - - if(forbidWeaponUse()) - if(self.weaponentity.state != WS_CLEAR) - { - w_ready(); - return; - } - - if(!self.switchweapon) - { - self.weapon = 0; - self.switchingweapon = 0; - self.weaponentity.state = WS_CLEAR; - self.weaponname = ""; - self.items &= ~IT_AMMO; - return; - } - - makevectors(self.v_angle); - fo = v_forward; // save them in case the weapon think functions change it - ri = v_right; - up = v_up; - - // Change weapon - if (self.weapon != self.switchweapon) - { - if (self.weaponentity.state == WS_CLEAR) - { - // end switching! - self.switchingweapon = self.switchweapon; - - entity newwep = get_weaponinfo(self.switchweapon); - - //setanim(self, self.anim_draw, FALSE, TRUE, TRUE); - self.weaponentity.state = WS_RAISE; - weapon_action(self.switchweapon, WR_SETUP); - - // set our clip load to the load of the weapon we switched to, if it's reloadable - if(newwep.spawnflags & WEP_FLAG_RELOADABLE && cvar(strcat("g_balance_", newwep.netname, "_reload_ammo"))) // prevent accessing undefined cvars - { - self.clip_load = self.(weapon_load[self.switchweapon]); - self.clip_size = cvar(strcat("g_balance_", newwep.netname, "_reload_ammo")); - } - else - self.clip_load = self.clip_size = 0; - - // VorteX: add player model weapon select frame here - // setcustomframe(PlayerWeaponRaise); - weapon_thinkf(WFRAME_IDLE, cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname)), w_ready); - //print(sprintf("W_WeaponFrame(): cvar: %s, value: %f\n", sprintf("g_balance_%s_switchdelay_raise", newwep.netname), cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname)))); - weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, '0 0 0'); - } - else if (self.weaponentity.state == WS_DROP) - { - // in dropping phase we can switch at any time - self.switchingweapon = self.switchweapon; - } - else if (self.weaponentity.state == WS_READY) - { - // start switching! - self.switchingweapon = self.switchweapon; - - entity oldwep = get_weaponinfo(self.weapon); - -#ifndef INDEPENDENT_ATTACK_FINISHED - if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5) - { -#endif - sound (self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTEN_NORM); - self.weaponentity.state = WS_DROP; - // set up weapon switch think in the future, and start drop anim - weapon_thinkf(WFRAME_DONTCHANGE, cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname)), w_clear); - //print(sprintf("W_WeaponFrame(): cvar: %s, value: %f\n", sprintf("g_balance_%s_switchdelay_drop", oldwep.netname), cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname)))); - weapon_boblayer1(PLAYER_WEAPONSELECTION_SPEED, PLAYER_WEAPONSELECTION_RANGE); -#ifndef INDEPENDENT_ATTACK_FINISHED - } -#endif - } - } - - // LordHavoc: network timing test code - //if (self.button0) - // print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(self)), " >= ", ftos(self.weapon_nextthink), "\n"); - - float w; - w = self.weapon; - - // call the think code which may fire the weapon - // and do so multiple times to resolve framerate dependency issues if the - // server framerate is very low and the weapon fire rate very high - float c; - c = 0; - while (c < W_TICSPERFRAME) - { - c = c + 1; - if(w && !(self.weapons & WepSet_FromWeapon(w))) - { - if(self.weapon == self.switchweapon) - W_SwitchWeapon_Force(self, w_getbestweapon(self)); - w = 0; - } - - v_forward = fo; - v_right = ri; - v_up = up; - - if(w) - weapon_action(self.weapon, WR_THINK); - else - weapon_action(self.weapon, WR_GONETHINK); - - if (time + self.weapon_frametime * 0.5 >= self.weapon_nextthink) - { - if(self.weapon_think) - { - v_forward = fo; - v_right = ri; - v_up = up; - self.weapon_think(); - } - else - bprint("\{1}^1ERROR: undefined weapon think function for ", self.netname, "\n"); - } - } - - // don't let attack_finished fall behind when not firing (must be after weapon_setup calls!) - //if (ATTACK_FINISHED(self) < time) - // ATTACK_FINISHED(self) = time; - - //if (self.weapon_nextthink < time) - // self.weapon_nextthink = time; - - // update currentammo incase it has changed -#if 0 - if (self.items & IT_CELLS) - self.currentammo = self.ammo_cells; - else if (self.items & IT_ROCKETS) - self.currentammo = self.ammo_rockets; - else if (self.items & IT_NAILS) - self.currentammo = self.ammo_nails; - else if (self.items & IT_SHELLS) - self.currentammo = self.ammo_shells; - else - self.currentammo = 1; -#endif -} - -string W_Apply_Weaponreplace(string in) -{ - float n = tokenize_console(in); - string out = ""; - float i; - for(i = 0; i < n; ++i) - { - string s = argv(i); - string r = cvar_string(strcat("g_weaponreplace_", s)); - if(r == "") - out = strcat(out, " ", s); - else if(r != "0") - out = strcat(out, " ", r); - } - return substring(out, 1, -1); -} diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc deleted file mode 100644 index f7ad7583d..000000000 --- a/qcsrc/server/w_crylink.qc +++ /dev/null @@ -1,727 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ CRYLINK, -/* function */ w_crylink, -/* ammotype */ IT_CELLS, -/* impulse */ 6, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* model */ "crylink", -/* shortname */ "crylink", -/* fullname */ _("Crylink") -); -#else -#ifdef SVQC -.float gravity; -.float crylink_waitrelease; -.entity crylink_lastgroup; - -.entity queuenext; -.entity queueprev; - -void W_Crylink_CheckLinks(entity e) -{ - float i; - entity p; - - if(e == world) - error("W_Crylink_CheckLinks: entity is world"); - if(e.classname != "spike" || wasfreed(e)) - error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e))); - - p = e; - for(i = 0; i < 1000; ++i) - { - if(p.queuenext.queueprev != p || p.queueprev.queuenext != p) - error("W_Crylink_CheckLinks: queue is inconsistent"); - p = p.queuenext; - if(p == e) - break; - } - if(i >= 1000) - error("W_Crylink_CheckLinks: infinite chain"); -} - -void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next) -{ - W_Crylink_CheckLinks(next); - if(me == own.crylink_lastgroup) - own.crylink_lastgroup = ((me == next) ? world : next); - prev.queuenext = next; - next.queueprev = prev; - me.classname = "spike_oktoremove"; - if(me != next) - W_Crylink_CheckLinks(next); -} - -void W_Crylink_Dequeue(entity e) -{ - W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext); -} - -void W_Crylink_Reset(void) -{ - W_Crylink_Dequeue(self); - remove(self); -} - -// force projectile to explode -void W_Crylink_LinkExplode (entity e, entity e2) -{ - float a; - - if(e == e2) - return; - - a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1); - - if(e == e.realowner.crylink_lastgroup) - e.realowner.crylink_lastgroup = world; - - if(e.projectiledeathtype & HITTYPE_SECONDARY) - RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_damage * a, autocvar_g_balance_crylink_secondary_edgedamage * a, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * a, e.projectiledeathtype, other); - else - RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other); - - W_Crylink_LinkExplode(e.queuenext, e2); - - e.classname = "spike_oktoremove"; - remove (e); -} - -// adjust towards center -// returns the origin where they will meet... and the time till the meeting is -// stored in w_crylink_linkjoin_time. -// could possibly network this origin and time, and display a special particle -// effect when projectiles meet there :P -// jspeed: joining speed (calculate this as join spread * initial speed) -float w_crylink_linkjoin_time; -vector W_Crylink_LinkJoin(entity e, float jspeed) -{ - vector avg_origin, avg_velocity; - vector targ_origin; - float avg_dist, n; - entity p; - - // FIXME remove this debug code - W_Crylink_CheckLinks(e); - - w_crylink_linkjoin_time = 0; - - avg_origin = e.origin; - avg_velocity = e.velocity; - n = 1; - for(p = e; (p = p.queuenext) != e; ) - { - avg_origin += WarpZone_RefSys_TransformOrigin(p, e, p.origin); - avg_velocity += WarpZone_RefSys_TransformVelocity(p, e, p.velocity); - ++n; - } - avg_origin *= (1.0 / n); - avg_velocity *= (1.0 / n); - - if(n < 2) - return avg_origin; // nothing to do - - // yes, mathematically we can do this in ONE step, but beware of 32bit floats... - avg_dist = pow(vlen(e.origin - avg_origin), 2); - for(p = e; (p = p.queuenext) != e; ) - avg_dist += pow(vlen(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_origin), 2); - avg_dist *= (1.0 / n); - avg_dist = sqrt(avg_dist); - - if(avg_dist == 0) - return avg_origin; // no change needed - - if(jspeed == 0) - { - e.velocity = avg_velocity; - UpdateCSQCProjectile(e); - for(p = e; (p = p.queuenext) != e; ) - { - p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity); - UpdateCSQCProjectile(p); - } - targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE - } - else - { - w_crylink_linkjoin_time = avg_dist / jspeed; - targ_origin = avg_origin + w_crylink_linkjoin_time * avg_velocity; - - e.velocity = (targ_origin - e.origin) * (1.0 / w_crylink_linkjoin_time); - UpdateCSQCProjectile(e); - for(p = e; (p = p.queuenext) != e; ) - { - p.velocity = WarpZone_RefSys_TransformVelocity(e, p, (targ_origin - WarpZone_RefSys_TransformOrigin(p, e, p.origin)) * (1.0 / w_crylink_linkjoin_time)); - UpdateCSQCProjectile(p); - } - - // analysis: - // jspeed -> +infinity: - // w_crylink_linkjoin_time -> +0 - // targ_origin -> avg_origin - // p->velocity -> HUEG towards center - // jspeed -> 0: - // w_crylink_linkjoin_time -> +/- infinity - // targ_origin -> avg_velocity * +/- infinity - // p->velocity -> avg_velocity - // jspeed -> -infinity: - // w_crylink_linkjoin_time -> -0 - // targ_origin -> avg_origin - // p->velocity -> HUEG away from center - } - - W_Crylink_CheckLinks(e); - - return targ_origin; -} - -void W_Crylink_LinkJoinEffect_Think() -{ - // is there at least 2 projectiles very close? - entity e, p; - float n; - e = self.owner.crylink_lastgroup; - n = 0; - if(e) - { - if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime) - ++n; - for(p = e; (p = p.queuenext) != e; ) - { - if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime) - ++n; - } - if(n >= 2) - { - if(e.projectiledeathtype & HITTYPE_SECONDARY) - { - if(autocvar_g_balance_crylink_secondary_joinexplode) - { - n = n / autocvar_g_balance_crylink_secondary_shots; - RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_joinexplode_damage * n, - autocvar_g_balance_crylink_secondary_joinexplode_edgedamage * n, - autocvar_g_balance_crylink_secondary_joinexplode_radius * n, e.realowner, - autocvar_g_balance_crylink_secondary_joinexplode_force * n, e.projectiledeathtype, other); - - pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n); - } - } - else - { - if(autocvar_g_balance_crylink_primary_joinexplode) - { - n = n / autocvar_g_balance_crylink_primary_shots; - RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_joinexplode_damage * n, - autocvar_g_balance_crylink_primary_joinexplode_edgedamage * n, - autocvar_g_balance_crylink_primary_joinexplode_radius * n, e.realowner, - autocvar_g_balance_crylink_primary_joinexplode_force * n, e.projectiledeathtype, other); - - pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n); - } - } - } - } - remove(self); -} - -float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad) -{ - entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE); - float hit_friendly = 0; - float hit_enemy = 0; - - while(head) - { - if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO)) - { - if(SAME_TEAM(head, projectile.realowner)) - ++hit_friendly; - else - ++hit_enemy; - } - - head = head.chain; - } - - return (hit_enemy ? FALSE : hit_friendly); -} - -// NO bounce protection, as bounces are limited! -void W_Crylink_Touch (void) -{ - float finalhit; - float f; - PROJECTILE_TOUCH; - - float a; - a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1); - - finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO)); - if(finalhit) - f = 1; - else - f = autocvar_g_balance_crylink_primary_bouncedamagefactor; - if(a) - f *= a; - - float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_primary_damage * f, autocvar_g_balance_crylink_primary_edgedamage * f, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other); - - if(totaldamage && ((autocvar_g_balance_crylink_primary_linkexplode == 2) || ((autocvar_g_balance_crylink_primary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_primary_radius)))) - { - if(self == self.realowner.crylink_lastgroup) - self.realowner.crylink_lastgroup = world; - W_Crylink_LinkExplode(self.queuenext, self); - self.classname = "spike_oktoremove"; - remove (self); - return; - } - else if(finalhit) - { - // just unlink - W_Crylink_Dequeue(self); - remove(self); - return; - } - self.cnt = self.cnt - 1; - self.angles = vectoangles(self.velocity); - self.owner = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - // commented out as it causes a little hitch... - //if(proj.cnt == 0) - // CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE); -} - -void W_Crylink_Touch2 (void) -{ - float finalhit; - float f; - PROJECTILE_TOUCH; - - float a; - a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1); - - finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO)); - if(finalhit) - f = 1; - else - f = autocvar_g_balance_crylink_secondary_bouncedamagefactor; - if(a) - f *= a; - - float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_secondary_damage * f, autocvar_g_balance_crylink_secondary_edgedamage * f, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other); - - if(totaldamage && ((autocvar_g_balance_crylink_secondary_linkexplode == 2) || ((autocvar_g_balance_crylink_secondary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_secondary_radius)))) - { - if(self == self.realowner.crylink_lastgroup) - self.realowner.crylink_lastgroup = world; - W_Crylink_LinkExplode(self.queuenext, self); - self.classname = "spike_oktoremove"; - remove (self); - return; - } - else if(finalhit) - { - // just unlink - W_Crylink_Dequeue(self); - remove(self); - return; - } - self.cnt = self.cnt - 1; - self.angles = vectoangles(self.velocity); - self.owner = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - // commented out as it causes a little hitch... - //if(proj.cnt == 0) - // CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE); -} - -void W_Crylink_Fadethink (void) -{ - W_Crylink_Dequeue(self); - remove(self); -} - -void W_Crylink_Attack (void) -{ - float counter, shots; - entity proj, prevproj, firstproj; - vector s; - vector forward, right, up; - float maxdmg; - - W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_reload_ammo); - - maxdmg = autocvar_g_balance_crylink_primary_damage*autocvar_g_balance_crylink_primary_shots; - maxdmg *= 1 + autocvar_g_balance_crylink_primary_bouncedamagefactor * autocvar_g_balance_crylink_primary_bounces; - if(autocvar_g_balance_crylink_primary_joinexplode) - maxdmg += autocvar_g_balance_crylink_primary_joinexplode_damage; - - W_SetupShot (self, FALSE, 2, "weapons/crylink_fire.wav", CH_WEAPON_A, maxdmg); - forward = v_forward; - right = v_right; - up = v_up; - - shots = autocvar_g_balance_crylink_primary_shots; - pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); - proj = prevproj = firstproj = world; - for(counter = 0; counter < shots; ++counter) - { - proj = spawn (); - proj.reset = W_Crylink_Reset; - proj.realowner = proj.owner = self; - proj.classname = "spike"; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = autocvar_g_balance_crylink_primary_damage; - if(shots == 1) { - proj.queuenext = proj; - proj.queueprev = proj; - } - else if(counter == 0) { // first projectile, store in firstproj for now - firstproj = proj; - } - else if(counter == shots - 1) { // last projectile, link up with first projectile - prevproj.queuenext = proj; - firstproj.queueprev = proj; - proj.queuenext = firstproj; - proj.queueprev = prevproj; - } - else { // else link up with previous projectile - prevproj.queuenext = proj; - proj.queueprev = prevproj; - } - - prevproj = proj; - - proj.movetype = MOVETYPE_BOUNCEMISSILE; - PROJECTILE_MAKETRIGGER(proj); - proj.projectiledeathtype = WEP_CRYLINK; - //proj.gravity = 0.001; - - setorigin (proj, w_shotorg); - setsize(proj, '0 0 0', '0 0 0'); - - - s = '0 0 0'; - if (counter == 0) - s = '0 0 0'; - else - { - makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); - s_y = v_forward_x; - s_z = v_forward_y; - } - s = s * autocvar_g_balance_crylink_primary_spread * g_weaponspreadfactor; - W_SetupProjectileVelocityEx(proj, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_crylink_primary_speed, 0, 0, 0, FALSE); - proj.touch = W_Crylink_Touch; - - proj.think = W_Crylink_Fadethink; - if(counter == 0) - { - proj.fade_time = time + autocvar_g_balance_crylink_primary_middle_lifetime; - proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_middle_fadetime; - proj.nextthink = time + autocvar_g_balance_crylink_primary_middle_lifetime + autocvar_g_balance_crylink_primary_middle_fadetime; - } - else - { - proj.fade_time = time + autocvar_g_balance_crylink_primary_other_lifetime; - proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_other_fadetime; - proj.nextthink = time + autocvar_g_balance_crylink_primary_other_lifetime + autocvar_g_balance_crylink_primary_other_fadetime; - } - proj.teleport_time = time + autocvar_g_balance_crylink_primary_joindelay; - proj.cnt = autocvar_g_balance_crylink_primary_bounces; - //proj.scale = 1 + 1 * proj.cnt; - - proj.angles = vectoangles (proj.velocity); - - //proj.glow_size = 20; - - proj.flags = FL_PROJECTILE; - proj.missile_flags = MIF_SPLASH; - - CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); - - other = proj; MUTATOR_CALLHOOK(EditProjectile); - } - if(autocvar_g_balance_crylink_primary_joinspread != 0) - { - self.crylink_lastgroup = proj; - W_Crylink_CheckLinks(proj); - self.crylink_waitrelease = 1; - } -} - -void W_Crylink_Attack2 (void) -{ - float counter, shots; - entity proj, prevproj, firstproj; - vector s; - vector forward, right, up; - float maxdmg; - - W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_secondary_ammo, autocvar_g_balance_crylink_reload_ammo); - - maxdmg = autocvar_g_balance_crylink_secondary_damage*autocvar_g_balance_crylink_secondary_shots; - maxdmg *= 1 + autocvar_g_balance_crylink_secondary_bouncedamagefactor * autocvar_g_balance_crylink_secondary_bounces; - if(autocvar_g_balance_crylink_secondary_joinexplode) - maxdmg += autocvar_g_balance_crylink_secondary_joinexplode_damage; - - W_SetupShot (self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg); - forward = v_forward; - right = v_right; - up = v_up; - - shots = autocvar_g_balance_crylink_secondary_shots; - pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots); - proj = prevproj = firstproj = world; - for(counter = 0; counter < shots; ++counter) - { - proj = spawn (); - proj.reset = W_Crylink_Reset; - proj.realowner = proj.owner = self; - proj.classname = "spike"; - proj.bot_dodge = TRUE; - proj.bot_dodgerating = autocvar_g_balance_crylink_secondary_damage; - if(shots == 1) { - proj.queuenext = proj; - proj.queueprev = proj; - } - else if(counter == 0) { // first projectile, store in firstproj for now - firstproj = proj; - } - else if(counter == shots - 1) { // last projectile, link up with first projectile - prevproj.queuenext = proj; - firstproj.queueprev = proj; - proj.queuenext = firstproj; - proj.queueprev = prevproj; - } - else { // else link up with previous projectile - prevproj.queuenext = proj; - proj.queueprev = prevproj; - } - - prevproj = proj; - - proj.movetype = MOVETYPE_BOUNCEMISSILE; - PROJECTILE_MAKETRIGGER(proj); - proj.projectiledeathtype = WEP_CRYLINK | HITTYPE_SECONDARY; - //proj.gravity = 0.001; - - setorigin (proj, w_shotorg); - setsize(proj, '0 0 0', '0 0 0'); - - if(autocvar_g_balance_crylink_secondary_spreadtype == 1) - { - s = '0 0 0'; - if (counter == 0) - s = '0 0 0'; - else - { - makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1))); - s_y = v_forward_x; - s_z = v_forward_y; - } - s = s * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor; - s = w_shotdir + right * s_y + up * s_z; - } - else - { - s = (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor); - } - - W_SetupProjectileVelocityEx(proj, s, v_up, autocvar_g_balance_crylink_secondary_speed, 0, 0, 0, FALSE); - proj.touch = W_Crylink_Touch2; - proj.think = W_Crylink_Fadethink; - if(counter == (shots - 1) / 2) - { - proj.fade_time = time + autocvar_g_balance_crylink_secondary_middle_lifetime; - proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_middle_fadetime; - proj.nextthink = time + autocvar_g_balance_crylink_secondary_middle_lifetime + autocvar_g_balance_crylink_secondary_middle_fadetime; - } - else - { - proj.fade_time = time + autocvar_g_balance_crylink_secondary_line_lifetime; - proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_line_fadetime; - proj.nextthink = time + autocvar_g_balance_crylink_secondary_line_lifetime + autocvar_g_balance_crylink_secondary_line_fadetime; - } - proj.teleport_time = time + autocvar_g_balance_crylink_secondary_joindelay; - proj.cnt = autocvar_g_balance_crylink_secondary_bounces; - //proj.scale = 1 + 1 * proj.cnt; - - proj.angles = vectoangles (proj.velocity); - - //proj.glow_size = 20; - - proj.flags = FL_PROJECTILE; - proj.missile_flags = MIF_SPLASH; - - CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE); - - other = proj; MUTATOR_CALLHOOK(EditProjectile); - } - if(autocvar_g_balance_crylink_secondary_joinspread != 0) - { - self.crylink_lastgroup = proj; - W_Crylink_CheckLinks(proj); - self.crylink_waitrelease = 2; - } -} - -void spawnfunc_weapon_crylink (void) -{ - weapon_defaultspawnfunc(WEP_CRYLINK); -} - -float w_crylink(float req) -{ - float ammo_amount; - if (req == WR_AIM) - { - if (random() < 0.10) - self.BUTTON_ATCK = bot_aim(autocvar_g_balance_crylink_primary_speed, 0, autocvar_g_balance_crylink_primary_middle_lifetime, FALSE); - else - self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_crylink_secondary_speed, 0, autocvar_g_balance_crylink_secondary_middle_lifetime, FALSE); - } - else if (req == WR_THINK) - { - if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo)) // forced reload - weapon_action(self.weapon, WR_RELOAD); - - if (self.BUTTON_ATCK) - { - if (self.crylink_waitrelease != 1) - if (weapon_prepareattack(0, autocvar_g_balance_crylink_primary_refire)) - { - W_Crylink_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_crylink_primary_animtime, w_ready); - } - } - - if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary) - { - if (self.crylink_waitrelease != 2) - if (weapon_prepareattack(1, autocvar_g_balance_crylink_secondary_refire)) - { - W_Crylink_Attack2(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_crylink_secondary_animtime, w_ready); - } - } - - if ((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2)) - { - if (!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time) - { - // fired and released now! - if(self.crylink_lastgroup) - { - vector pos; - entity linkjoineffect; - - if(self.crylink_waitrelease == 1) - { - pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_primary_joinspread * autocvar_g_balance_crylink_primary_speed); - - } - else - { - pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_secondary_joinspread * autocvar_g_balance_crylink_secondary_speed); - } - - linkjoineffect = spawn(); - linkjoineffect.think = W_Crylink_LinkJoinEffect_Think; - linkjoineffect.classname = "linkjoineffect"; - linkjoineffect.nextthink = time + w_crylink_linkjoin_time; - linkjoineffect.owner = self; - setorigin(linkjoineffect, pos); - } - self.crylink_waitrelease = 0; - if(!w_crylink(WR_CHECKAMMO1) && !w_crylink(WR_CHECKAMMO2)) - if (!(self.items & IT_UNLIMITED_WEAPON_AMMO)) - { - // ran out of ammo! - self.cnt = WEP_CRYLINK; - self.switchweapon = w_getbestweapon(self); - } - } - } - } - else if (req == WR_PRECACHE) - { - precache_model ("models/weapons/g_crylink.md3"); - precache_model ("models/weapons/v_crylink.md3"); - precache_model ("models/weapons/h_crylink.iqm"); - precache_sound ("weapons/crylink_fire.wav"); - precache_sound ("weapons/crylink_fire2.wav"); - precache_sound ("weapons/crylink_linkjoin.wav"); - //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else - } - else if (req == WR_SETUP) - { - weapon_setup(WEP_CRYLINK); - self.current_ammo = ammo_cells; - } - else if (req == WR_CHECKAMMO1) - { - // don't "run out of ammo" and switch weapons while waiting for release - if(self.crylink_lastgroup && self.crylink_waitrelease) - return TRUE; - - ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo; - ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_primary_ammo; - return ammo_amount; - } - else if (req == WR_CHECKAMMO2) - { - // don't "run out of ammo" and switch weapons while waiting for release - if(self.crylink_lastgroup && self.crylink_waitrelease) - return TRUE; - - ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo; - ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_secondary_ammo; - return ammo_amount; - } - else if (req == WR_RELOAD) - { - W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav"); - } - else if (req == WR_SUICIDEMESSAGE) - { - return WEAPON_CRYLINK_SUICIDE; - } - else if (req == WR_KILLMESSAGE) - { - return WEAPON_CRYLINK_MURDER; - } - return TRUE; -} -#endif -#ifdef CSQC -float w_crylink(float req) -{ - if(req == WR_IMPACTEFFECT) - { - vector org2; - org2 = w_org + w_backoff * 2; - if(w_deathtype & HITTYPE_SECONDARY) - { - pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/crylink_impact2.wav", VOL_BASE, ATTEN_NORM); - } - else - { - pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/crylink_impact.wav", VOL_BASE, ATTEN_NORM); - } - } - else if(req == WR_PRECACHE) - { - precache_sound("weapons/crylink_impact2.wav"); - precache_sound("weapons/crylink_impact.wav"); - } - return TRUE; -} -#endif -#endif diff --git a/qcsrc/server/w_grenadelauncher.qc b/qcsrc/server/w_grenadelauncher.qc deleted file mode 100644 index 17144d3a5..000000000 --- a/qcsrc/server/w_grenadelauncher.qc +++ /dev/null @@ -1,414 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ GRENADE_LAUNCHER, -/* function */ w_glauncher, -/* ammotype */ IT_ROCKETS, -/* impulse */ 4, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_MID, -/* model */ "gl", -/* shortname */ "grenadelauncher", -/* fullname */ _("Mortar") -); -#else -#ifdef SVQC -.float gl_detonate_later; -.float gl_bouncecnt; - -void W_Grenade_Explode (void) -{ - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - if(self.movetype == MOVETYPE_NONE) - self.velocity = self.oldvelocity; - - RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other); - - remove (self); -} - -void W_Grenade_Explode2 (void) -{ - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - if(self.movetype == MOVETYPE_NONE) - self.velocity = self.oldvelocity; - - RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other); - - remove (self); -} - -void W_Grenade_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if (self.health <= 0) - return; - - if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - - if (self.health <= 0) - W_PrepareExplosionByDamage(attacker, self.use); -} - -void W_Grenade_Think1 (void) -{ - self.nextthink = time; - if (time > self.cnt) - { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_Grenade_Explode (); - return; - } - if(self.gl_detonate_later && self.gl_bouncecnt >= autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt) - W_Grenade_Explode(); -} - -void W_Grenade_Touch1 (void) -{ - PROJECTILE_TOUCH; - if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_primary_type == 0) // always explode when hitting a player, or if normal mortar projectile - { - self.use (); - } - else if (autocvar_g_balance_grenadelauncher_primary_type == 1) // bounce - { - float r; - r = random() * 6; - if(r < 1) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM); - else if(r < 2) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM); - else if(r < 3) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM); - else if(r < 4) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM); - else if(r < 5) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM); - else - spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM); - self.projectiledeathtype |= HITTYPE_BOUNCE; - self.gl_bouncecnt += 1; - } - else if(autocvar_g_balance_grenadelauncher_primary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick - { - spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM); - - // let it stick whereever it is - self.oldvelocity = self.velocity; - self.velocity = '0 0 0'; - self.movetype = MOVETYPE_NONE; // also disables gravity - self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO - UpdateCSQCProjectile(self); - - // do not respond to any more touches - self.solid = SOLID_NOT; - - self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_primary_lifetime_stick); - } -} - -void W_Grenade_Touch2 (void) -{ - PROJECTILE_TOUCH; - if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_secondary_type == 0) // always explode when hitting a player, or if normal mortar projectile - { - self.use (); - } - else if (autocvar_g_balance_grenadelauncher_secondary_type == 1) // bounce - { - float r; - r = random() * 6; - if(r < 1) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM); - else if(r < 2) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM); - else if(r < 3) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM); - else if(r < 4) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM); - else if(r < 5) - spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM); - else - spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM); - self.projectiledeathtype |= HITTYPE_BOUNCE; - self.gl_bouncecnt += 1; - - if (autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce && self.gl_bouncecnt == 1) - self.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce; - - } - else if(autocvar_g_balance_grenadelauncher_secondary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick - { - spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM); - - // let it stick whereever it is - self.oldvelocity = self.velocity; - self.velocity = '0 0 0'; - self.movetype = MOVETYPE_NONE; // also disables gravity - self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO - UpdateCSQCProjectile(self); - - // do not respond to any more touches - self.solid = SOLID_NOT; - - self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_secondary_lifetime_stick); - } -} - -void W_Grenade_Attack (void) -{ - entity gren; - - W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo); - - W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_primary_damage); - w_shotdir = v_forward; // no TrueAim for grenades please - - pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - gren = spawn (); - gren.owner = gren.realowner = self; - gren.classname = "grenade"; - gren.bot_dodge = TRUE; - gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_primary_damage; - gren.movetype = MOVETYPE_BOUNCE; - gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor; - gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop; - PROJECTILE_MAKETRIGGER(gren); - gren.projectiledeathtype = WEP_GRENADE_LAUNCHER; - setorigin(gren, w_shotorg); - setsize(gren, '-3 -3 -3', '3 3 3'); - - gren.cnt = time + autocvar_g_balance_grenadelauncher_primary_lifetime; - gren.nextthink = time; - gren.think = W_Grenade_Think1; - gren.use = W_Grenade_Explode; - gren.touch = W_Grenade_Touch1; - - gren.takedamage = DAMAGE_YES; - gren.health = autocvar_g_balance_grenadelauncher_primary_health; - gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale; - gren.event_damage = W_Grenade_Damage; - gren.damagedbycontents = TRUE; - gren.missile_flags = MIF_SPLASH | MIF_ARC; - W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary); - - gren.angles = vectoangles (gren.velocity); - gren.flags = FL_PROJECTILE; - - if(autocvar_g_balance_grenadelauncher_primary_type == 0 || autocvar_g_balance_grenadelauncher_primary_type == 2) - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE); - else - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE); - - other = gren; MUTATOR_CALLHOOK(EditProjectile); -} - -void W_Grenade_Attack2 (void) -{ - entity gren; - - W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_secondary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo); - - W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_secondary_damage); - w_shotdir = v_forward; // no TrueAim for grenades please - - pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - gren = spawn (); - gren.owner = gren.realowner = self; - gren.classname = "grenade"; - gren.bot_dodge = TRUE; - gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_secondary_damage; - gren.movetype = MOVETYPE_BOUNCE; - gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor; - gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop; - PROJECTILE_MAKETRIGGER(gren); - gren.projectiledeathtype = WEP_GRENADE_LAUNCHER | HITTYPE_SECONDARY; - setorigin(gren, w_shotorg); - setsize(gren, '-3 -3 -3', '3 3 3'); - - gren.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime; - gren.think = adaptor_think2use_hittype_splash; - gren.use = W_Grenade_Explode2; - gren.touch = W_Grenade_Touch2; - - gren.takedamage = DAMAGE_YES; - gren.health = autocvar_g_balance_grenadelauncher_secondary_health; - gren.damageforcescale = autocvar_g_balance_grenadelauncher_secondary_damageforcescale; - gren.event_damage = W_Grenade_Damage; - gren.damagedbycontents = TRUE; - gren.missile_flags = MIF_SPLASH | MIF_ARC; - W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_secondary); - - gren.angles = vectoangles (gren.velocity); - gren.flags = FL_PROJECTILE; - - if(autocvar_g_balance_grenadelauncher_secondary_type == 0 || autocvar_g_balance_grenadelauncher_secondary_type == 2) - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE); - else - CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE); - - other = gren; MUTATOR_CALLHOOK(EditProjectile); -} - -void spawnfunc_weapon_grenadelauncher (void) -{ - weapon_defaultspawnfunc(WEP_GRENADE_LAUNCHER); -} - -.float bot_secondary_grenademooth; -float w_glauncher(float req) -{ - entity nade; - float nadefound; - float ammo_amount; - - if (req == WR_AIM) - { - self.BUTTON_ATCK = FALSE; - self.BUTTON_ATCK2 = FALSE; - if (self.bot_secondary_grenademooth == 0) - { - if(bot_aim(autocvar_g_balance_grenadelauncher_primary_speed, autocvar_g_balance_grenadelauncher_primary_speed_up, autocvar_g_balance_grenadelauncher_primary_lifetime, TRUE)) - { - self.BUTTON_ATCK = TRUE; - if(random() < 0.01) self.bot_secondary_grenademooth = 1; - } - } - else - { - if(bot_aim(autocvar_g_balance_grenadelauncher_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_grenadelauncher_secondary_lifetime, TRUE)) - { - self.BUTTON_ATCK2 = TRUE; - if(random() < 0.02) self.bot_secondary_grenademooth = 0; - } - } - } - else if (req == WR_THINK) - { - if(autocvar_g_balance_grenadelauncher_reload_ammo && self.clip_load < min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo)) // forced reload - weapon_action(self.weapon, WR_RELOAD); - else if (self.BUTTON_ATCK) - { - if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire)) - { - W_Grenade_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready); - } - } - else if (self.BUTTON_ATCK2) - { - if (cvar("g_balance_grenadelauncher_secondary_remote_detonateprimary")) - { - nadefound = 0; - for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self) - { - if(!nade.gl_detonate_later) - { - nade.gl_detonate_later = TRUE; - nadefound = 1; - } - } - if(nadefound) - sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM); - } - else if (weapon_prepareattack(1, autocvar_g_balance_grenadelauncher_secondary_refire)) - { - W_Grenade_Attack2(); - weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_grenadelauncher_secondary_animtime, w_ready); - } - } - } - else if (req == WR_PRECACHE) - { - precache_model ("models/weapons/g_gl.md3"); - precache_model ("models/weapons/v_gl.md3"); - precache_model ("models/weapons/h_gl.iqm"); - precache_sound ("weapons/grenade_bounce1.wav"); - precache_sound ("weapons/grenade_bounce2.wav"); - precache_sound ("weapons/grenade_bounce3.wav"); - precache_sound ("weapons/grenade_bounce4.wav"); - precache_sound ("weapons/grenade_bounce5.wav"); - precache_sound ("weapons/grenade_bounce6.wav"); - precache_sound ("weapons/grenade_stick.wav"); - precache_sound ("weapons/grenade_fire.wav"); - //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else - } - else if (req == WR_SETUP) - { - weapon_setup(WEP_GRENADE_LAUNCHER); - self.current_ammo = ammo_rockets; - } - else if (req == WR_CHECKAMMO1) - { - ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo; - ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_primary_ammo; - return ammo_amount; - } - else if (req == WR_CHECKAMMO2) - { - ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo; - ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_secondary_ammo; - return ammo_amount; - } - else if (req == WR_RELOAD) - { - W_Reload(min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo), autocvar_g_balance_grenadelauncher_reload_ammo, autocvar_g_balance_grenadelauncher_reload_time, "weapons/reload.wav"); - } - else if (req == WR_SUICIDEMESSAGE) - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_MORTAR_SUICIDE_BOUNCE; - else - return WEAPON_MORTAR_SUICIDE_EXPLODE; - } - else if (req == WR_KILLMESSAGE) - { - if(w_deathtype & HITTYPE_SECONDARY) - return WEAPON_MORTAR_MURDER_BOUNCE; - else - return WEAPON_MORTAR_MURDER_EXPLODE; - } - return TRUE; -} -#endif -#ifdef CSQC -float w_glauncher(float req) -{ - if(req == WR_IMPACTEFFECT) - { - vector org2; - org2 = w_org + w_backoff * 12; - pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM); - } - else if(req == WR_PRECACHE) - { - precache_sound("weapons/grenade_impact.wav"); - } - return TRUE; -} -#endif -#endif diff --git a/qcsrc/server/w_minelayer.qc b/qcsrc/server/w_minelayer.qc deleted file mode 100644 index 5d88df8b2..000000000 --- a/qcsrc/server/w_minelayer.qc +++ /dev/null @@ -1,563 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ MINE_LAYER, -/* function */ w_minelayer, -/* ammotype */ IT_ROCKETS, -/* impulse */ 4, -/* flags */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_HIGH, -/* model */ "minelayer", -/* shortname */ "minelayer", -/* fullname */ _("Mine Layer") -); -#else -#ifdef SVQC -void W_Mine_Think (void); -.float minelayer_detonate, mine_explodeanyway; -.float mine_time; -.vector mine_orientation; - -void spawnfunc_weapon_minelayer (void) -{ - weapon_defaultspawnfunc(WEP_MINE_LAYER); -} - -void W_Mine_Stick (entity to) -{ - spamsound (self, CH_SHOTS, "weapons/mine_stick.wav", VOL_BASE, ATTEN_NORM); - - // in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile - - entity newmine; - newmine = spawn(); - newmine.classname = self.classname; - - newmine.bot_dodge = self.bot_dodge; - newmine.bot_dodgerating = self.bot_dodgerating; - - newmine.owner = self.owner; - newmine.realowner = self.realowner; - setsize(newmine, '-4 -4 -4', '4 4 4'); - setorigin(newmine, self.origin); - setmodel(newmine, "models/mine.md3"); - newmine.angles = vectoangles(-trace_plane_normal); // face against the surface - - newmine.mine_orientation = -trace_plane_normal; - - newmine.takedamage = self.takedamage; - newmine.damageforcescale = self.damageforcescale; - newmine.health = self.health; - newmine.event_damage = self.event_damage; - newmine.spawnshieldtime = self.spawnshieldtime; - newmine.damagedbycontents = TRUE; - - newmine.movetype = MOVETYPE_NONE; // lock the mine in place - newmine.projectiledeathtype = self.projectiledeathtype; - - newmine.mine_time = self.mine_time; - - newmine.touch = func_null; - newmine.think = W_Mine_Think; - newmine.nextthink = time; - newmine.cnt = self.cnt; - newmine.flags = self.flags; - - remove(self); - self = newmine; - - if(to) - SetMovetypeFollow(self, to); -} - -void W_Mine_Explode () -{ - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_damage, autocvar_g_balance_minelayer_edgedamage, autocvar_g_balance_minelayer_radius, world, autocvar_g_balance_minelayer_force, self.projectiledeathtype, other); - - if (self.realowner.weapon == WEP_MINE_LAYER) - { - entity oldself; - oldself = self; - self = self.realowner; - if (!weapon_action(WEP_MINE_LAYER, WR_CHECKAMMO1)) - { - self.cnt = WEP_MINE_LAYER; - ATTACK_FINISHED(self) = time; - self.switchweapon = w_getbestweapon(self); - } - self = oldself; - } - self.realowner.minelayer_mines -= 1; - remove (self); -} - -void W_Mine_DoRemoteExplode () -{ - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW) - self.velocity = self.mine_orientation; // particle fx and decals need .velocity - - RadiusDamage (self, self.realowner, autocvar_g_balance_minelayer_remote_damage, autocvar_g_balance_minelayer_remote_edgedamage, autocvar_g_balance_minelayer_remote_radius, world, autocvar_g_balance_minelayer_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); - - if (self.realowner.weapon == WEP_MINE_LAYER) - { - entity oldself; - oldself = self; - self = self.realowner; - if (!weapon_action(WEP_MINE_LAYER, WR_CHECKAMMO1)) - { - self.cnt = WEP_MINE_LAYER; - ATTACK_FINISHED(self) = time; - self.switchweapon = w_getbestweapon(self); - } - self = oldself; - } - self.realowner.minelayer_mines -= 1; - remove (self); -} - -void W_Mine_RemoteExplode () -{ - if(self.realowner.deadflag == DEAD_NO) - if((self.spawnshieldtime >= 0) - ? (time >= self.spawnshieldtime) // timer - : (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_minelayer_remote_radius) // safety device - ) - { - W_Mine_DoRemoteExplode(); - } -} - -void W_Mine_ProximityExplode () -{ - // make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance - if(autocvar_g_balance_minelayer_protection && self.mine_explodeanyway == 0) - { - entity head; - head = findradius(self.origin, autocvar_g_balance_minelayer_radius); - while(head) - { - if(head == self.realowner || SAME_TEAM(head, self.realowner)) - return; - head = head.chain; - } - } - - self.mine_time = 0; - W_Mine_Explode(); -} - -float W_Mine_Count(entity e) -{ - float minecount = 0; - entity mine; - for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e) - minecount += 1; - - return minecount; -} - -void W_Mine_Think (void) -{ - entity head; - - self.nextthink = time; - - if(self.movetype == MOVETYPE_FOLLOW) - { - if(LostMovetypeFollow(self)) - { - UnsetMovetypeFollow(self); - self.movetype = MOVETYPE_NONE; - } - } - - // our lifetime has expired, it's time to die - mine_time just allows us to play a sound for this - // TODO: replace this mine_trigger.wav sound with a real countdown - if ((time > self.cnt) && (!self.mine_time)) - { - if(autocvar_g_balance_minelayer_lifetime_countdown > 0) - spamsound (self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTEN_NORM); - self.mine_time = time + autocvar_g_balance_minelayer_lifetime_countdown; - self.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near. - } - - // a player's mines shall explode if he disconnects or dies - // TODO: Do this on team change too -- Samual: But isn't a player killed when they switch teams? - if(!IS_PLAYER(self.realowner) || self.realowner.deadflag != DEAD_NO) - { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_Mine_Explode(); - return; - } - - // set the mine for detonation when a foe gets close enough - head = findradius(self.origin, autocvar_g_balance_minelayer_proximityradius); - while(head) - { - if(IS_PLAYER(head) && head.deadflag == DEAD_NO) - if(head != self.realowner && DIFF_TEAM(head, self.realowner)) // don't trigger for team mates - if(!self.mine_time) - { - spamsound (self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTEN_NORM); - self.mine_time = time + autocvar_g_balance_minelayer_time; - } - head = head.chain; - } - - // explode if it's time to - if(self.mine_time && time >= self.mine_time) - { - W_Mine_ProximityExplode(); - return; - } - - // remote detonation - if (self.realowner.weapon == WEP_MINE_LAYER) - if (self.realowner.deadflag == DEAD_NO) - if (self.minelayer_detonate) - W_Mine_RemoteExplode(); -} - -void W_Mine_Touch (void) -{ - if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW) - return; // we're already a stuck mine, why do we get called? TODO does this even happen? - - if(WarpZone_Projectile_Touch()) - { - if(wasfreed(self)) - self.realowner.minelayer_mines -= 1; - return; - } - - if(other && IS_PLAYER(other) && other.deadflag == DEAD_NO) - { - // hit a player - // don't stick - } - else - { - W_Mine_Stick(other); - } -} - -void W_Mine_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if (self.health <= 0) - return; - - float is_from_enemy = (inflictor.realowner != self.realowner); - - if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_from_enemy ? 1 : -1))) - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - self.angles = vectoangles(self.velocity); - - if (self.health <= 0) - W_PrepareExplosionByDamage(attacker, W_Mine_Explode); -} - -void W_Mine_Attack (void) -{ - entity mine; - entity flash; - - // scan how many mines we placed, and return if we reached our limit - if(autocvar_g_balance_minelayer_limit) - { - if(self.minelayer_mines >= autocvar_g_balance_minelayer_limit) - { - // the refire delay keeps this message from being spammed - sprint(self, strcat("minelayer: You cannot place more than ^2", ftos(autocvar_g_balance_minelayer_limit), " ^7mines at a time\n") ); - play2(self, "weapons/unavailable.wav"); - return; - } - } - - W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo); - - W_SetupShot_ProjectileSize (self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", CH_WEAPON_A, autocvar_g_balance_minelayer_damage); - pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - mine = WarpZone_RefSys_SpawnSameRefSys(self); - mine.owner = mine.realowner = self; - if(autocvar_g_balance_minelayer_detonatedelay >= 0) - mine.spawnshieldtime = time + autocvar_g_balance_minelayer_detonatedelay; - else - mine.spawnshieldtime = -1; - mine.classname = "mine"; - mine.bot_dodge = TRUE; - mine.bot_dodgerating = autocvar_g_balance_minelayer_damage * 2; // * 2 because it can detonate inflight which makes it even more dangerous - - mine.takedamage = DAMAGE_YES; - mine.damageforcescale = autocvar_g_balance_minelayer_damageforcescale; - mine.health = autocvar_g_balance_minelayer_health; - mine.event_damage = W_Mine_Damage; - mine.damagedbycontents = TRUE; - - mine.movetype = MOVETYPE_TOSS; - PROJECTILE_MAKETRIGGER(mine); - mine.projectiledeathtype = WEP_MINE_LAYER; - setsize (mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot - - setorigin (mine, w_shotorg - v_forward * 4); // move it back so it hits the wall at the right point - W_SetupProjectileVelocity(mine, autocvar_g_balance_minelayer_speed, 0); - mine.angles = vectoangles (mine.velocity); - - mine.touch = W_Mine_Touch; - mine.think = W_Mine_Think; - mine.nextthink = time; - mine.cnt = time + (autocvar_g_balance_minelayer_lifetime - autocvar_g_balance_minelayer_lifetime_countdown); - mine.flags = FL_PROJECTILE; - mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY; - - CSQCProjectile(mine, TRUE, PROJECTILE_MINE, TRUE); - - // muzzle flash for 1st person view - flash = spawn (); - setmodel (flash, "models/flash.md3"); // precision set below - SUB_SetFade (flash, time, 0.1); - flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; - W_AttachToShotorg(flash, '5 0 0'); - - // common properties - - other = mine; MUTATOR_CALLHOOK(EditProjectile); - - self.minelayer_mines = W_Mine_Count(self); -} - -float W_PlacedMines(float detonate) -{ - entity mine; - float minfound = 0; - - for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == self) - { - if(detonate) - { - if(!mine.minelayer_detonate) - { - mine.minelayer_detonate = TRUE; - minfound = 1; - } - } - else - minfound = 1; - } - return minfound; -} - -float w_minelayer(float req) -{ - entity mine; - float ammo_amount; - - if (req == WR_AIM) - { - // aim and decide to fire if appropriate - if(self.minelayer_mines >= autocvar_g_balance_minelayer_limit) - self.BUTTON_ATCK = FALSE; - else - self.BUTTON_ATCK = bot_aim(autocvar_g_balance_minelayer_speed, 0, autocvar_g_balance_minelayer_lifetime, FALSE); - if(skill >= 2) // skill 0 and 1 bots won't detonate mines! - { - // decide whether to detonate mines - entity targetlist, targ; - float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; - float selfdamage, teamdamage, enemydamage; - edgedamage = autocvar_g_balance_minelayer_edgedamage; - coredamage = autocvar_g_balance_minelayer_damage; - edgeradius = autocvar_g_balance_minelayer_radius; - recipricoledgeradius = 1 / edgeradius; - selfdamage = 0; - teamdamage = 0; - enemydamage = 0; - targetlist = findchainfloat(bot_attack, TRUE); - mine = find(world, classname, "mine"); - while (mine) - { - if (mine.realowner != self) - { - mine = find(mine, classname, "mine"); - continue; - } - targ = targetlist; - while (targ) - { - d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - mine.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(targ)) - enemydamage = enemydamage + d; - targ = targ.chain; - } - mine = find(mine, classname, "mine"); - } - float desirabledamage; - desirabledamage = enemydamage; - if (time > self.invincible_finished && time > self.spawnshieldtime) - desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; - if (teamplay && self.team) - desirabledamage = desirabledamage - teamdamage; - - mine = find(world, classname, "mine"); - while (mine) - { - if (mine.realowner != self) - { - mine = find(mine, classname, "mine"); - continue; - } - makevectors(mine.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(mine.origin - targ.origin)< 0.1) - && desirabledamage > 0.1*coredamage - )self.BUTTON_ATCK2 = TRUE; - targ = targ.chain; - } - }else{ - float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000); - //As the distance gets larger, a correct detonation gets near imposible - //Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player - if(v_forward * normalize(mine.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)) - self.BUTTON_ATCK2 = TRUE; - // dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n"); - } - - mine = find(mine, classname, "mine"); - } - // 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 - self.BUTTON_ATCK2 = TRUE; - if ((skill > 6.5) && (selfdamage > self.health)) - self.BUTTON_ATCK2 = FALSE; - //if(self.BUTTON_ATCK2 == TRUE) - // dprint(ftos(desirabledamage),"\n"); - if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE; - } - } - else if (req == WR_THINK) - { - if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < autocvar_g_balance_minelayer_ammo) // forced reload - { - // not if we're holding the minelayer without enough ammo, but can detonate existing mines - if (!(W_PlacedMines(FALSE) && self.ammo_rockets < autocvar_g_balance_minelayer_ammo)) - weapon_action(self.weapon, WR_RELOAD); - } - else if (self.BUTTON_ATCK) - { - if(weapon_prepareattack(0, autocvar_g_balance_minelayer_refire)) - { - W_Mine_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_minelayer_animtime, w_ready); - } - } - - if (self.BUTTON_ATCK2) - { - if(W_PlacedMines(TRUE)) - sound (self, CH_WEAPON_B, "weapons/mine_det.wav", VOL_BASE, ATTEN_NORM); - } - } - else if (req == WR_PRECACHE) - { - precache_model ("models/flash.md3"); - precache_model ("models/mine.md3"); - precache_model ("models/weapons/g_minelayer.md3"); - precache_model ("models/weapons/v_minelayer.md3"); - precache_model ("models/weapons/h_minelayer.iqm"); - precache_sound ("weapons/mine_det.wav"); - precache_sound ("weapons/mine_fire.wav"); - precache_sound ("weapons/mine_stick.wav"); - precache_sound ("weapons/mine_trigger.wav"); - //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else - } - else if (req == WR_SETUP) - { - weapon_setup(WEP_MINE_LAYER); - self.current_ammo = ammo_rockets; - } - else if (req == WR_CHECKAMMO1) - { - // don't switch while placing a mine - if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER) - { - ammo_amount = self.ammo_rockets >= autocvar_g_balance_minelayer_ammo; - ammo_amount += self.(weapon_load[WEP_MINE_LAYER]) >= autocvar_g_balance_minelayer_ammo; - return ammo_amount; - } - } - else if (req == WR_CHECKAMMO2) - { - if (W_PlacedMines(FALSE)) - return TRUE; - else - return FALSE; - } - else if (req == WR_RESETPLAYER) - { - self.minelayer_mines = 0; - } - else if (req == WR_RELOAD) - { - W_Reload(autocvar_g_balance_minelayer_ammo, autocvar_g_balance_minelayer_reload_ammo, autocvar_g_balance_minelayer_reload_time, "weapons/reload.wav"); - } - else if (req == WR_SUICIDEMESSAGE) - { - return WEAPON_MINELAYER_SUICIDE; - } - else if (req == WR_KILLMESSAGE) - { - return WEAPON_MINELAYER_MURDER; - } - return TRUE; -} -#endif -#ifdef CSQC -float w_minelayer(float req) -{ - if(req == WR_IMPACTEFFECT) - { - vector org2; - org2 = w_org + w_backoff * 12; - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/mine_exp.wav", VOL_BASE, ATTEN_NORM); - } - else if(req == WR_PRECACHE) - { - precache_sound("weapons/mine_exp.wav"); - } - return TRUE; -} -#endif -#endif diff --git a/qcsrc/server/w_rocketlauncher.qc b/qcsrc/server/w_rocketlauncher.qc deleted file mode 100644 index 6cd8929f6..000000000 --- a/qcsrc/server/w_rocketlauncher.qc +++ /dev/null @@ -1,491 +0,0 @@ -#ifdef REGISTER_WEAPON -REGISTER_WEAPON( -/* WEP_##id */ ROCKET_LAUNCHER, -/* function */ w_rlauncher, -/* ammotype */ IT_ROCKETS, -/* impulse */ 9, -/* flags */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH, -/* rating */ BOT_PICKUP_RATING_HIGH, -/* model */ "rl", -/* shortname */ "rocketlauncher", -/* fullname */ _("Rocket Launcher") -); -#else -#ifdef SVQC -.float rl_release; -.float rl_detonate_later; - -void W_Rocket_Unregister() -{ - if(self.realowner && self.realowner.lastrocket == self) - { - self.realowner.lastrocket = world; - // self.realowner.rl_release = 1; - } -} - -void W_Rocket_Explode () -{ - W_Rocket_Unregister(); - - if(other.takedamage == DAMAGE_AIM) - if(IS_PLAYER(other)) - if(DIFF_TEAM(self.realowner, other)) - if(other.deadflag == DEAD_NO) - if(IsFlying(other)) - Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other); - - if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) - { - if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) - { - self.realowner.cnt = WEP_ROCKET_LAUNCHER; - ATTACK_FINISHED(self.realowner) = time; - self.realowner.switchweapon = w_getbestweapon(self.realowner); - } - } - remove (self); -} - -void W_Rocket_DoRemoteExplode () -{ - W_Rocket_Unregister(); - - self.event_damage = func_null; - self.takedamage = DAMAGE_NO; - - RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world); - - if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) - { - if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) - { - self.realowner.cnt = WEP_ROCKET_LAUNCHER; - ATTACK_FINISHED(self.realowner) = time; - self.realowner.switchweapon = w_getbestweapon(self.realowner); - } - } - remove (self); -} - -void W_Rocket_RemoteExplode() -{ - if(self.realowner.deadflag == DEAD_NO) - if(self.realowner.lastrocket) - { - if((self.spawnshieldtime >= 0) - ? (time >= self.spawnshieldtime) // timer - : (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_rocketlauncher_remote_radius) // safety device - ) - { - W_Rocket_DoRemoteExplode(); - } - } -} - -vector rocket_steerto(vector thisdir, vector goaldir, float maxturn_cos) -{ - if(thisdir * goaldir > maxturn_cos) - return goaldir; - if(thisdir * goaldir < -0.9998) // less than 1 degree and opposite - return thisdir; // refuse to guide (better than letting a numerical error happen) - float f, m2; - vector v; - // solve: - // g = normalize(thisdir + goaldir * X) - // thisdir * g = maxturn - // - // gg = thisdir + goaldir * X - // (thisdir * gg)^2 = maxturn^2 * (gg * gg) - // - // (1 + (thisdir * goaldir) * X)^2 = maxturn^2 * (1 + X*X + 2 * X * thisdir * goaldir) - f = thisdir * goaldir; - // (1 + f * X)^2 = maxturn^2 * (1 + X*X + 2 * X * f) - // 0 = (m^2 - f^2) * x^2 + (2 * f * (m^2 - 1)) * x + (m^2 - 1) - m2 = maxturn_cos * maxturn_cos; - v = solve_quadratic(m2 - f * f, 2 * f * (m2 - 1), m2 - 1); - return normalize(thisdir + goaldir * v_y); // the larger solution! -} -// assume thisdir == -goaldir: -// f == -1 -// v = solve_qadratic(m2 - 1, -2 * (m2 - 1), m2 - 1) -// (m2 - 1) x^2 - 2 * (m2 - 1) * x + (m2 - 1) = 0 -// x^2 - 2 * x + 1 = 0 -// (x - 1)^2 = 0 -// x = 1 -// normalize(thisdir + goaldir) -// normalize(0) - -void W_Rocket_Think (void) -{ - vector desireddir, olddir, newdir, desiredorigin, goal; -#if 0 - float cosminang, cosmaxang, cosang; -#endif - float velspeed, f; - self.nextthink = time; - if (time > self.cnt) - { - other = world; - self.projectiledeathtype |= HITTYPE_BOUNCE; - W_Rocket_Explode (); - return; - } - - // accelerate - makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0'); - velspeed = autocvar_g_balance_rocketlauncher_speed * g_weaponspeedfactor - (self.velocity * v_forward); - if (velspeed > 0) - self.velocity = self.velocity + v_forward * min(autocvar_g_balance_rocketlauncher_speedaccel * g_weaponspeedfactor * frametime, velspeed); - - // laser guided, or remote detonation - if (self.realowner.weapon == WEP_ROCKET_LAUNCHER) - { - if(self == self.realowner.lastrocket) - if (!self.realowner.rl_release) - if (!self.BUTTON_ATCK2) - if(autocvar_g_balance_rocketlauncher_guiderate) - if(time > self.pushltime) - if(self.realowner.deadflag == DEAD_NO) - { - f = autocvar_g_balance_rocketlauncher_guideratedelay; - if(f) - f = bound(0, (time - self.pushltime) / f, 1); - else - f = 1; - - velspeed = vlen(self.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); - - // 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 + autocvar_g_balance_rocketlauncher_guidegoal) * desireddir; - newdir = rocket_steerto(olddir, normalize(goal - self.origin), cos(autocvar_g_balance_rocketlauncher_guiderate * f * frametime * DEG2RAD)); - - self.velocity = newdir * velspeed; - self.angles = vectoangles(self.velocity); - - if(!self.count) - { - pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1); - // TODO add a better sound here - sound (self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTEN_NORM); - self.count = 1; - } - } - - if(self.rl_detonate_later) - W_Rocket_RemoteExplode(); - } - - if(self.csqcprojectile_clientanimate == 0) - UpdateCSQCProjectile(self); -} - -void W_Rocket_Touch (void) -{ - if(WarpZone_Projectile_Touch()) - { - if(wasfreed(self)) - W_Rocket_Unregister(); - return; - } - W_Rocket_Unregister(); - W_Rocket_Explode (); -} - -void W_Rocket_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) -{ - if (self.health <= 0) - return; - - if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions - return; // g_projectiles_damage says to halt - - self.health = self.health - damage; - self.angles = vectoangles(self.velocity); - - if (self.health <= 0) - W_PrepareExplosionByDamage(attacker, W_Rocket_Explode); -} - -void W_Rocket_Attack (void) -{ - entity missile; - entity flash; - - W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo); - - W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, autocvar_g_balance_rocketlauncher_damage); - pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1); - - missile = WarpZone_RefSys_SpawnSameRefSys(self); - missile.owner = missile.realowner = self; - self.lastrocket = missile; - if(autocvar_g_balance_rocketlauncher_detonatedelay >= 0) - missile.spawnshieldtime = time + autocvar_g_balance_rocketlauncher_detonatedelay; - else - missile.spawnshieldtime = -1; - missile.pushltime = time + autocvar_g_balance_rocketlauncher_guidedelay; - missile.classname = "rocket"; - missile.bot_dodge = TRUE; - missile.bot_dodgerating = autocvar_g_balance_rocketlauncher_damage * 2; // * 2 because it can be detonated inflight which makes it even more dangerous - - missile.takedamage = DAMAGE_YES; - missile.damageforcescale = autocvar_g_balance_rocketlauncher_damageforcescale; - missile.health = autocvar_g_balance_rocketlauncher_health; - missile.event_damage = W_Rocket_Damage; - missile.damagedbycontents = TRUE; - - missile.movetype = MOVETYPE_FLY; - PROJECTILE_MAKETRIGGER(missile); - missile.projectiledeathtype = WEP_ROCKET_LAUNCHER; - setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot - - setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point - W_SetupProjectileVelocity(missile, autocvar_g_balance_rocketlauncher_speedstart, 0); - missile.angles = vectoangles (missile.velocity); - - missile.touch = W_Rocket_Touch; - missile.think = W_Rocket_Think; - missile.nextthink = time; - missile.cnt = time + autocvar_g_balance_rocketlauncher_lifetime; - missile.flags = FL_PROJECTILE; - missile.missile_flags = MIF_SPLASH; - - CSQCProjectile(missile, autocvar_g_balance_rocketlauncher_guiderate == 0 && autocvar_g_balance_rocketlauncher_speedaccel == 0, PROJECTILE_ROCKET, FALSE); // because of fly sound - - // muzzle flash for 1st person view - flash = spawn (); - setmodel (flash, "models/flash.md3"); // precision set below - SUB_SetFade (flash, time, 0.1); - flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; - W_AttachToShotorg(flash, '5 0 0'); - - // common properties - other = missile; MUTATOR_CALLHOOK(EditProjectile); -} - -void spawnfunc_weapon_rocketlauncher (void); // defined in t_items.qc - -float w_rlauncher(float req) -{ - entity rock; - float rockfound; - float ammo_amount; - - if (req == WR_AIM) - { - // aim and decide to fire if appropriate - self.BUTTON_ATCK = bot_aim(autocvar_g_balance_rocketlauncher_speed, 0, autocvar_g_balance_rocketlauncher_lifetime, FALSE); - if(skill >= 2) // skill 0 and 1 bots won't detonate rockets! - { - // decide whether to detonate rockets - entity missile, targetlist, targ; - float edgedamage, coredamage, edgeradius, recipricoledgeradius, d; - float selfdamage, teamdamage, enemydamage; - edgedamage = autocvar_g_balance_rocketlauncher_edgedamage; - coredamage = autocvar_g_balance_rocketlauncher_damage; - edgeradius = autocvar_g_balance_rocketlauncher_radius; - recipricoledgeradius = 1 / edgeradius; - selfdamage = 0; - teamdamage = 0; - enemydamage = 0; - targetlist = findchainfloat(bot_attack, TRUE); - missile = find(world, classname, "rocket"); - while (missile) - { - if (missile.realowner != self) - { - missile = find(missile, classname, "rocket"); - continue; - } - targ = targetlist; - while (targ) - { - d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - missile.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(targ)) - enemydamage = enemydamage + d; - targ = targ.chain; - } - missile = find(missile, classname, "rocket"); - } - float desirabledamage; - desirabledamage = enemydamage; - if (time > self.invincible_finished && time > self.spawnshieldtime) - desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent; - if (teamplay && self.team) - desirabledamage = desirabledamage - teamdamage; - - missile = find(world, classname, "rocket"); - while (missile) - { - if (missile.realowner != self) - { - missile = find(missile, classname, "rocket"); - continue; - } - makevectors(missile.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(missile.origin - targ.origin)< 0.1) - && desirabledamage > 0.1*coredamage - )self.BUTTON_ATCK2 = TRUE; - targ = targ.chain; - } - }else{ - float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000); - //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(missile.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)) - self.BUTTON_ATCK2 = TRUE; - // dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n"); - } - - missile = find(missile, classname, "rocket"); - } - // 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 - self.BUTTON_ATCK2 = TRUE; - if ((skill > 6.5) && (selfdamage > self.health)) - self.BUTTON_ATCK2 = FALSE; - //if(self.BUTTON_ATCK2 == TRUE) - // dprint(ftos(desirabledamage),"\n"); - if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE; - } - } - else if (req == WR_THINK) - { - if(autocvar_g_balance_rocketlauncher_reload_ammo && self.clip_load < autocvar_g_balance_rocketlauncher_ammo) // forced reload - weapon_action(self.weapon, WR_RELOAD); - else - { - if (self.BUTTON_ATCK) - { - if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop) - if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire)) - { - W_Rocket_Attack(); - weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready); - self.rl_release = 0; - } - } - else - self.rl_release = 1; - - if (self.BUTTON_ATCK2) - { - rockfound = 0; - for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self) - { - if(!rock.rl_detonate_later) - { - rock.rl_detonate_later = TRUE; - rockfound = 1; - } - } - if(rockfound) - sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM); - } - } - } - else if (req == WR_PRECACHE) - { - precache_model ("models/flash.md3"); - precache_model ("models/weapons/g_rl.md3"); - precache_model ("models/weapons/v_rl.md3"); - precache_model ("models/weapons/h_rl.iqm"); - precache_sound ("weapons/rocket_det.wav"); - precache_sound ("weapons/rocket_fire.wav"); - precache_sound ("weapons/rocket_mode.wav"); - //precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else - } - else if (req == WR_SETUP) - { - weapon_setup(WEP_ROCKET_LAUNCHER); - self.current_ammo = ammo_rockets; - self.rl_release = 1; - } - else if (req == WR_CHECKAMMO1) - { - // don't switch while guiding a missile - if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER) - { - ammo_amount = FALSE; - if(autocvar_g_balance_rocketlauncher_reload_ammo) - { - if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.(weapon_load[WEP_ROCKET_LAUNCHER]) < autocvar_g_balance_rocketlauncher_ammo) - ammo_amount = TRUE; - } - else if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo) - ammo_amount = TRUE; - return !ammo_amount; - } - } - else if (req == WR_CHECKAMMO2) - return FALSE; - else if (req == WR_RESETPLAYER) - { - self.rl_release = 0; - } - else if (req == WR_RELOAD) - { - W_Reload(autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo, autocvar_g_balance_rocketlauncher_reload_time, "weapons/reload.wav"); - } - else if (req == WR_SUICIDEMESSAGE) - { - return WEAPON_ROCKETLAUNCHER_SUICIDE; - } - else if (req == WR_KILLMESSAGE) - { - if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH)) - return WEAPON_ROCKETLAUNCHER_MURDER_SPLASH; - else - return WEAPON_ROCKETLAUNCHER_MURDER_DIRECT; - } - return TRUE; -} -#endif -#ifdef CSQC -float w_rlauncher(float req) -{ - if(req == WR_IMPACTEFFECT) - { - vector org2; - org2 = w_org + w_backoff * 12; - pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1); - if(!w_issilent) - sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM); - } - else if(req == WR_PRECACHE) - { - precache_sound("weapons/rocket_impact.wav"); - } - return TRUE; -} -#endif -#endif