From: drjaska Date: Thu, 28 Oct 2021 02:16:15 +0000 (+0300) Subject: refactored some of the round-based stuff, added a bunch of stuff X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=0c35fd94759c835dc324bd4fee0b60f5938d7a98;p=xonotic%2Fxonotic-data.pk3dir.git refactored some of the round-based stuff, added a bunch of stuff added a new late join notification, wrote some documentation on round functions --- diff --git a/qcsrc/common/gamemodes/gamemode/mh/TODO.txt b/qcsrc/common/gamemodes/gamemode/mh/TODO.txt index ad6880c17..1ea205fbf 100644 --- a/qcsrc/common/gamemodes/gamemode/mh/TODO.txt +++ b/qcsrc/common/gamemodes/gamemode/mh/TODO.txt @@ -1,14 +1,14 @@ -everything xd -round based -create INFO_MH_JOIN_LATE based on INFO_CA_JOIN_LATE for the use of "newly joined player is only able to join the hunters for this round" -shuffle teams after every round -have players change teams upon dying decide names for teams, runners and hunters? -mid-round joins go into hunters(?) + +add g_mh_startitem cvars to the balance files + collision detection which kills the runner(?), check if goombastomp's or touchexplode's code is reusable + avoid players bumping into each other and losing speed regardless of team without affecting ^ -score for hunters(?) for each kill and score for runners(?) for staying alive + +teleport tagged players to where they got tagged / restore their velocity, coordinates and view angles + on-screen notification (and sound?) for getting tagged -add more TODO: notes +add more TODO: notes diff --git a/qcsrc/common/gamemodes/gamemode/mh/mh.qh b/qcsrc/common/gamemodes/gamemode/mh/mh.qh index 5390f9fe9..0c34c99b9 100644 --- a/qcsrc/common/gamemodes/gamemode/mh/mh.qh +++ b/qcsrc/common/gamemodes/gamemode/mh/mh.qh @@ -9,11 +9,11 @@ void HUD_Mod_MH_Export(int fh); CLASS(Manhunt, Gametype) INIT(Manhunt) { - this.gametype_init(this, _("Manhunt"),"mh","g_mh",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS | GAMETYPE_FLAG_PRIORITY,"","timelimit=15 pointlimit=10 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team")); + this.gametype_init(this, _("Manhunt"),"mh","g_mh",GAMETYPE_FLAG_TEAMPLAY | GAMETYPE_FLAG_USEPOINTS | GAMETYPE_FLAG_PRIORITY,"","timelimit=30 pointlimit=10 teams=2 leadlimit=0",_("Help your team score the most frags against the enemy team")); } METHOD(Manhunt, m_isAlwaysSupported, bool(Gametype this, int spawnpoints, float diameter)) { - if(spawnpoints >= 8 && diameter > 4096) + if(spawnpoints >= 4 && diameter > 4096) return true; return false; } diff --git a/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qc b/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qc index c92f0d55e..48d85b0c7 100644 --- a/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qc +++ b/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qc @@ -45,75 +45,21 @@ MUTATOR_HOOKFUNCTION(mh, FilterItem) return true; } -// ============= -// score hooks -// ============= - -//refactor this when setting up score for tagging -MUTATOR_HOOKFUNCTION(mh, Damage_Calculate) +MUTATOR_HOOKFUNCTION(mh, PlayerRegen) { - entity frag_attacker = M_ARGV(1, entity); - entity frag_target = M_ARGV(2, entity); - float frag_deathtype = M_ARGV(3, float); - float frag_damage = M_ARGV(4, float); - float frag_mirrordamage = M_ARGV(5, float); - - if (IS_PLAYER(frag_target)) - if (!IS_DEAD(frag_target)) - if (frag_target == frag_attacker || SAME_TEAM(frag_target, frag_attacker) || frag_deathtype == DEATH_FALL.m_id) - frag_damage = 0; - - frag_mirrordamage = 0; - - M_ARGV(4, float) = frag_damage; - M_ARGV(5, float) = frag_mirrordamage; + // no regeneration nor rot + return true; } -//refactor this when setting up score for tagging -MUTATOR_HOOKFUNCTION(mh, PlayerDamage_SplitHealthArmor) -{ - if (time < game_starttime || (round_handler_IsActive() && !round_handler_IsRoundStarted())) - return; +// ============= +// score hooks +// ============= - entity frag_attacker = M_ARGV(1, entity); - entity frag_target = M_ARGV(2, entity); - if(frag_attacker.team == -1 || frag_target.team == -1)return; - //print("\n", "frag_attacker.team: ", sprintf("%f ", frag_attacker.team), "\n"); // - //print("\n", "frag_target.team: ", sprintf("%f ", frag_target.team), "\n"); // - float frag_deathtype = M_ARGV(6, float); - float frag_damage = M_ARGV(7, float); - float damage_take = bound(0, M_ARGV(4, float), GetResource(frag_target, RES_HEALTH)); - float damage_save = bound(0, M_ARGV(5, float), GetResource(frag_target, RES_ARMOR)); - - float excess = max(0, frag_damage - damage_take - damage_save); - - //non-friendly fire - if (frag_target != frag_attacker && IS_PLAYER(frag_attacker) && DIFF_TEAM(frag_target, frag_attacker)) - GameRules_scoring_add_team(frag_attacker, SCORE, (frag_damage - excess) * 1); - - //friendly fire - if (SAME_TEAM(frag_target, frag_attacker)) - GameRules_scoring_add_team(frag_attacker, SCORE, (-1 * (frag_damage - excess)) * 1); - - //handle (environmental hazard) suiciding, check first if player has a registered attacker who most likely pushed them there to avoid punishing pushed players as pushers are already rewarded - //deathtypes: - //kill = suicide, drown = drown in water/liquid, hurttrigger = out of the map void or hurt triggers inside maps like electric sparks - //camp = campcheck, lava = lava, slime = slime - //team change / rebalance suicides are currently not included - if (!IS_PLAYER(frag_attacker) && ( - frag_deathtype == DEATH_KILL.m_id || - frag_deathtype == DEATH_DROWN.m_id || - frag_deathtype == DEATH_HURTTRIGGER.m_id || - frag_deathtype == DEATH_CAMP.m_id || - frag_deathtype == DEATH_LAVA.m_id || - frag_deathtype == DEATH_SLIME.m_id || - frag_deathtype == DEATH_SWAMP.m_id)) - GameRules_scoring_add_team(frag_target, SCORE, (-1 * (frag_damage - excess)) * 1); -} +// MH_CheckWinner gives runners score MUTATOR_HOOKFUNCTION(mh, GiveFragsForKill, CBC_ORDER_FIRST) { - M_ARGV(2, float) = 0; // score will be given to the players differently + M_ARGV(2, float) = 30; //30 points for every tag a hunter gets, might include runners telefragging a hunter idk lol but they can keep it then return true; } @@ -126,50 +72,38 @@ MUTATOR_HOOKFUNCTION(mh, GiveFragsForKill, CBC_ORDER_FIRST) // "wtf do these functions do" chart -// all functions: read and modified -// understood: to fit mh: +// all functions: refactor documented: +// finished: :) // mh_LastPlayerForTeam y y // mh_LastPlayerForTeam_Notify y y -// PlayerDies y +// PlayerDies add tp y // ClientDisconnect y y // HideTeamNagger y y -// PlayerSpawn -// ForbidSpawn -// PutClientInServer -// reset_map_players -// reset_map_global y y until something needs to be added there +// PlayerSpawn add tp y +// PutClientInServer y y // MH_count_alive_players y y // MH_GetWinnerTeam y y -// nades_Clear ?? ?? +// nades_Clear y y // MH_CheckWinner y y // MH_RoundStart y y // MH_CheckTeams y y -// mh_isEliminated y y - -// general order which they are called in: - - - - - - - - - - - - - - - - + +// general order which they are called in / when they are called: +// todo: update after cleanup is finished and when new functions are added +// Start by initiating round_handler, when there is >= 1 player alive on both teams MH_CheckTeams(which is done by calling MH_count_alive_players and +// it also updates the count for alive players for Team_ functions) let's round handler start a new round +// Between rounds reset_map_ hooks get triggered and on new round start MH_RoundStart is called +// On every tick round handler calls MH_CheckWinner to see if the round should end, if a round should end the game is stopped, +// nades_Clear is called and MH_CheckWinner calls forward adding score to teams +// When a player dies PlayerDies hook gets triggered and mh_LastPlayerForTeam gets called, it may chain to +// mh_LastPlayerForTeam_Notify if appropriate. These are also called when ClientDisconnect hook gets triggered @@ -180,9 +114,9 @@ MUTATOR_HOOKFUNCTION(mh, GiveFragsForKill, CBC_ORDER_FIRST) // Needed in MH? Purpose?: // yes, same // Needed modifications for MH: -// Removed check for if player is not dead as players don't "die" die +// Removed check for if player is not dead as players don't "die" die without being instantly respawned // Called by: -// mh_LastPlayerForTeam_Notify +// mh_LastPlayerForTeam_Notify , PlayerDies // Calls: // none entity mh_LastPlayerForTeam(entity this) @@ -222,43 +156,6 @@ void mh_LastPlayerForTeam_Notify(entity this) } } -// Function: -// PlayerDies -// Purpose in CA: -// handle players dying -// Needed in MH? Purpose?: -// yes, handle players getting tagged -// Needed modifications for MH: -// change respawning -// Called by: -// a player dying -// Calls: -// mh_LastPlayerForTeam_Notify -MUTATOR_HOOKFUNCTION(mh, PlayerDies) -{ - entity frag_target = M_ARGV(2, entity); - - mh_LastPlayerForTeam_Notify(frag_target); - //if (!allowed_to_spawn_untagged) - //{ - frag_target.respawn_flags = RESPAWN_SILENT; - // prevent unwanted sudden rejoin as spectator and movement of spectator camera - frag_target.respawn_time = time; - //} - frag_target.respawn_flags |= RESPAWN_FORCE; - //print("\n", "frag_target.team: ", sprintf("%f ", frag_target.team), "\n"); //5 or 14 - //print("\n", "Team_IndexToTeam(1): ", sprintf("%f ", Team_IndexToTeam(1)), "\n"); //5 - //print("\n", "Team_IndexToTeam(2): ", sprintf("%f ", Team_IndexToTeam(2)), "\n"); //14 - //print("\n", "Team_IndexToTeam(3): ", sprintf("%f ", Team_IndexToTeam(3)), "\n"); //13 - //print("\n", "Team_IndexToTeam(4): ", sprintf("%f ", Team_IndexToTeam(4)), "\n"); //10 - if(frag_target.team == Team_IndexToTeam(2) && !allowed_to_spawn_untagged && (frag_target != mh_LastPlayerForTeam(frag_target))) - MoveToTeam(frag_target, 1, 6); //index of 1 static is wrong way but it's working somehow with bubblegum and prayers - - //if (!warmup_stage) - // eliminatedPlayers.SendFlags |= 1; - return true; -} - // Function: // ClientDisconnect // Purpose in CA: @@ -289,127 +186,6 @@ MUTATOR_HOOKFUNCTION(mh, HideTeamNagger) return true; // doesn't work well with the whole stack teams until no non-tagged players exist thing } -// Function: -// PlayerSpawn -// Purpose in CA: -// -// Needed in MH? Purpose?: -// -// Needed modifications for MH: -// -// Called by: -// a player spawning -// Calls: -// none -//MUTATOR_HOOKFUNCTION(mh, PlayerSpawn) -//{ -// entity player = M_ARGV(0, entity); - - //if(!allowed_to_spawn_untagged) - // MoveToTeam(player, Team_IndexToTeam(2), 6); - - //player.caplayer = 1; - //if (!warmup_stage) - // eliminatedPlayers.SendFlags |= 1; -//} - -// Function: -// ForbidSpawn -// Purpose in CA: -// -// Needed in MH? Purpose?: -// -// Needed modifications for MH: -// remove? -// Called by: -// -// Calls: -// -//MUTATOR_HOOKFUNCTION(mh, ForbidSpawn) -//{ -// entity player = M_ARGV(0, entity); -// -// // spectators / observers that weren't playing can join; they are -// // immediately forced to observe in the PutClientInServer hook -// // this way they are put in a team and can play in the next round -// if (!allowed_to_spawn_untagged && player.caplayer) -// return true; -// return false; -//} - -// Function: -// PutClientInServer -// Purpose in CA: -// -// Needed in MH? Purpose?: -// -// Needed modifications for MH: -// Removed TRANSMUTE(Observer, player); -// Called by: -// -// Calls: -// -MUTATOR_HOOKFUNCTION(mh, PutClientInServer) -{ - entity player = M_ARGV(0, entity); - - if (!allowed_to_spawn_untagged && IS_PLAYER(player)) // this is true even when player is trying to join - { - if (CS(player).jointime != time) // not when connecting - { - Send_Notification(NOTIF_ONE_ONLY, player, MSG_INFO, INFO_CA_JOIN_LATE); - } - } -} - -// Function: -// reset_map_players -// Purpose in CA: -// reset's each player's killstreak -// -// Needed in MH? Purpose?: -// yes, -// Needed modifications for MH: -// -// Called by: -// map being reset after round end -// Calls: -// PutClientInServer -MUTATOR_HOOKFUNCTION(mh, reset_map_players) -{ - FOREACH_CLIENT(true, { - CS(it).killcount = 0; - if(IS_BOT_CLIENT(it)){ - it.team = -1; - - } - if(1){ - //TRANSMUTE(Player, it); - PutClientInServer(it); - } - }); - - return true; -} - -// Function: -// reset_map_global -// Purpose in CA: -// allow players to spawn after a new round is started -// Needed in MH? Purpose?: -// yes, same but as untagged -// Needed modifications for MH: -// renamed allowed_to_spawn to allowed_to_spawn_untagged -// Called by: -// map being reset after round end -// Calls: -// none -MUTATOR_HOOKFUNCTION(mh, reset_map_global) -{ - allowed_to_spawn_untagged = true; - return true; -} - // Function: // MH_count_alive_players // Purpose in CA: @@ -419,7 +195,7 @@ MUTATOR_HOOKFUNCTION(mh, reset_map_global) // Needed modifications for MH: // Removed support for 3rd and 4th teams // Called by: -// MH_CheckWinner +// MH_CheckWinner , MH_CheckTeams // Calls: // multiple Team_ functions which are imported void MH_count_alive_players() @@ -457,16 +233,13 @@ void MH_count_alive_players() // Needed in MH? Purpose?: // yes, same // Needed modifications for MH: -// cleanup +// changed running out of time being a stalemate into runners winning, removed support for 3rd and 4th teams, refactored // Called by: // MH_CheckWinner // Calls: -// none +// Team_ int MH_GetWinnerTeam() { - //print("\n", "Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1): ", sprintf("%f ", Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1)), "\n")); //5 - //print("\n", "Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(2): ", sprintf("%f ", Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(2)), "\n")); //14 - //there were runners and hunters alive, runners win if ((Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1)) >= 1) && (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(2)) >= 1)){ return Team_IndexToTeam(2); } @@ -479,50 +252,38 @@ int MH_GetWinnerTeam() return -1; // no player left } -// Function: -// nades_Clear -// Purpose in CA: -// ??? maybe clear nades of the entity given as argument? how? -// Needed in MH? Purpose?: -// if it's needed in CA, yes -// Needed modifications for MH: -// none? -// Called by: -// MH_CheckWinner -// Calls: -// ??? maybe qcsrc/common/mutators/mutator/nades/nades.qc nades_Clear, idfk this magic / bubblegum fix and only given documentation is "// Remove nades that are being thrown" -void nades_Clear(entity player); - // Function: // MH_CheckWinner // Purpose in CA: -// +// ran on every frame to handle checking if a team has won with CA_GetWinnerTeam and then do the appropriate actions depending on results including starting a new round or continueing current round // Needed in MH? Purpose?: -// +// yes, same // Needed modifications for MH: -// renamed allowed_to_spawn to allowed_to_spawn_untagged +// renamed allowed_to_spawn to allowed_to_spawn_untagged, refactored // Called by: -// +// round_handler // Calls: -// round_handler_Init , MH_count_alive_players -float MH_CheckWinner(){ - +// round_handler_Init , MH_count_alive_players , MH_GetWinnerTeam , nades_Clear +float MH_CheckWinner() +{ int did_the_round_end = 0; MH_count_alive_players(); int winner_team = MH_GetWinnerTeam(); - if(winner_team != 14)print("\n", "winner_team: ", sprintf("%f ", winner_team), "\n"); + if(winner_team == 14) + FOREACH_CLIENT(IS_PLAYER(it) && it.team == 14, + { GameRules_scoring_add_team(it, SCORE, (0.016666667)); }); //add 1 score to each runner's score per second at 60 tickrate if(round_handler_GetEndTime() - time > 0 && winner_team == Team_IndexToTeam(2)){ did_the_round_end = 0; } else if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0 && winner_team == Team_IndexToTeam(2)){ - Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN)); - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN)); - print("runners \n"); + Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN)); //replace with runners win + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN)); //replace with runners win TeamScore_AddToTeam(winner_team, ST_MH_ROUNDS, +1); did_the_round_end = 1; + FOREACH_CLIENT(IS_PLAYER(it) && it.team == 14, + { GameRules_scoring_add_team(it, SCORE, (30)); }); //add 30 score to each runner's score } else if(winner_team == Team_IndexToTeam(1)){ - Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN)); - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN)); - print("hunters \n"); + Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, APP_TEAM_NUM(winner_team, CENTER_ROUND_TEAM_WIN)); //replace with hunters win + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(winner_team, INFO_ROUND_TEAM_WIN)); //replace with hunters win TeamScore_AddToTeam(winner_team, ST_MH_ROUNDS, +1); did_the_round_end = 1; } else if(winner_team == -1){ @@ -530,39 +291,21 @@ float MH_CheckWinner(){ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ROUND_TIED); did_the_round_end = 1; } else { - print("How did we get here? \n"); + //print("Error: Ran out of appropriate team win situations\n"); } if(did_the_round_end == 0)return 0; - allowed_to_spawn_untagged = false; game_stopped = true; round_handler_Init(5, autocvar_g_mh_warmup, autocvar_g_mh_round_timelimit); - shuffleteams_on_reset_map = !allowed_to_spawn_untagged; - - FOREACH_CLIENT(IS_PLAYER(it), { nades_Clear(it); }); + if(pymod(round_counter_for_teamchanging, 2)) + shuffleteams_on_reset_map = !allowed_to_spawn_untagged; //only shuffle every other round + ++round_counter_for_teamchanging; + FOREACH_CLIENT(IS_PLAYER(it), { CS(it).killcount = 0; nades_Clear(it); }); //hopefully "{ CS(it).killcount = 0; nades_Clear(it); }" works and doesn't cut off nades_Clear, untested return did_the_round_end; } -// Function: -// MH_RoundStart -// Purpose in CA: -// if the game is in warmup players can just respawn as players instead of be forced to spectate -// Needed in MH? Purpose?: -// yes, allow players to respawn in runners while in warmup. maybe other stuff which depend on the round starting? -// Needed modifications for MH: -// renamed allowed_to_spawn to allowed_to_spawn_untagged -// Called by: -// round_handler_Spawn -// Calls: -// none -void MH_RoundStart() -{ - //shuffleteams_on_reset_map = 0; - allowed_to_spawn_untagged = boolean(warmup_stage); -} - // Function: // MH_CheckTeams // Purpose in CA: @@ -570,7 +313,7 @@ void MH_RoundStart() // Needed in MH? Purpose?: // yes, same // Needed modifications for MH: -// +// removed support for 3rd and 4th teams, none more? I skimmed through this without fully diving in and understanding deeply every bit // Called by: // round_handler_Spawn // Calls: @@ -580,31 +323,26 @@ bool MH_CheckTeams() static int prev_missing_teams_mask; allowed_to_spawn_untagged = true; MH_count_alive_players(); - if (Team_GetNumberOfAliveTeams() == NumTeams(mh_teams)) - { + if (Team_GetNumberOfAliveTeams() == NumTeams(mh_teams)){ if(prev_missing_teams_mask > 0) Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_MISSING_TEAMS); prev_missing_teams_mask = -1; return true; } - if(total_players == 0) - { + if(total_players == 0){ if(prev_missing_teams_mask > 0) Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_MISSING_TEAMS); prev_missing_teams_mask = -1; return false; } int missing_teams_mask = 0; - for (int i = 1; i <= 2; ++i) - { + for (int i = 1; i <= 2; ++i){ if ((mh_teams & Team_IndexToBit(i)) && - (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) == 0)) - { + (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) == 0)){ missing_teams_mask |= Team_IndexToBit(i); } } - if(prev_missing_teams_mask != missing_teams_mask) - { + if(prev_missing_teams_mask != missing_teams_mask){ Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask); prev_missing_teams_mask = missing_teams_mask; } @@ -612,22 +350,120 @@ bool MH_CheckTeams() } // Function: -// mh_isEliminated +// MH_RoundStart // Purpose in CA: -// find if player has been eliminated and is not alive anymore +// if the game is in warmup players can just respawn as players instead of be forced to spectate // Needed in MH? Purpose?: -// no? +// yes, allow players to respawn in runners while in warmup. maybe other stuff which depend on the round starting? // Needed modifications for MH: -// remove? +// renamed allowed_to_spawn to allowed_to_spawn_untagged // Called by: -// EliminatedPlayers_Init +// round_handler_Spawn +// Calls: +// none +void MH_RoundStart() +{ + allowed_to_spawn_untagged = boolean(warmup_stage); +} + +// Function: +// PutClientInServer +// Purpose in CA: +// place the client in the server with the appropriate flags and as an observer when a spectator joins the game in the middle of the round +// Needed in MH? Purpose?: +// only to send an edited join late message about not being able to join runners? +// Needed modifications for MH: +// Removed TRANSMUTE(Observer, player); , fixed unnecessary printing of the message(fixed by removing call from reset_map_players?) , replaced the message with a new mh one +// Called by: +// a connecting player , reset_map_players // Calls: // none -//bool mh_isEliminated(entity e) -//{ -// if(e.caplayer == 1 && (IS_DEAD(e) || e.frags == FRAGS_PLAYER_OUT_OF_GAME)) -// return true; -// if(e.caplayer == 0.5) -// return true; -// return false; -//} \ No newline at end of file +MUTATOR_HOOKFUNCTION(mh, PutClientInServer) +{ + entity player = M_ARGV(0, entity); + + if (!allowed_to_spawn_untagged && IS_PLAYER(player)){ // this is true even when player is trying to join + if (CS(player).jointime != time){ // not when connecting + Send_Notification(NOTIF_ONE_ONLY, player, MSG_INFO, INFO_MH_JOIN_LATE); + } + } +} + +// Function: +// nades_Clear +// Purpose in CA: +// clear nades of the entity given as argument +// Needed in MH? Purpose?: +// yes, same +// Needed modifications for MH: +// none +// Called by: +// MH_CheckWinner +// Calls: +// qcsrc/common/mutators/mutator/nades/nades.qc nades_Clear +void nades_Clear(entity player); + + + +// =========== +// to change +// =========== + + + +// Maybe add player teleporting to where they died if they just got tagged? + +// Function: +// PlayerSpawn +// Purpose in CA: +// set flags on the player when they spawn as a player +// Needed in MH? Purpose?: +// yes, don't allow players to join runners mid-round +// Needed modifications for MH: +// +// Called by: +// a player spawning +// Calls: +// none +MUTATOR_HOOKFUNCTION(mh, PlayerSpawn) +{ + entity player = M_ARGV(0, entity); + MH_count_alive_players(); + if(player.team == Team_IndexToTeam(2) && !allowed_to_spawn_untagged && Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(2)) > 1 && round_handler_IsActive() && round_handler_IsRoundStarted()){ + player.deadflag = 1; // avoid a crash when a spectator joins runners mid-round and gets sent to hunters + MoveToTeam(player, 1, 6); //index of 1 static is wrong way but it's working somehow with bubblegum and prayers + player.deadflag = 0; // with bubblegum and prayers, there probably is probably a better check to use here + } + //if (!warmup_stage) + // eliminatedPlayers.SendFlags |= 1; +} + +// Maybe add player teleporting to where they died if they just got tagged? + +// Function: +// PlayerDies +// Purpose in CA: +// handle players dying +// Needed in MH? Purpose?: +// yes, handle players getting tagged +// Needed modifications for MH: +// change respawning +// Called by: +// a player dying/dc'ing +// Calls: +// mh_LastPlayerForTeam_Notify +MUTATOR_HOOKFUNCTION(mh, PlayerDies) +{ + entity frag_target = M_ARGV(2, entity); + + mh_LastPlayerForTeam_Notify(frag_target); + if (!allowed_to_spawn_untagged) + { + frag_target.respawn_flags = RESPAWN_SILENT; //idk what this exactly does yet, below comment was there for respawn time = time + 2 and this line inside the backets + // prevent unwanted sudden rejoin as spectator and movement of spectator camera + } + frag_target.respawn_time = time; + frag_target.respawn_flags |= RESPAWN_FORCE; + + return true; +} diff --git a/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qh b/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qh index a55f5b72a..b78023997 100644 --- a/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qh +++ b/qcsrc/common/gamemodes/gamemode/mh/sv_mh.qh @@ -1,9 +1,9 @@ #pragma once #include -//#include #include #include +#include // TODO: change this? float autocvar_g_mh_point_limit; @@ -13,14 +13,15 @@ float autocvar_g_mh_round_timelimit; string autocvar_g_mh_weaponarena; int mh_teams; -bool allowed_to_spawn_untagged; +bool allowed_to_spawn_untagged = 1; + +int round_counter_for_teamchanging = 1; const int ST_MH_ROUNDS = 1; bool MH_CheckTeams(); bool MH_CheckWinner(); void MH_RoundStart(); -//bool mh_isEliminated(entity e); // code from here on is just to support maps that don't have team entities void mh_SpawnTeam (string teamname, int teamcolor) @@ -55,9 +56,6 @@ REGISTER_MUTATOR(mh, false) mh_SpawnTeam("Hunters", NUM_TEAM_1); if(mh_teams & BIT(1)) mh_SpawnTeam("Runners", NUM_TEAM_2); - - print("\n", "Hunters: ", sprintf("%f ", Team_IndexToTeam(1)), "\n"); //5 - print("\n", "Runners: ", sprintf("%f ", Team_IndexToTeam(2)), "\n"); //14 GameRules_scoring(mh_teams, SFL_SORT_PRIO_PRIMARY, 0, { field_team(ST_MH_ROUNDS, "rounds", SFL_SORT_PRIO_PRIMARY); @@ -66,7 +64,6 @@ REGISTER_MUTATOR(mh, false) allowed_to_spawn_untagged = true; round_handler_Spawn(MH_CheckTeams, MH_CheckWinner, MH_RoundStart); round_handler_Init(5, autocvar_g_mh_warmup, autocvar_g_mh_round_timelimit); - //EliminatedPlayers_Init(mh_isEliminated); } return 0; } \ No newline at end of file diff --git a/qcsrc/common/notifications/all.inc b/qcsrc/common/notifications/all.inc index f1b2af8e6..291a49a5a 100644 --- a/qcsrc/common/notifications/all.inc +++ b/qcsrc/common/notifications/all.inc @@ -258,6 +258,8 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input != MSG_INFO_NOTIF(CA_JOIN_LATE, N_CONSOLE, 0, 0, "", "", "", _("^F1Round already started, you will join the game in the next round"), "") MSG_INFO_NOTIF(CA_LEAVE, N_CONSOLE, 0, 0, "", "", "", _("^F2You will spectate in the next round"), "") + MSG_INFO_NOTIF(MH_JOIN_LATE, N_CONSOLE, 0, 0, "", "", "", _("^F1Round already started, you can only join the Hunters"), "") + MSG_INFO_NOTIF(DEATH_MURDER_BUFF, N_CONSOLE, 3, 3, "spree_inf s1 s2 f3buffname s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was killed by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s"), _("^BG%s%s^K1 was scored against by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s")) MSG_INFO_NOTIF(DEATH_MURDER_CHEAT, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_death", _("^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s"), "") MSG_INFO_NOTIF(DEATH_MURDER_DROWN, N_CONSOLE, 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1", "notify_water", _("^BG%s%s^K1 was drowned by ^BG%s^K1%s%s"), "")