bool autocvar_hud_panel_powerups_progressbar;
bool autocvar_hud_panel_buffs = 1;
//float autocvar_hud_panel_buffs_iconalign;
+string autocvar_hud_panel_powerups_progressbar_shield;
+string autocvar_hud_panel_powerups_progressbar_strength;
string autocvar_hud_panel_powerups_progressbar_superweapons;
bool autocvar_hud_panel_powerups_text;
int autocvar_hud_panel_pressedkeys;
vector autocvar_hud_progressbar_fuel_color;
vector autocvar_hud_progressbar_health_color;
vector autocvar_hud_progressbar_nexball_color;
+vector autocvar_hud_progressbar_shield_color;
vector autocvar_hud_progressbar_speed_color;
+vector autocvar_hud_progressbar_strength_color;
vector autocvar_hud_progressbar_superweapons_color;
bool autocvar_hud_showbinds;
bool autocvar_hud_showbinds_limit;
//
void HUD_Powerups(void)
{
- float superweapons_time;
+ float strength_time, shield_time, superweapons_time;
if(!autocvar__hud_configure)
{
if(!autocvar_hud_panel_powerups) return;
if(spectatee_status == -1) return;
- if(!(getstati(STAT_ITEMS, 0, 24) & IT_SUPERWEAPON)) return;
+ if(!(getstati(STAT_ITEMS, 0, 24) & (IT_STRENGTH | IT_INVINCIBLE | IT_SUPERWEAPON))) return;
if (getstati(STAT_HEALTH) <= 0) return;
+ strength_time = bound(0, getstatf(STAT_STRENGTH_FINISHED) - time, 99);
+ shield_time = bound(0, getstatf(STAT_INVINCIBLE_FINISHED) - time, 99);
superweapons_time = bound(0, getstatf(STAT_SUPERWEAPONS_FINISHED) - time, 99);
if (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_SUPERWEAPONS)
}
else
{
+ strength_time = 15;
+ shield_time = 27;
superweapons_time = 13;
}
pos = panel_pos;
mySize = panel_size;
- HUD_Panel_DrawBg(bound(0, superweapons_time, 1));
+ HUD_Panel_DrawBg(bound(0, max(strength_time, shield_time, superweapons_time), 1));
if(panel_bg_padding)
{
pos += '1 1 0' * panel_bg_padding;
float panel_ar = mySize.x/mySize.y;
float is_vertical = (panel_ar < 1);
- vector superweapons_offset = '0 0 0';
+ vector shield_offset = '0 0 0', strength_offset = '0 0 0', superweapons_offset = '0 0 0';
float superweapons_is = -1;
- if(superweapons_time) { superweapons_is = 2; }
+ if(superweapons_time)
+ {
+ if(strength_time)
+ {
+ if(shield_time)
+ superweapons_is = 0;
+ else
+ superweapons_is = 2;
+ }
+ else
+ {
+ if(shield_time)
+ superweapons_is = 1;
+ else
+ superweapons_is = 2;
+ }
+ }
- float superweapons_baralign;
- float superweapons_iconalign;
+ // FIXME handle superweapons here
+ if(superweapons_is == 0)
+ {
+ if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
+ {
+ mySize.x *= (1.0 / 3.0);
+ superweapons_offset.x = mySize.x;
+ if (autocvar_hud_panel_powerups_flip)
+ shield_offset.x = 2*mySize.x;
+ else
+ strength_offset.x = 2*mySize.x;
+ }
+ else
+ {
+ mySize.y *= (1.0 / 3.0);
+ superweapons_offset.y = mySize.y;
+ if (autocvar_hud_panel_powerups_flip)
+ shield_offset.y = 2*mySize.y;
+ else
+ strength_offset.y = 2*mySize.y;
+ }
+ }
+ else
+ {
+ if (panel_ar >= 4 || (panel_ar >= 1/4 && panel_ar < 1))
+ {
+ mySize.x *= 0.5;
+ if (autocvar_hud_panel_powerups_flip)
+ shield_offset.x = mySize.x;
+ else
+ strength_offset.x = mySize.x;
+ }
+ else
+ {
+ mySize.y *= 0.5;
+ if (autocvar_hud_panel_powerups_flip)
+ shield_offset.y = mySize.y;
+ else
+ strength_offset.y = mySize.y;
+ }
+ }
+
+ float shield_baralign, strength_baralign, superweapons_baralign;
+ float shield_iconalign, strength_iconalign, superweapons_iconalign;
if (autocvar_hud_panel_powerups_flip)
{
- superweapons_baralign = (autocvar_hud_panel_powerups_baralign == 3 || autocvar_hud_panel_powerups_baralign == 1);
- superweapons_iconalign = (autocvar_hud_panel_powerups_iconalign == 3 || autocvar_hud_panel_powerups_iconalign == 1);
+ strength_baralign = (autocvar_hud_panel_powerups_baralign == 2 || autocvar_hud_panel_powerups_baralign == 1);
+ shield_baralign = (autocvar_hud_panel_powerups_baralign == 3 || autocvar_hud_panel_powerups_baralign == 1);
+ strength_iconalign = (autocvar_hud_panel_powerups_iconalign == 2 || autocvar_hud_panel_powerups_iconalign == 1);
+ shield_iconalign = (autocvar_hud_panel_powerups_iconalign == 3 || autocvar_hud_panel_powerups_iconalign == 1);
}
else
{
- superweapons_baralign = (autocvar_hud_panel_powerups_baralign == 2 || autocvar_hud_panel_powerups_baralign == 1);
- superweapons_iconalign = (autocvar_hud_panel_powerups_iconalign == 2 || autocvar_hud_panel_powerups_iconalign == 1);
+ shield_baralign = (autocvar_hud_panel_powerups_baralign == 2 || autocvar_hud_panel_powerups_baralign == 1);
+ strength_baralign = (autocvar_hud_panel_powerups_baralign == 3 || autocvar_hud_panel_powerups_baralign == 1);
+ shield_iconalign = (autocvar_hud_panel_powerups_iconalign == 2 || autocvar_hud_panel_powerups_iconalign == 1);
+ strength_iconalign = (autocvar_hud_panel_powerups_iconalign == 3 || autocvar_hud_panel_powerups_iconalign == 1);
+ }
+
+ if(superweapons_is == 0)
+ {
+ superweapons_iconalign = strength_iconalign;
+ superweapons_baralign = 2;
+ }
+ else if(superweapons_is == 1)
+ {
+ superweapons_offset = strength_offset;
+ superweapons_iconalign = strength_iconalign;
+ superweapons_baralign = strength_baralign;
+ }
+ else // if(superweapons_is == 2)
+ {
+ superweapons_offset = shield_offset;
+ superweapons_iconalign = shield_iconalign;
+ superweapons_baralign = shield_baralign;
+ }
+
+ if(shield_time)
+ {
+ const float maxshield = 30;
+ float shield = ceil(shield_time);
+ if(autocvar_hud_panel_powerups_progressbar)
+ HUD_Panel_DrawProgressBar(pos + shield_offset, mySize, autocvar_hud_panel_powerups_progressbar_shield, shield/maxshield, is_vertical, shield_baralign, autocvar_hud_progressbar_shield_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ if(autocvar_hud_panel_powerups_text)
+ {
+ if(shield > 1)
+ DrawNumIcon(pos + shield_offset, mySize, shield, "shield", is_vertical, shield_iconalign, '1 1 1', 1);
+ if(shield <= 5)
+ DrawNumIcon_expanding(pos + shield_offset, mySize, shield, "shield", is_vertical, shield_iconalign, '1 1 1', 1, bound(0, (shield - shield_time) / 0.5, 1));
+ }
+ }
+
+ if(strength_time)
+ {
+ const float maxstrength = 30;
+ float strength = ceil(strength_time);
+ if(autocvar_hud_panel_powerups_progressbar)
+ HUD_Panel_DrawProgressBar(pos + strength_offset, mySize, autocvar_hud_panel_powerups_progressbar_strength, strength/maxstrength, is_vertical, strength_baralign, autocvar_hud_progressbar_strength_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ if(autocvar_hud_panel_powerups_text)
+ {
+ if(strength > 1)
+ DrawNumIcon(pos + strength_offset, mySize, strength, "strength", is_vertical, strength_iconalign, '1 1 1', 1);
+ if(strength <= 5)
+ DrawNumIcon_expanding(pos + strength_offset, mySize, strength, "strength", is_vertical, strength_iconalign, '1 1 1', 1, bound(0, (strength - strength_time) / 0.5, 1));
+ }
}
if(superweapons_time)
{
- float maxsuperweapons = 30;
+ const float maxsuperweapons = 30;
float superweapons = ceil(superweapons_time);
if(autocvar_hud_panel_powerups_progressbar)
HUD_Panel_DrawProgressBar(pos + superweapons_offset, mySize, autocvar_hud_panel_powerups_progressbar_superweapons, superweapons/maxsuperweapons, is_vertical, superweapons_baralign, autocvar_hud_progressbar_superweapons_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
HUD_Write("\n");
HUD_Write_Cvar_q("hud_progressbar_alpha");
+ HUD_Write_Cvar_q("hud_progressbar_strength_color");
+ HUD_Write_Cvar_q("hud_progressbar_shield_color");
HUD_Write_Cvar_q("hud_progressbar_health_color");
HUD_Write_Cvar_q("hud_progressbar_armor_color");
HUD_Write_Cvar_q("hud_progressbar_fuel_color");
HUD_Write_PanelCvar_q("_iconalign");
HUD_Write_PanelCvar_q("_baralign");
HUD_Write_PanelCvar_q("_progressbar");
+ HUD_Write_PanelCvar_q("_progressbar_strength");
+ HUD_Write_PanelCvar_q("_progressbar_shield");
HUD_Write_PanelCvar_q("_text");
break;
case HUD_PANEL_HEALTHARMOR:
}
// edge detection postprocess handling done second (used by hud_powerup)
- float sharpen_intensity = 0, buffs = getstati(STAT_BUFFS, 0, 24);
- entity e;
- for(e = Buff_Type_first; e; e = e.enemy)
- if(buffs & e.items)
- ++sharpen_intensity;
+ float sharpen_intensity = 0, strength_finished = getstatf(STAT_STRENGTH_FINISHED), invincible_finished = getstatf(STAT_INVINCIBLE_FINISHED);
+ if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
+ if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
sharpen_intensity = bound(0, ((getstati(STAT_HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds.
case "item-invis": return 2;
case "item-extralife": return 2;
case "item-speed": return 2;
+ case "item-strength": return 2;
+ case "item-shield": return 2;
case "item-fuelregen": return 2;
case "item-jetpack": return 2;
case "tagged-target": return 2;
case "item-invis": return _("Invisibility");
case "item-extralife": return _("Extra life");
case "item-speed": return _("Speed");
+ case "item-strength": return _("Strength");
+ case "item-shield": return _("Shield");
case "item-fuelregen": return _("Fuel regen");
case "item-jetpack": return _("Jet Pack");
case "frozen": return _("Frozen!");
MULTITEAM_INFO(1, INFO_ONSLAUGHT_CPDESTROYED_, 4, 2, 0, "s1 s2", "", "", _("^TC^TT^BG team %s^BG control point has been destroyed by %s"), "") \
MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_, 4, 0, 0, "", "", "", _("^TC^TT^BG generator has been destroyed"), "") \
MULTITEAM_INFO(1, INFO_ONSLAUGHT_GENDESTROYED_OVERTIME_, 4, 0, 0, "", "", "", _("^TC^TT^BG generator spontaneously combusted due to overtime!"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_INVISIBILITY, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Invisibility"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_SHIELD, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Shield"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_SPEED, 1, 0, "s1", "s1", "shield", _("^BG%s^K1 picked up Speed"), "") \
+ MSG_INFO_NOTIF(1, INFO_POWERUP_STRENGTH, 1, 0, "s1", "s1", "strength", _("^BG%s^K1 picked up Strength"), "") \
MSG_INFO_NOTIF(2, INFO_QUIT_DISCONNECT, 1, 0, "s1", "", "", _("^BG%s^F3 disconnected"), "") \
MSG_INFO_NOTIF(2, INFO_QUIT_KICK_IDLING, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for idling"), "") \
MSG_INFO_NOTIF(1, INFO_QUIT_KICK_SPECTATING, 0, 0, "", "", "", _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment."), "") \
MSG_CENTER_NOTIF(1, CENTER_PORTO_FAILED, 0, 0, "", NO_CPID, "0 0", _("^K1Portal deployment failed.\n\n^F2Catch it to try again!"), "") \
MSG_CENTER_NOTIF(1, CENTER_PORTO_CREATED_IN, 0, 0, "", NO_CPID, "0 0", _("^K1In^BG-portal created"), "") \
MSG_CENTER_NOTIF(1, CENTER_PORTO_CREATED_OUT, 0, 0, "", NO_CPID, "0 0", _("^F3Out^BG-portal created"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_INVISIBILITY, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Invisibility has worn off"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_SHIELD, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Shield has worn off"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_SPEED, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Speed has worn off"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERDOWN_STRENGTH, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Strength has worn off"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERUP_INVISIBILITY, 0, 0, "", CPID_POWERUP, "0 0", _("^F2You are invisible"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERUP_SHIELD, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Shield surrounds you"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERUP_SPEED, 0, 0, "", CPID_POWERUP, "0 0", _("^F2You are on speed"), "") \
+ MSG_CENTER_NOTIF(1, CENTER_POWERUP_STRENGTH, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Strength infuses your weapons with devastating power"), "") \
MSG_CENTER_NOTIF(1, CENTER_RACE_FINISHLAP, 0, 0, "", CPID_RACE_FINISHLAP, "0 0", _("^F2The race is over, finish your lap!"), "") \
MSG_CENTER_NOTIF(1, CENTER_SECONDARY_NODAMAGE, 0, 0, "", NO_CPID, "0 0", _("^BGSecondary fire inflicts no damage!"), "") \
MSG_CENTER_NOTIF(1, CENTER_SEQUENCE_COMPLETED, 0, 0, "", NO_CPID, "0 0", _("^BGSequence completed!"), "") \
gren.think = W_Porto_Think;
gren.touch = W_Porto_Touch;
- W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed), 0);
+ if(self.items & IT_STRENGTH)
+ W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed) * autocvar_g_balance_powerup_strength_force, 0);
+ else
+ W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed), 0);
gren.angles = vectoangles(gren.velocity);
gren.flags = FL_PROJECTILE;
// set start time of melee
if(!self.cnt)
{
- self.cnt = time;
+ self.cnt = time;
+ W_PlayStrengthSound(self.realowner);
}
// update values for v_* vectors
if(!self.cnt) // set start time of melee
{
self.cnt = time;
+ W_PlayStrengthSound(self.realowner);
}
makevectors(self.realowner.v_angle); // update values for v_* vectors
float autocvar_g_balance_pause_health_rot_spawn;
float autocvar_g_balance_portal_health;
float autocvar_g_balance_portal_lifetime;
+float autocvar_g_balance_powerup_invincible_takedamage;
+float autocvar_g_balance_powerup_invincible_time;
+float autocvar_g_balance_powerup_strength_damage;
+float autocvar_g_balance_powerup_strength_force;
+float autocvar_g_balance_powerup_strength_selfdamage;
+float autocvar_g_balance_powerup_strength_selfforce;
+float autocvar_g_balance_powerup_strength_time;
float autocvar_g_balance_superweapons_time;
float autocvar_g_balance_selfdamagepercent;
float autocvar_g_balance_teams;
float autocvar_g_ctf_throw_punish_count;
float autocvar_g_ctf_throw_punish_delay;
float autocvar_g_ctf_throw_punish_time;
+float autocvar_g_ctf_throw_strengthmultiplier;
float autocvar_g_ctf_throw_velocity_forward;
float autocvar_g_ctf_throw_velocity_up;
float autocvar_g_ctf_drop_velocity_up;
float autocvar_g_instagib_ammo_drop;
float autocvar_g_instagib_ammo_rockets;
float autocvar_g_instagib_extralives;
+float autocvar_g_instagib_speed_highspeed;
+float autocvar_g_instagib_invis_alpha;
float autocvar_g_instagib_damagedbycontents;
float autocvar_g_instagib_blaster_keepdamage;
float autocvar_g_instagib_blaster_keepforce;
//float autocvar_g_nick_flood_timeout;
float autocvar_g_nix_with_healtharmor;
float autocvar_g_nix_with_blaster;
+float autocvar_g_nix_with_powerups;
float autocvar_g_nodepthtestitems;
float autocvar_g_nodepthtestplayers;
float autocvar_g_norecoil;
float autocvar_g_player_alpha;
float autocvar_g_player_brightness;
float autocvar_g_playerclip_collisions;
+float autocvar_g_powerups;
float autocvar_g_projectiles_damage;
float autocvar_g_projectiles_keep_owner;
float autocvar_g_projectiles_newton_style;
float autocvar_sv_spectator_speed_multiplier;
float autocvar_sv_status_privacy;
float autocvar_sv_stepheight;
+float autocvar_sv_strengthsound_antispam_refire_threshold;
+float autocvar_sv_strengthsound_antispam_time;
float autocvar_sv_teamnagger;
float autocvar_sv_timeout;
float autocvar_sv_timeout_leadtime;
self.personal.pauserothealth_finished = self.pauserothealth_finished;
self.personal.pauserotfuel_finished = self.pauserotfuel_finished;
self.personal.pauseregen_finished = self.pauseregen_finished;
+ self.personal.strength_finished = self.strength_finished;
+ self.personal.invincible_finished = self.invincible_finished;
self.personal.teleport_time = time;
break; // this part itself doesn't cheat, so let's not count this
case CHIMPULSE_CLONE_MOVING:
self.pauserothealth_finished = time + self.personal.pauserothealth_finished - self.personal.teleport_time;
self.pauserotfuel_finished = time + self.personal.pauserotfuel_finished - self.personal.teleport_time;
self.pauseregen_finished = time + self.personal.pauseregen_finished - self.personal.teleport_time;
+ self.strength_finished = time + self.personal.strength_finished - self.personal.teleport_time;
+ self.invincible_finished = time + self.personal.invincible_finished - self.personal.teleport_time;
DID_CHEAT();
break;
self.fade_time = 0;
self.pain_frame = 0;
self.pain_finished = 0;
+ self.strength_finished = 0;
+ self.invincible_finished = 0;
self.superweapons_finished = 0;
self.pushltime = 0;
self.istypefrag = 0;
self.fade_time = 0;
self.pain_frame = 0;
self.pain_finished = 0;
+ self.strength_finished = 0;
+ self.invincible_finished = 0;
self.pushltime = 0;
// players have no think function
self.think = func_null;
if (!g_instagib)
{
+ if (self.items & IT_STRENGTH)
+ {
+ play_countdown(self.strength_finished, "misc/poweroff.wav");
+ self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
+ if (time > self.strength_finished)
+ {
+ self.items = self.items - (self.items & IT_STRENGTH);
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_STRENGTH, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
+ }
+ }
+ else
+ {
+ if (time < self.strength_finished)
+ {
+ self.items = self.items | IT_STRENGTH;
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_STRENGTH, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_STRENGTH);
+ }
+ }
+ if (self.items & IT_INVINCIBLE)
+ {
+ play_countdown(self.invincible_finished, "misc/poweroff.wav");
+ self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
+ if (time > self.invincible_finished)
+ {
+ self.items = self.items - (self.items & IT_INVINCIBLE);
+ //Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERDOWN_SHIELD, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
+ }
+ }
+ else
+ {
+ if (time < self.invincible_finished)
+ {
+ self.items = self.items | IT_INVINCIBLE;
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SHIELD, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SHIELD);
+ }
+ }
if (self.items & IT_SUPERWEAPON)
{
if (!(self.weapons & WEPSET_SUPERWEAPONS))
self.last_pickup = spectatee.last_pickup;
self.hit_time = spectatee.hit_time;
self.metertime = spectatee.metertime;
+ self.strength_finished = spectatee.strength_finished;
+ self.invincible_finished = spectatee.invincible_finished;
self.pressedkeys = spectatee.pressedkeys;
self.weapons = spectatee.weapons;
self.switchweapon = spectatee.switchweapon;
if(w == 0)
w = player.cnt; // previous weapon!
s = strcat(s, ftos(w));
+ if(time < player.strength_finished)
+ s = strcat(s, "S");
+ if(time < player.invincible_finished)
+ s = strcat(s, "I");
if(player.flagcarried != world)
s = strcat(s, "F");
if(player.BUTTON_CHAT)
self = oldself;
}
+ if(!g_instagib)
+ {
+ // apply strength multiplier
+ if (attacker.items & IT_STRENGTH)
+ {
+ if(targ == attacker)
+ {
+ damage = damage * autocvar_g_balance_powerup_strength_selfdamage;
+ force = force * autocvar_g_balance_powerup_strength_selfforce;
+ }
+ else
+ {
+ damage = damage * autocvar_g_balance_powerup_strength_damage;
+ force = force * autocvar_g_balance_powerup_strength_force;
+ }
+ }
+
+ // apply invincibility multiplier
+ if (targ.items & IT_INVINCIBLE)
+ damage = damage * autocvar_g_balance_powerup_invincible_takedamage;
+ }
+
if (targ == attacker)
damage = damage * autocvar_g_balance_selfdamagepercent; // Partial damage if the attacker hits himself
if(autocvar_g_norecoil)
s = strcat(s, ":norecoil");
+ // TODO to mutator system
+ if(autocvar_g_powerups == 0)
+ s = strcat(s, ":no_powerups");
+ if(autocvar_g_powerups > 0)
+ s = strcat(s, ":powerups");
+
GameLogEcho(s);
GameLogEcho(":gameinfo:end");
}
addstat(STAT_ALLOW_OLDVORTEXBEAM, AS_INT, stat_allow_oldvortexbeam);
Nagger_Init();
+ addstat(STAT_STRENGTH_FINISHED, AS_FLOAT, strength_finished);
+ addstat(STAT_INVINCIBLE_FINISHED, AS_FLOAT, invincible_finished);
addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished);
addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys);
addstat(STAT_FUEL, AS_INT, ammo_fuel);
{
makevectors((player.v_angle.y * '0 1 0') + (bound(autocvar_g_ctf_throw_angle_min, player.v_angle.x, autocvar_g_ctf_throw_angle_max) * '1 0 0'));
- flag_velocity = (('0 0 1' * autocvar_g_ctf_throw_velocity_up) + ((v_forward * autocvar_g_ctf_throw_velocity_forward)));
+ flag_velocity = (('0 0 1' * autocvar_g_ctf_throw_velocity_up) + ((v_forward * autocvar_g_ctf_throw_velocity_forward) * ((player.items & IT_STRENGTH) ? autocvar_g_ctf_throw_strengthmultiplier : 1)));
flag.velocity = W_CalculateProjectileVelocity(player.velocity, flag_velocity, false);
ctf_Handle_Drop(flag, player, droptype);
break;
if(self.oldbuffs & BUFF_INVISIBLE)
{
- self.alpha = self.buff_invisible_prev_alpha;
+ if(time < self.strength_finished && g_instagib)
+ self.alpha = autocvar_g_instagib_invis_alpha;
+ else
+ self.alpha = self.buff_invisible_prev_alpha;
}
else if(self.buffs & BUFF_INVISIBLE)
{
- self.buff_invisible_prev_alpha = self.alpha;
+ if(time < self.strength_finished && g_instagib)
+ self.buff_invisible_prev_alpha = default_player_alpha;
+ else
+ self.buff_invisible_prev_alpha = self.alpha;
self.alpha = autocvar_g_buffs_invisible_alpha;
}
return false;
}
+MUTATOR_HOOKFUNCTION(instagib_BotShouldAttack)
+{
+ if(other.items & IT_STRENGTH)
+ return true;
+
+ return false;
+}
+
MUTATOR_HOOKFUNCTION(instagib_MakePlayerObserver)
{
instagib_stop_countdown(self);
{
if (!(self.effects & EF_FULLBRIGHT))
self.effects |= EF_FULLBRIGHT;
+
+ if (self.items & IT_STRENGTH)
+ {
+ play_countdown(self.strength_finished, "misc/poweroff.wav");
+ if (time > self.strength_finished)
+ {
+ self.alpha = default_player_alpha;
+ self.exteriorweaponentity.alpha = default_weapon_alpha;
+ self.items &= ~IT_STRENGTH;
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_INVISIBILITY);
+ }
+ }
+ else
+ {
+ if (time < self.strength_finished)
+ {
+ self.alpha = autocvar_g_instagib_invis_alpha;
+ self.exteriorweaponentity.alpha = autocvar_g_instagib_invis_alpha;
+ self.items |= IT_STRENGTH;
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_INVISIBILITY, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_INVISIBILITY);
+ }
+ }
+
+ if (self.items & IT_INVINCIBLE)
+ {
+ play_countdown(self.invincible_finished, "misc/poweroff.wav");
+ if (time > self.invincible_finished)
+ {
+ self.items &= ~IT_INVINCIBLE;
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERDOWN_SPEED);
+ }
+ }
+ else
+ {
+ if (time < self.invincible_finished)
+ {
+ self.items |= IT_INVINCIBLE;
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_POWERUP_SPEED, self.netname);
+ Send_Notification(NOTIF_ONE, self, MSG_CENTER, CENTER_POWERUP_SPEED);
+ }
+ }
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(instagib_PlayerPhysics)
+{
+ if(self.items & IT_INVINCIBLE)
+ self.stat_sv_maxspeed = self.stat_sv_maxspeed * autocvar_g_instagib_speed_highspeed;
+
return false;
}
frag_mirrordamage = 0;
}
- if(frag_target.buffs & BUFF_INVISIBLE)
+ if((frag_target.buffs & BUFF_INVISIBLE) || (frag_target.items & IT_STRENGTH))
yoda = 1;
return false;
return true;
}
+MUTATOR_HOOKFUNCTION(instagib_CustomizeWaypoint)
+{
+ entity e = WaypointSprite_getviewentity(other);
+
+ // if you have the invisibility powerup, sprites ALWAYS are restricted to your team
+ // but only apply this to real players, not to spectators
+ if((self.owner.flags & FL_CLIENT) && (self.owner.items & IT_STRENGTH) && (e == other))
+ if(DIFF_TEAM(self.owner, e))
+ return true;
+
+ return false;
+}
+
MUTATOR_HOOKFUNCTION(instagib_ItemCountdown)
{
switch(self.items)
{
+ case IT_STRENGTH: item_name = "item-invis"; item_color = '0 0 1'; break;
case IT_NAILS: item_name = "item-extralife"; item_color = '1 0 0'; break;
+ case IT_INVINCIBLE: item_name = "item-speed"; item_color = '1 0 1'; break;
}
return false;
}
if(random() <= 0.5)
instagib_item_supercells();
- return false;
+ if(!autocvar_g_powerups) { return false; }
+ if(!(self.classname == "item_strength" || self.classname == "item_invincible" || self.classname == "item_health_mega"))
+ return false;
+
+ entity e = spawn();
+
+ if(random() < 0.3)
+ e.think = spawnfunc_item_strength;
+ else if(random() < 0.6)
+ e.think = instagib_health_mega;
+ else
+ e.think = spawnfunc_item_invincible;
+
+ e.nextthink = time + 0.1;
+ e.spawnflags = self.spawnflags;
+ e.noalign = self.noalign;
+ setorigin(e, self.origin);
+
+ return true;
}
MUTATOR_HOOKFUNCTION(instagib_BuildMutatorsString)
MUTATOR_HOOK(MatchEnd, instagib_MatchEnd, CBC_ORDER_ANY);
MUTATOR_HOOK(MonsterDropItem, instagib_MonsterLoot, CBC_ORDER_ANY);
MUTATOR_HOOK(MonsterSpawn, instagib_MonsterSpawn, CBC_ORDER_ANY);
+ MUTATOR_HOOK(BotShouldAttack, instagib_BotShouldAttack, CBC_ORDER_ANY);
+ MUTATOR_HOOK(PlayerPhysics, instagib_PlayerPhysics, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerSpawn, instagib_PlayerSpawn, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerDamage_Calculate, instagib_PlayerDamage, CBC_ORDER_ANY);
MUTATOR_HOOK(MakePlayerObserver, instagib_MakePlayerObserver, CBC_ORDER_ANY);
MUTATOR_HOOK(SetStartItems, instagib_SetStartItems, CBC_ORDER_ANY);
MUTATOR_HOOK(ItemTouch, instagib_ItemTouch, CBC_ORDER_ANY);
MUTATOR_HOOK(FilterItem, instagib_FilterItem, CBC_ORDER_ANY);
+ MUTATOR_HOOK(CustomizeWaypoint, instagib_CustomizeWaypoint, CBC_ORDER_ANY);
MUTATOR_HOOK(Item_RespawnCountdown, instagib_ItemCountdown, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerDies, instagib_PlayerDies, CBC_ORDER_ANY);
MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, instagib_SplitHealthArmor, CBC_ORDER_ANY);
if (autocvar_g_nix_with_healtharmor)
return 0;
break;
+ case IT_STRENGTH:
+ case IT_INVINCIBLE:
+ if (autocvar_g_nix_with_powerups)
+ return 0;
+ break;
}
return 1; // delete all other items
#define _SSMAGIX "SUPERSPEC_OPTIONSFILE_V1"
#define _ISLOCAL ((edict_num(1) == self) ? true : false)
+const float ASF_STRENGTH = 1;
+const float ASF_SHIELD = 2;
const float ASF_MEGA_AR = 4;
const float ASF_MEGA_HP = 8;
const float ASF_FLAG_GRAB = 16;
}
}
- if( (self.autospec_flags & ASF_MEGA_AR && _item.classname == "item_armor_large") ||
+ if((self.autospec_flags & ASF_SHIELD && _item.invincible_finished) ||
+ (self.autospec_flags & ASF_STRENGTH && _item.strength_finished) ||
+ (self.autospec_flags & ASF_MEGA_AR && _item.classname == "item_armor_large") ||
(self.autospec_flags & ASF_MEGA_HP && _item.classname == "item_health_mega") ||
(self.autospec_flags & ASF_FLAG_GRAB && _item.classname == "item_flag_team"))
{
if(argv(1) == "help")
{
_aspeco = "use cmd autospec [option] [on|off] to set options\n\n";
+ _aspeco = strcat(_aspeco, "^3 strength ^7(short^5 st^7) for automatic spectate on strength powerup\n");
+ _aspeco = strcat(_aspeco, "^3 shield ^7(short^5 sh^7) for automatic spectate on shield powerup\n");
_aspeco = strcat(_aspeco, "^3 mega_health ^7(short^5 mh^7) for automatic spectate on mega health\n");
_aspeco = strcat(_aspeco, "^3 mega_armor ^7(short^5 ma^7) for automatic spectate on mega armor\n");
_aspeco = strcat(_aspeco, "^3 flag_grab ^7(short^5 fg^7) for automatic spectate on CTF flag grab\n");
}
else
{
+ if((argv(i) == "strength") || (argv(i) == "st")) _bits |= ASF_STRENGTH;
+ if((argv(i) == "shield") || (argv(i) == "sh")) _bits |= ASF_SHIELD;
if((argv(i) == "mega_health") || (argv(i) == "mh")) _bits |= ASF_MEGA_HP;
if((argv(i) == "mega_armor") || (argv(i) == "ma")) _bits |= ASF_MEGA_AR;
if((argv(i) == "flag_grab") || (argv(i) == "fg")) _bits |= ASF_FLAG_GRAB;
}
_aspeco = "";
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_STRENGTH, "Strength", "strength", "st");
+ OPTIONINFO(self.autospec_flags, _aspeco, ASF_SHIELD, "Shield", "shield", "sh");
OPTIONINFO(self.autospec_flags, _aspeco, ASF_MEGA_HP, "Mega Health", "mega_health", "mh");
OPTIONINFO(self.autospec_flags, _aspeco, ASF_MEGA_AR, "Mega Armor", "mega_armor", "ma");
OPTIONINFO(self.autospec_flags, _aspeco, ASF_FLAG_GRAB, "Flag grab", "flag_grab","fg");
entity _player;
FOR_EACH_PLAYER(_player)
{
- if(_player.buffs)
+ if(_player.strength_finished > time || _player.invincible_finished > time)
return _spectate(_player);
}
return true;
}
+ if(cmd_name == "followstrength")
+ {
+ entity _player;
+ FOR_EACH_PLAYER(_player)
+ {
+ if(_player.strength_finished > time)
+ return _spectate(_player);
+ }
+
+ superspec_msg("", "", self, "No active Strength\n", 1);
+ return true;
+ }
+
+ if(cmd_name == "followshield")
+ {
+ entity _player;
+ FOR_EACH_PLAYER(_player)
+ {
+ if(_player.invincible_finished > time)
+ return _spectate(_player);
+ }
+
+ superspec_msg("", "", self, "No active Shield\n", 1);
+ return true;
+ }
+
if(cmd_name == "followfc")
{
if(!g_ctf)
item.SendFlags |= ISF_LOCATION;
}
-bool have_pickup_item(void)
+float have_pickup_item(void)
{
- if(autocvar_g_pickup_items > 0)
- return true;
- if(autocvar_g_pickup_items == 0)
- return false;
- if(g_weaponarena)
- if(self.weapons || (self.items & IT_AMMO))
- return false;
+ if(self.flags & FL_POWERUP)
+ {
+ if(autocvar_g_powerups > 0)
+ return true;
+ if(autocvar_g_powerups == 0)
+ return false;
+ }
+ else
+ {
+ if(autocvar_g_pickup_items > 0)
+ return true;
+ if(autocvar_g_pickup_items == 0)
+ return false;
+ if(g_weaponarena)
+ if(self.weapons || (self.items & IT_AMMO)) // no item or ammo pickups in weaponarena
+ return false;
+ }
return true;
}
e.ItemStatus &= ~ITS_AVAILABLE;
}
+ if (e.items & IT_STRENGTH || e.items & IT_INVINCIBLE)
+ e.ItemStatus |= ITS_POWERUP;
+
if (autocvar_g_nodepthtestitems)
e.effects |= EF_NODEPTHTEST;
void Item_Respawn (void)
{
Item_Show(self, 1);
- sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ // this is ugly...
+ if(self.items == IT_STRENGTH)
+ sound (self, CH_TRIGGER, "misc/strength_respawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ else if(self.items == IT_INVINCIBLE)
+ sound (self, CH_TRIGGER, "misc/shield_respawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
+ else
+ sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTEN_NORM); // play respawn sound
setorigin (self, self.origin);
self.think = Item_Think;
{
case IT_FUEL_REGEN: name = "item-fuelregen"; rgb = '1 0.5 0'; break;
case IT_JETPACK: name = "item-jetpack"; rgb = '0.5 0.5 0.5'; break;
+ case IT_STRENGTH: name = "item-strength"; rgb = '0 0 1'; break;
+ case IT_INVINCIBLE: name = "item-shield"; rgb = '1 0 1'; break;
}
item_name = name;
item_color = rgb;
Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_ITEM_WEAPON_GOT, item.netname);
}
+ if (item.strength_finished)
+ {
+ pickedup = true;
+ player.strength_finished = max(player.strength_finished, time) + item.strength_finished;
+ }
+ if (item.invincible_finished)
+ {
+ pickedup = true;
+ player.invincible_finished = max(player.invincible_finished, time) + item.invincible_finished;
+ }
if (item.superweapons_finished)
{
pickedup = true;
}
if (self.classname == "droppedweapon")
+ {
+ self.strength_finished = max(0, self.strength_finished - time);
+ self.invincible_finished = max(0, self.invincible_finished - time);
self.superweapons_finished = max(0, self.superweapons_finished - time);
+ }
if(!Item_GiveTo(self, other))
{
if (self.classname == "droppedweapon")
{
// undo what we did above
+ self.strength_finished += time;
+ self.invincible_finished += time;
self.superweapons_finished += time;
}
return;
self.takedamage = DAMAGE_YES;
self.event_damage = Item_Damage;
- if(self.superweapons_finished)
+ if(self.strength_finished || self.invincible_finished || self.superweapons_finished)
+ /*
+ if(self.items == 0)
+ if(!(self.weapons & ~WEPSET_SUPERWEAPONS)) // only superweapons
+ if(self.ammo_nails == 0)
+ if(self.ammo_cells == 0)
+ if(self.ammo_rockets == 0)
+ if(self.ammo_shells == 0)
+ if(self.ammo_fuel == 0)
+ if(self.health == 0)
+ if(self.armorvalue == 0)
+ */
{
// if item is worthless after a timer, have it expire then
- self.nextthink = self.superweapons_finished;
+ self.nextthink = max(self.strength_finished, self.invincible_finished, self.superweapons_finished);
}
// don't drop if in a NODROP zone (such as lava)
precache_sound (self.item_pickupsound);
precache_sound ("misc/itemrespawncountdown.wav");
- precache_sound ("misc/itemrespawn.wav");
+ if(itemid == IT_STRENGTH)
+ precache_sound ("misc/strength_respawn.wav");
+ else if(itemid == IT_INVINCIBLE)
+ precache_sound ("misc/shield_respawn.wav");
+ else
+ precache_sound ("misc/itemrespawn.wav");
if((itemflags & (FL_POWERUP | FL_WEAPON)) || (itemid & (IT_HEALTH | IT_ARMOR | IT_KEY1 | IT_KEY2)))
self.target = "###item###"; // for finding the nearest item using find()
void spawnfunc_item_health25() { spawnfunc_item_health_medium(); }
void spawnfunc_item_health100() { spawnfunc_item_health_mega(); }
-// mutator hookable items
-void spawnfunc_item_strength() { /* dummy item */ }
-void spawnfunc_item_invincible() { /* dummy item */ }
+void spawnfunc_item_strength (void) {
+ precache_sound("weapons/strength_fire.wav");
+ if(!self.strength_finished)
+ self.strength_finished = autocvar_g_balance_powerup_strength_time;
+ StartItem ("models/items/g_strength.md3", "misc/powerup.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Strength Powerup", IT_STRENGTH, 0, FL_POWERUP, generic_pickupevalfunc, 100000);
+}
+
+void spawnfunc_item_invincible (void) {
+ if(!self.invincible_finished)
+ self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
+ StartItem ("models/items/g_invincible.md3", "misc/powerup_shield.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Shield", IT_INVINCIBLE, 0, FL_POWERUP, generic_pickupevalfunc, 100000);
+}
// compatibility:
void spawnfunc_item_quad (void) {self.classname = "item_strength";spawnfunc_item_strength();}
string s;
self.use = target_items_use;
+ if(!self.strength_finished)
+ self.strength_finished = autocvar_g_balance_powerup_strength_time;
+ if(!self.invincible_finished)
+ self.invincible_finished = autocvar_g_balance_powerup_invincible_time;
if(!self.superweapons_finished)
self.superweapons_finished = autocvar_g_balance_superweapons_time;
if (argv(i) == "unlimited_ammo") self.items |= IT_UNLIMITED_AMMO;
else if(argv(i) == "unlimited_weapon_ammo") self.items |= IT_UNLIMITED_WEAPON_AMMO;
else if(argv(i) == "unlimited_superweapons") self.items |= IT_UNLIMITED_SUPERWEAPONS;
+ else if(argv(i) == "strength") self.items |= IT_STRENGTH;
+ else if(argv(i) == "invincible") self.items |= IT_INVINCIBLE;
else if(argv(i) == "superweapons") self.items |= IT_SUPERWEAPON;
else if(argv(i) == "jetpack") self.items |= IT_JETPACK;
else if(argv(i) == "fuel_regen") self.items |= IT_FUEL_REGEN;
self.netname = "";
self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_UNLIMITED_WEAPON_AMMO), "unlimited_weapon_ammo");
self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
+ self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.strength_finished * !!(self.items & IT_STRENGTH), "strength");
+ self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.invincible_finished * !!(self.items & IT_INVINCIBLE), "invincible");
self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, self.superweapons_finished * !!(self.items & IT_SUPERWEAPON), "superweapons");
self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_JETPACK), "jetpack");
self.netname = sprintf("%s %s%d %s", self.netname, itemprefix, !!(self.items & IT_FUEL_REGEN), "fuel_regen");
if (e.switchweapon == w_getbestweapon(e))
_switchweapon = true;
+ e.strength_finished = max(0, e.strength_finished - time);
+ e.invincible_finished = max(0, e.invincible_finished - time);
e.superweapons_finished = max(0, e.superweapons_finished - time);
PREGIVE(e, items);
PREGIVE_WEAPONS(e);
+ PREGIVE(e, strength_finished);
+ PREGIVE(e, invincible_finished);
PREGIVE(e, superweapons_finished);
PREGIVE(e, ammo_nails);
PREGIVE(e, ammo_cells);
continue;
case "ALL":
got += GiveBit(e, items, IT_FUEL_REGEN, op, val);
+ got += GiveValue(e, strength_finished, op, val);
+ got += GiveValue(e, invincible_finished, op, val);
got += GiveValue(e, superweapons_finished, op, val);
got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
case "all":
case "fuel_regen":
got += GiveBit(e, items, IT_FUEL_REGEN, op, val);
break;
+ case "strength":
+ got += GiveValue(e, strength_finished, op, val);
+ break;
+ case "invincible":
+ got += GiveValue(e, invincible_finished, op, val);
+ break;
case "superweapons":
got += GiveValue(e, superweapons_finished, op, val);
break;
WEP_ACTION(wi.weapon, WR_INIT);
}
}
+ POSTGIVE_VALUE(e, strength_finished, 1, "misc/powerup.wav", "misc/poweroff.wav");
+ POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", "misc/poweroff.wav");
POSTGIVE_VALUE(e, ammo_nails, 0, "misc/itempickup.wav", string_null);
POSTGIVE_VALUE(e, ammo_cells, 0, "misc/itempickup.wav", string_null);
POSTGIVE_VALUE(e, ammo_plasma, 0, "misc/itempickup.wav", string_null);
if(self.weapons & WEPSET_SUPERWEAPONS)
e.superweapons_finished = autocvar_g_balance_superweapons_time;
+ if(e.strength_finished <= 0)
+ e.strength_finished = 0;
+ else
+ e.strength_finished += time;
+ if(e.invincible_finished <= 0)
+ e.invincible_finished = 0;
+ else
+ e.invincible_finished += time;
if(e.superweapons_finished <= 0)
e.superweapons_finished = 0;
else
self = oldself;
}
+void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
+{
+ if((player.items & IT_STRENGTH)
+ && ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam
+ || (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)))
+ {
+ sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTEN_NORM);
+ player.prevstrengthsound = time;
+ }
+ player.prevstrengthsoundattempt = time;
+}
+
float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception)
{
float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA);
#define WEAPONS_COMMON_H
void W_GiveWeapon (entity e, float wep);
+.float prevstrengthsound;
+.float prevstrengthsoundattempt;
+void W_PlayStrengthSound(entity player);
float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception);
void W_PrepareExplosionByDamage(entity attacker, void() explode);
if (snd != "")
{
sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
+ W_PlayStrengthSound(ent);
}
// nudge w_shotend so a trace to w_shotend hits