From: Mario Date: Mon, 23 Mar 2015 00:31:38 +0000 (+1100) Subject: Bring back old powerups temporarily for tourney X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=b4efd89a89ab4db1b791ef9a8dc1a1c1af1eebea;p=xonotic%2Fxonotic-data.pk3dir.git Bring back old powerups temporarily for tourney --- diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index a721dc87a..9f6cac591 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -307,6 +307,8 @@ int autocvar_hud_panel_powerups_iconalign; 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; @@ -369,7 +371,9 @@ vector autocvar_hud_progressbar_armor_color; 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; diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 54971ff36..1e45bfc46 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -1292,14 +1292,16 @@ void DrawNumIcon(vector myPos, vector mySize, float x, string icon, float vertic // 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) @@ -1311,6 +1313,8 @@ void HUD_Powerups(void) } else { + strength_time = 15; + shield_time = 27; superweapons_time = 13; } @@ -1322,7 +1326,7 @@ void HUD_Powerups(void) 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; @@ -1331,29 +1335,139 @@ void HUD_Powerups(void) 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); diff --git a/qcsrc/client/hud_config.qc b/qcsrc/client/hud_config.qc index d5b3f0546..1b453e628 100644 --- a/qcsrc/client/hud_config.qc +++ b/qcsrc/client/hud_config.qc @@ -41,6 +41,8 @@ void HUD_Panel_ExportCfg(string cfgname) 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"); @@ -112,6 +114,8 @@ void HUD_Panel_ExportCfg(string cfgname) 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: diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index d1a8839fb..63a5809d9 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -1852,11 +1852,9 @@ void CSQC_UpdateView(float w, float h) } // 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. diff --git a/qcsrc/client/waypointsprites.qc b/qcsrc/client/waypointsprites.qc index 973a9b5ef..aca18c17c 100644 --- a/qcsrc/client/waypointsprites.qc +++ b/qcsrc/client/waypointsprites.qc @@ -157,6 +157,8 @@ float spritelookupblinkvalue(string s) 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; @@ -226,6 +228,8 @@ string spritelookuptext(string s) 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!"); diff --git a/qcsrc/common/notifications.qh b/qcsrc/common/notifications.qh index 9298d6e3a..0de2de451 100644 --- a/qcsrc/common/notifications.qh +++ b/qcsrc/common/notifications.qh @@ -531,6 +531,10 @@ void Send_Notification_WOCOVA( 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."), "") \ @@ -824,6 +828,14 @@ void Send_Notification_WOCOVA( 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!"), "") \ diff --git a/qcsrc/common/weapons/w_porto.qc b/qcsrc/common/weapons/w_porto.qc index 6f49dbffd..87b5af045 100644 --- a/qcsrc/common/weapons/w_porto.qc +++ b/qcsrc/common/weapons/w_porto.qc @@ -260,7 +260,10 @@ void W_Porto_Attack(float type) 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; diff --git a/qcsrc/common/weapons/w_shockwave.qc b/qcsrc/common/weapons/w_shockwave.qc index c69e2f976..9d8a73c43 100644 --- a/qcsrc/common/weapons/w_shockwave.qc +++ b/qcsrc/common/weapons/w_shockwave.qc @@ -123,7 +123,8 @@ void W_Shockwave_Melee_Think(void) // set start time of melee if(!self.cnt) { - self.cnt = time; + self.cnt = time; + W_PlayStrengthSound(self.realowner); } // update values for v_* vectors diff --git a/qcsrc/common/weapons/w_shotgun.qc b/qcsrc/common/weapons/w_shotgun.qc index d88a15159..994ba9278 100644 --- a/qcsrc/common/weapons/w_shotgun.qc +++ b/qcsrc/common/weapons/w_shotgun.qc @@ -94,6 +94,7 @@ void W_Shotgun_Melee_Think(void) 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 diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index c8f2a35fa..8ceff9aeb 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -160,6 +160,13 @@ float autocvar_g_balance_pause_health_rot; 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; @@ -215,6 +222,7 @@ float autocvar_g_ctf_throw_angle_min; 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; @@ -452,6 +460,8 @@ float autocvar_g_instagib_use_normal_ammo; 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; @@ -486,6 +496,7 @@ float autocvar_g_nick_flood_penalty_yellow; //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; @@ -499,6 +510,7 @@ float autocvar_g_pickup_shells_max; 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; @@ -667,6 +679,8 @@ float autocvar_sv_spectate; 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; diff --git a/qcsrc/server/cheats.qc b/qcsrc/server/cheats.qc index 9bc06ea88..6b331cd80 100644 --- a/qcsrc/server/cheats.qc +++ b/qcsrc/server/cheats.qc @@ -177,6 +177,8 @@ float CheatImpulse(float i) 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: @@ -234,6 +236,8 @@ float CheatImpulse(float i) 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; diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index 5b2b7043a..a26de6e02 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -304,6 +304,8 @@ void PutObserverInServer (void) 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; @@ -676,6 +678,8 @@ void PutClientInServer (void) 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; @@ -1646,6 +1650,46 @@ void player_powerups (void) 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)) @@ -1894,6 +1938,8 @@ void SpectateCopy(entity spectatee) { 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; diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index ec3b00021..0be216800 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -192,6 +192,10 @@ string AppendItemcodes(string s, entity player) 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) @@ -837,6 +841,28 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float 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 diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 60de30e0d..6d424816c 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -743,6 +743,12 @@ void spawnfunc_worldspawn (void) 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"); } @@ -807,6 +813,8 @@ void spawnfunc_worldspawn (void) 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); diff --git a/qcsrc/server/mutators/gamemode_ctf.qc b/qcsrc/server/mutators/gamemode_ctf.qc index 7e9565698..cc05b729e 100644 --- a/qcsrc/server/mutators/gamemode_ctf.qc +++ b/qcsrc/server/mutators/gamemode_ctf.qc @@ -377,7 +377,7 @@ void ctf_Handle_Throw(entity player, entity receiver, float droptype) { 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; diff --git a/qcsrc/server/mutators/mutator_buffs.qc b/qcsrc/server/mutators/mutator_buffs.qc index f710e89c5..b039e95f7 100644 --- a/qcsrc/server/mutators/mutator_buffs.qc +++ b/qcsrc/server/mutators/mutator_buffs.qc @@ -751,11 +751,17 @@ MUTATOR_HOOKFUNCTION(buffs_PlayerThink) 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; } diff --git a/qcsrc/server/mutators/mutator_instagib.qc b/qcsrc/server/mutators/mutator_instagib.qc index c6db80991..951f99bda 100644 --- a/qcsrc/server/mutators/mutator_instagib.qc +++ b/qcsrc/server/mutators/mutator_instagib.qc @@ -158,6 +158,14 @@ MUTATOR_HOOKFUNCTION(instagib_MonsterSpawn) return false; } +MUTATOR_HOOKFUNCTION(instagib_BotShouldAttack) +{ + if(other.items & IT_STRENGTH) + return true; + + return false; +} + MUTATOR_HOOKFUNCTION(instagib_MakePlayerObserver) { instagib_stop_countdown(self); @@ -186,6 +194,56 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerPowerups) { 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; } @@ -277,7 +335,7 @@ MUTATOR_HOOKFUNCTION(instagib_PlayerDamage) frag_mirrordamage = 0; } - if(frag_target.buffs & BUFF_INVISIBLE) + if((frag_target.buffs & BUFF_INVISIBLE) || (frag_target.items & IT_STRENGTH)) yoda = 1; return false; @@ -349,11 +407,26 @@ MUTATOR_HOOKFUNCTION(instagib_FilterItem) 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; } @@ -407,7 +480,25 @@ MUTATOR_HOOKFUNCTION(instagib_OnEntityPreSpawn) 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) @@ -433,12 +524,15 @@ MUTATOR_DEFINITION(mutator_instagib) 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); diff --git a/qcsrc/server/mutators/mutator_nix.qc b/qcsrc/server/mutators/mutator_nix.qc index 56b3d5261..a0ec6adaa 100644 --- a/qcsrc/server/mutators/mutator_nix.qc +++ b/qcsrc/server/mutators/mutator_nix.qc @@ -184,6 +184,11 @@ MUTATOR_HOOKFUNCTION(nix_FilterItem) 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 diff --git a/qcsrc/server/mutators/mutator_superspec.qc b/qcsrc/server/mutators/mutator_superspec.qc index 9a8ff07c4..da9e36a61 100644 --- a/qcsrc/server/mutators/mutator_superspec.qc +++ b/qcsrc/server/mutators/mutator_superspec.qc @@ -3,6 +3,8 @@ #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; @@ -117,7 +119,9 @@ MUTATOR_HOOKFUNCTION(superspec_ItemTouch) } } - 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")) { @@ -270,6 +274,8 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand) 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"); @@ -305,6 +311,8 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand) } 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; @@ -318,6 +326,8 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand) } _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"); @@ -335,7 +345,7 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand) entity _player; FOR_EACH_PLAYER(_player) { - if(_player.buffs) + if(_player.strength_finished > time || _player.invincible_finished > time) return _spectate(_player); } @@ -343,6 +353,32 @@ MUTATOR_HOOKFUNCTION(superspec_SV_ParseClientCommand) 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) diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc index 31799ac16..e96af453e 100644 --- a/qcsrc/server/t_items.qc +++ b/qcsrc/server/t_items.qc @@ -286,15 +286,25 @@ void ItemUpdate(entity item) 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; } @@ -364,6 +374,9 @@ void Item_Show (entity e, float mode) 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; @@ -392,7 +405,13 @@ void Item_Think() 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; @@ -422,6 +441,8 @@ void Item_RespawnCountdown (void) { 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; @@ -602,6 +623,16 @@ float Item_GiveTo(entity item, entity player) 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; @@ -661,13 +692,19 @@ void Item_Touch (void) } 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; @@ -949,10 +986,21 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, 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) @@ -1036,7 +1084,12 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, 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() @@ -1273,9 +1326,18 @@ void spawnfunc_item_health1() { spawnfunc_item_health_small(); } 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();} @@ -1311,6 +1373,10 @@ void spawnfunc_target_items (void) 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; @@ -1333,6 +1399,8 @@ void spawnfunc_target_items (void) 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; @@ -1385,6 +1453,8 @@ void spawnfunc_target_items (void) 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"); @@ -1579,10 +1649,14 @@ float GiveItems(entity e, float beginarg, float endarg) 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); @@ -1623,6 +1697,8 @@ float GiveItems(entity e, float beginarg, float endarg) 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": @@ -1661,6 +1737,12 @@ float GiveItems(entity e, float beginarg, float endarg) 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; @@ -1725,6 +1807,8 @@ float GiveItems(entity e, float beginarg, float endarg) 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); @@ -1739,6 +1823,14 @@ float GiveItems(entity e, float beginarg, float endarg) 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 diff --git a/qcsrc/server/weapons/common.qc b/qcsrc/server/weapons/common.qc index dfb232388..442765063 100644 --- a/qcsrc/server/weapons/common.qc +++ b/qcsrc/server/weapons/common.qc @@ -31,6 +31,18 @@ void W_GiveWeapon (entity e, float wep) 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); diff --git a/qcsrc/server/weapons/common.qh b/qcsrc/server/weapons/common.qh index a0f99999d..eeb197f37 100644 --- a/qcsrc/server/weapons/common.qh +++ b/qcsrc/server/weapons/common.qh @@ -2,6 +2,9 @@ #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); diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc index 302152e85..169e71187 100644 --- a/qcsrc/server/weapons/tracing.qc +++ b/qcsrc/server/weapons/tracing.qc @@ -131,6 +131,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector m if (snd != "") { sound (ent, chan, snd, VOL_BASE, ATTN_NORM); + W_PlayStrengthSound(ent); } // nudge w_shotend so a trace to w_shotend hits