From: unknown Date: Mon, 29 Nov 2010 08:01:35 +0000 (-0500) Subject: Lots and lots of updates, mainly involving spectators (waypoints are now not shown... X-Git-Tag: xonotic-v0.1.0preview~86^2~2^2~1^2~2 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=2c022461b9a9a44b84dbf8fd1b8b3063b5160141;p=xonotic%2Fxonotic-data.pk3dir.git Lots and lots of updates, mainly involving spectators (waypoints are now not shown to someone who is spectating the ballcarrier), the HUD (fixed an issue where scoreboard would re-play the ball pickup animation), ball size (It was too large and would get stuck in walls) and powerups (especially powerup effects, don't show a waypoint for ballcarrier who has invisibility) --- Still much more to be done, but this is a huge step forward --- diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg index 7a61616de..3b54b0c36 100644 --- a/defaultXonotic.cfg +++ b/defaultXonotic.cfg @@ -1250,6 +1250,7 @@ set g_keepaway 0 "game mode which focuses around a ball, look at g_keepaway_win_ set g_keepaway_bckillscore 1 "enable scoring points (y/n) for ball carrier kills" set g_keepaway_pointlimit -1 "total amount of points you can get, -1 for unlimited" set g_keepaway_pointleadlimit -1 "mercy rule, -1 for unlimited" +set g_keepaway_ballcarrier_alpha 0.6 "alpha when the player is the ballcarrier" set g_keepaway_ballcarrier_highspeed 1.5 "speed multiplier done to the person holding the ball" set g_keepaway_ballcarrier_damage 1.5 "damage multiplier while having powerup" set g_keepaway_ballcarrier_force 1.5 "force multiplier while having powerup" diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc index 15d31c16e..cc8b21e74 100644 --- a/qcsrc/client/hud.qc +++ b/qcsrc/client/hud.qc @@ -4327,10 +4327,9 @@ void HUD_Mod_KH(vector pos, vector mySize) float kaball_prevstatus; // last remembered status float kaball_statuschange_time; // time when the status changed -void HUD_Mod_Keepaway_Reset(void) -{ - kaball_prevstatus = kaball_statuschange_time = 0; -} +// we don't need to reset for keepaway since it immediately +// autocorrects prevstatus as to if the player has the ball or not + void HUD_Mod_Keepaway(vector pos, vector mySize) { mod_active = 1; // keepaway should always show the mod HUD @@ -4343,12 +4342,14 @@ void HUD_Mod_Keepaway(vector pos, vector mySize) float stat_items = getstati(STAT_ITEMS); float kaball = (stat_items/IT_KEY1) & 1; - if (kaball != kaball_prevstatus) + if(kaball != kaball_prevstatus) { kaball_statuschange_time = time; kaball_prevstatus = kaball; } + // todo: Fix the sizing with the expanding image + float kaball_statuschange_elapsedtime = time - kaball_statuschange_time; float f = bound(0, kaball_statuschange_elapsedtime*2, 1); @@ -5083,8 +5084,6 @@ void HUD_Reset (void) // reset gametype specific icons if(gametype == GAME_KEYHUNT) HUD_Mod_KH_Reset(); - else if(gametype == GAME_KEEPAWAY) - HUD_Mod_Keepaway_Reset(); else if(gametype == GAME_CTF) HUD_Mod_CTF_Reset(); } diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index f7764c07e..781836469 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -1987,6 +1987,9 @@ string getTimeoutText(float addOneSecond) { void player_powerups (void) { + // add a way to see what the items were BEFORE all of these checks for the mutator hook + olditems = self.items; + if((self.items & IT_USING_JETPACK) && !self.deadflag) { SoundEntity_StartSound(self, CHAN_PLAYER, "misc/jetpack_fly.wav", VOL_BASE, cvar("g_jetpack_attenuation")); @@ -2049,64 +2052,67 @@ void player_powerups (void) sprint(self, "^3You are on speed\n"); } } - return; } - - if (self.items & IT_STRENGTH) + else // if we're not in minstagib, continue. I added this else to replace the "return" which was here that broke the callhook for this function -- This code is nasty. { - play_countdown(self.strength_finished, "misc/poweroff.wav"); - self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT); - if (time > self.strength_finished && cvar("g_balance_powerup_timer")) + if (self.items & IT_STRENGTH) { - self.items = self.items - (self.items & IT_STRENGTH); - sprint(self, "^3Strength has worn off\n"); + play_countdown(self.strength_finished, "misc/poweroff.wav"); + self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT); + if (time > self.strength_finished && cvar("g_balance_powerup_timer")) + { + self.items = self.items - (self.items & IT_STRENGTH); + sprint(self, "^3Strength has worn off\n"); + } } - } - else - { - if (time < self.strength_finished) + else { - self.items = self.items | IT_STRENGTH; - sprint(self, "^3Strength infuses your weapons with devastating power\n"); + if (time < self.strength_finished) + { + self.items = self.items | IT_STRENGTH; + sprint(self, "^3Strength infuses your weapons with devastating power\n"); + } } - } - 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 && cvar("g_balance_powerup_timer")) + if (self.items & IT_INVINCIBLE) { - self.items = self.items - (self.items & IT_INVINCIBLE); - sprint(self, "^3Shield has worn off\n"); + play_countdown(self.invincible_finished, "misc/poweroff.wav"); + self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT); + if (time > self.invincible_finished && cvar("g_balance_powerup_timer")) + { + self.items = self.items - (self.items & IT_INVINCIBLE); + sprint(self, "^3Shield has worn off\n"); + } } - } - else - { - if (time < self.invincible_finished) + else { - self.items = self.items | IT_INVINCIBLE; - sprint(self, "^3Shield surrounds you\n"); + if (time < self.invincible_finished) + { + self.items = self.items | IT_INVINCIBLE; + sprint(self, "^3Shield surrounds you\n"); + } } - } - if(cvar("g_nodepthtestplayers")) - self.effects = self.effects | EF_NODEPTHTEST; + if(cvar("g_nodepthtestplayers")) + self.effects = self.effects | EF_NODEPTHTEST; - if(cvar("g_fullbrightplayers")) - self.effects = self.effects | EF_FULLBRIGHT; + if(cvar("g_fullbrightplayers")) + self.effects = self.effects | EF_FULLBRIGHT; - // midair gamemode: damage only while in the air - // if in midair mode, being on ground grants temporary invulnerability - // (this is so that multishot weapon don't clear the ground flag on the - // first damage in the frame, leaving the player vulnerable to the - // remaining hits in the same frame) - if (self.flags & FL_ONGROUND) - if (g_midair) - self.spawnshieldtime = max(self.spawnshieldtime, time + cvar("g_midair_shieldtime")); + // midair gamemode: damage only while in the air + // if in midair mode, being on ground grants temporary invulnerability + // (this is so that multishot weapon don't clear the ground flag on the + // first damage in the frame, leaving the player vulnerable to the + // remaining hits in the same frame) + if (self.flags & FL_ONGROUND) + if (g_midair) + self.spawnshieldtime = max(self.spawnshieldtime, time + cvar("g_midair_shieldtime")); - if (time >= game_starttime) - if (time < self.spawnshieldtime) - self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); + if (time >= game_starttime) + if (time < self.spawnshieldtime) + self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); + } + + MUTATOR_CALLHOOK(PlayerPowerups); } float CalcRegen(float current, float stable, float regenfactor, float regenframetime) diff --git a/qcsrc/server/mutators/base.qh b/qcsrc/server/mutators/base.qh index b254dfe84..974e1a4c5 100644 --- a/qcsrc/server/mutators/base.qh +++ b/qcsrc/server/mutators/base.qh @@ -139,3 +139,9 @@ MUTATOR_HOOKABLE(PlayerDamage_Calculate); // INPUT, OUTPUT: float frag_damage; vector frag_force; + +MUTATOR_HOOKABLE(PlayerPowerups); + // called at the end of player_powerups() in cl_client.qc, used for manipulating the values which are set by powerup items. + // INPUT + entity self; + float olditems; // also technically output, but since it is at the end of the function it's useless for that :P \ No newline at end of file diff --git a/qcsrc/server/mutators/gamemode_keepaway.qc b/qcsrc/server/mutators/gamemode_keepaway.qc index dd88aebc8..c771ab173 100644 --- a/qcsrc/server/mutators/gamemode_keepaway.qc +++ b/qcsrc/server/mutators/gamemode_keepaway.qc @@ -3,6 +3,8 @@ void ka_TouchEvent(void); void ka_RespawnBall(void); void ka_DropEvent(entity); +float ka_ballcarrier_waypointsprite_visible_for_player(entity); + void ka_Initialize() // run at the start of a match, initiates game mode { if(!g_keepaway) @@ -36,7 +38,7 @@ void ka_SpawnBall() // loads various values for the ball e.scale = 1; precache_model(e.model); setmodel(e, e.model); - setsize(e, '-20 -20 -20', '20 20 20'); + setsize(e, '-16 -16 -20', '16 16 20'); // 20 20 20 was too big, player is only 16 16 24... gotta cheat with the Z (20) axis so that the particle isn't cut off e.classname = "keepawayball"; e.damageforcescale = cvar("g_keepawayball_damageforcescale"); e.takedamage = DAMAGE_YES; @@ -72,7 +74,7 @@ void ka_RespawnBall() // runs whenever the ball needs to be relocated WaypointSprite_UpdateTeamRadar(self.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '0 1 1'); WaypointSprite_Ping(self.waypointsprite_attachedforcarrier); - sound(self, CHAN_AUTO, "keepaway/respawn.wav", VOL_BASE, ATTN_NONE); // no attenuation as this is a global sound + sound(self, CHAN_AUTO, "keepaway/respawn.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) } else { @@ -95,7 +97,7 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth sound(self, CHAN_AUTO, "keepaway/touch.wav", VOL_BASE, ATTN_NORM); return; } - if(self.wait > time) { return; } + else if(self.wait > time) { return; } // attach the ball to the player self.owner = other; @@ -115,20 +117,22 @@ void ka_TouchEvent() // runs any time that the ball comes in contact with someth // apply effects to player other.glow_color = cvar("g_keepawayball_trail_color"); other.glow_trail = TRUE; - other.effects |= 8; - other.alpha = 0.6; + other.effects |= EF_DIMLIGHT; + other.alpha = cvar("g_keepaway_ballcarrier_alpha"); + other.exteriorweaponentity.alpha = cvar("g_keepaway_ballcarrier_alpha"); // messages and sounds Send_KillNotification(other.netname, "", "", KA_PICKUPBALL, MSG_KA); WriteByte(MSG_BROADCAST, SVC_CENTERPRINT); WriteString(MSG_BROADCAST, strcat("\n\n", other.netname, "^7 has picked up the ball!\n")); - sound(self.owner, CHAN_AUTO, "keepaway/pickedup.wav", VOL_BASE, ATTN_NONE); + sound(self.owner, CHAN_AUTO, "keepaway/pickedup.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) // scoring PlayerScore_Add(other, SP_KEEPAWAY_PICKUPS, 1); // waypoints WaypointSprite_AttachCarrier("ka-ballcarrier", other); + other.waypointsprite_attachedforcarrier.waypointsprite_visible_for_player = ka_ballcarrier_waypointsprite_visible_for_player; WaypointSprite_UpdateRule(other.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT); WaypointSprite_UpdateTeamRadar(other.waypointsprite_attachedforcarrier, RADARICON_FLAGCARRIER, '1 0 0'); WaypointSprite_Ping(other.waypointsprite_attachedforcarrier); @@ -145,7 +149,7 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los // reset the ball setattachment(ball, world, ""); ball.movetype = MOVETYPE_BOUNCE; - ball.solid = SOLID_TRIGGER; + ball.solid = SOLID_TRIGGER; // is this needed? ball.wait = time + 1; ball.think = ka_RespawnBall; ball.nextthink = time + cvar("g_keepawayball_respawntime"); @@ -154,19 +158,20 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los ball.effects &~= EF_NODRAW; setorigin(ball, plyr.origin + '0 0 10'); ball.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom(); - ball.owner.ballcarried = world; + ball.owner.ballcarried = world; // I hope nothing checks to see if the world has the ball in the rest of my code :P ball.owner = world; // reset the player effects - plyr.effects &~= 8; - plyr.alpha = 1.0; + plyr.effects &~= EF_DIMLIGHT; + plyr.alpha = default_player_alpha; + plyr.exteriorweaponentity.alpha = default_weapon_alpha; plyr.glow_trail = FALSE; // messages and sounds Send_KillNotification(plyr.netname, "", "", KA_DROPBALL, MSG_KA); WriteByte(MSG_BROADCAST, SVC_CENTERPRINT); WriteString(MSG_BROADCAST, strcat("\n\n", plyr.netname, "^7 has dropped the ball!\n")); - sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE); + sound(other, CHAN_AUTO, "keepaway/dropped.wav", VOL_BASE, ATTN_NONE); // ATTN_NONE (it's a sound intended to be heard anywhere) // scoring PlayerScore_Add(plyr, SP_KEEPAWAY_DROPS, 1); @@ -179,6 +184,19 @@ void ka_DropEvent(entity plyr) // runs any time that a player is supposed to los WaypointSprite_Kill(plyr.waypointsprite_attachedforcarrier); } +float ka_ballcarrier_waypointsprite_visible_for_player(entity e) // runs on waypoints which are attached to ballcarriers, updates once per frame +{ + if(e.ballcarried) + { + if(other.classname == "spectator") + return FALSE; // we don't want spectators of the ballcarrier to see the attached waypoint on the top of their screen + else if(g_minstagib && (e.items & IT_STRENGTH)) + return FALSE; // if the ballcarrier has invisibility, don't draw the waypoint as this is the function of invisibility in keepaway + } + + return TRUE; +} + MUTATOR_HOOKFUNCTION(ka_RemovePlayer) { if(self.ballcarried) { ka_DropEvent(self); } // a player with the ball has left the match, drop it @@ -214,12 +232,15 @@ MUTATOR_HOOKFUNCTION(ka_GiveFragsForKill) MUTATOR_HOOKFUNCTION(ka_PlayerPreThink) { + // clear the item used for the ball in keepaway self.items &~= IT_KEY1; - + + // if the player has the ball, make sure they have the item for it (Used for HUD primarily) if(self.ballcarried) self.items |= IT_KEY1; - - if(self.BUTTON_USE) // drop the ball if the player presses the use button + + // drop the ball if the player presses the use button + if(self.BUTTON_USE) if(self.ballcarried) { ka_DropEvent(self); } return 0; @@ -227,7 +248,7 @@ MUTATOR_HOOKFUNCTION(ka_PlayerPreThink) MUTATOR_HOOKFUNCTION(ka_PlayerDamage) // for changing damage and force values that are applied to players in g_damage.qc { - if(frag_attacker.items & IT_KEY1) // if the attacker is a ballcarrier + if(frag_attacker.ballcarried) // if the attacker is a ballcarrier { if(frag_target == frag_attacker) // damage done to yourself { @@ -240,7 +261,7 @@ MUTATOR_HOOKFUNCTION(ka_PlayerDamage) // for changing damage and force values th frag_force *= cvar("g_keepaway_ballcarrier_force"); } } - else if not(frag_target.items & IT_KEY1) // if the target is a noncarrier + else if not(frag_target.ballcarried) // if the target is a noncarrier { if(frag_target == frag_attacker) // damage done to yourself { @@ -256,14 +277,64 @@ MUTATOR_HOOKFUNCTION(ka_PlayerDamage) // for changing damage and force values th return 0; } +MUTATOR_HOOKFUNCTION(ka_PlayerPowerups) +{ + if(self.ballcarried) + { + // if the player has the ball, force ballcarrier alpha upon them + self.alpha = cvar("g_keepaway_ballcarrier_alpha"); + self.exteriorweaponentity.alpha = cvar("g_keepaway_ballcarrier_alpha"); + + // if we're in minstagib and a ballcarrier has just picked up invisibility, + // notify all the other players that the ballcarrier no longer has a waypoint + if(g_minstagib) + { + if(olditems & IT_STRENGTH) + { + if(time > self.strength_finished) + { // this only runs ONCE right after the player loses invisibility + bprint(self.netname, "^7 isn't invisible from radar anymore.\n"); + } + } + else + { + if(time < self.strength_finished) + { // this only runs ONCE right after the player gains invisibility + bprint(self.netname, "^7 has picked up invisibility and can no longer be seen on radar!\n"); + } + } + } + } + else if(g_minstagib) + { + // if we're in minstagib and a noncarrier has invisibility, assure that we apply the invisibility effects normally + if(olditems & IT_STRENGTH) + { + self.alpha = g_minstagib_invis_alpha; + self.exteriorweaponentity.alpha = g_minstagib_invis_alpha; + } + } + else + { + // if we're a normal player with no powerups that edit alpha make sure the alpha is default. + // (normal powerups just use EF_ADDITIVE) + self.alpha = default_player_alpha; + self.exteriorweaponentity.alpha = default_weapon_alpha; + } + + return 0; +} + MUTATOR_DEFINITION(gamemode_keepaway) { + // I don't quite understand these orders, perhaps someone could enlighten me? MUTATOR_HOOK(MakePlayerObserver, ka_RemovePlayer, CBC_ORDER_ANY); MUTATOR_HOOK(ClientDisconnect, ka_RemovePlayer, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerDies, ka_Scoring, CBC_ORDER_ANY); MUTATOR_HOOK(GiveFragsForKill, ka_GiveFragsForKill, CBC_ORDER_ANY); MUTATOR_HOOK(PlayerPreThink, ka_PlayerPreThink, CBC_ORDER_FIRST); MUTATOR_HOOK(PlayerDamage_Calculate, ka_PlayerDamage, CBC_ORDER_ANY); + MUTATOR_HOOK(PlayerPowerups, ka_PlayerPowerups, CBC_ORDER_ANY); MUTATOR_ONADD {