From: Lyberta Date: Wed, 4 Apr 2018 16:44:14 +0000 (+0300) Subject: Merge branch 'master' into Lyberta/TeamplayOverhaul X-Git-Tag: xonotic-v0.8.5~1953^2~25 X-Git-Url: http://de.git.xonotic.org/?a=commitdiff_plain;h=195d267efd270e8d9ff9b4565f67d5aa4dc7681f;hp=-c;p=xonotic%2Fxonotic-data.pk3dir.git Merge branch 'master' into Lyberta/TeamplayOverhaul --- 195d267efd270e8d9ff9b4565f67d5aa4dc7681f diff --combined qcsrc/common/t_items.qc index 4ce8c8104,02a0dc171..9ab49e7fd --- a/qcsrc/common/t_items.qc +++ b/qcsrc/common/t_items.qc @@@ -628,18 -628,14 +628,18 @@@ float adjust_respawntime(float normal_r return normal_respawntime; } - CheckAllowedTeams(NULL); - GetTeamCounts(NULL); + entity balance = TeamBalance_CheckAllowedTeams(NULL); + TeamBalance_GetTeamCounts(balance, NULL); int players = 0; - if (c1 != -1) players += c1; - if (c2 != -1) players += c2; - if (c3 != -1) players += c3; - if (c4 != -1) players += c4; - + for (int i = 1; i <= NUM_TEAMS; ++i) + { + if (TeamBalance_IsTeamAllowed(balance, i)) + { + players += TeamBalance_GetNumberOfPlayers(balance, i); + } + } + TeamBalance_Destroy(balance); + if (players >= 2) { return normal_respawntime * (r / (players + o) + l); } else { @@@ -667,8 -663,6 +667,6 @@@ void Item_ScheduleRespawn(entity e AUTOCVAR(g_pickup_respawntime_initial_random, int, 1, "For items that don't start spawned: 0: spawn after their normal respawntime; 1: spawn after `random * respawntime` with the *same* random; 2: same as 1 but each item has separate random"); - float shared_random; - STATIC_INIT(shared_random) { shared_random = random(); } void Item_ScheduleInitialRespawn(entity e) { Item_Show(e, 0); @@@ -679,18 -673,26 +677,26 @@@ // range: respawntime .. respawntime + respawntimejitter spawn_in = e.respawntime + random() * e.respawntimejitter; } - else if (autocvar_g_pickup_respawntime_initial_random == 1) + else { + float rnd; + if (autocvar_g_pickup_respawntime_initial_random == 1) + { + static float shared_random = 0; + // NOTE this code works only if items are scheduled at the same time (normal case) + // NOTE2 random() can't return exactly 1 so this check always work as intended + if (!shared_random || floor(time) > shared_random) + shared_random = floor(time) + random(); + rnd = shared_random - floor(time); + } + else + rnd = random(); + // range: // if respawntime >= ITEM_RESPAWN_TICKS: ITEM_RESPAWN_TICKS .. respawntime + respawntimejitter // else: 0 .. ITEM_RESPAWN_TICKS // this is to prevent powerups spawning unexpectedly without waypoints - spawn_in = ITEM_RESPAWN_TICKS + shared_random * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS); - } - else - { - // range: same as 1 - spawn_in = ITEM_RESPAWN_TICKS + random() * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS); + spawn_in = ITEM_RESPAWN_TICKS + rnd * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS); } Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : spawn_in)); diff --combined qcsrc/server/defs.qh index 5befffee4,f85d6e2b6..03428b12b --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@@ -27,6 -27,8 +27,6 @@@ float bots_would_leave void UpdateFrags(entity player, int f); .float totalfrags; -float team1_score, team2_score, team3_score, team4_score; - // flag set on worldspawn so that the code knows if it is dedicated or not float server_is_dedicated; @@@ -180,8 -182,6 +180,6 @@@ float default_weapon_alpha string gamemode_name; - float startitem_failed; - string W_Apply_Weaponreplace(string in); void FixIntermissionClient(entity e); @@@ -231,6 -231,8 +229,6 @@@ void Damage (entity targ, entity inflic // WEAPONTODO #define DMG_NOWEP (weaponentities[0]) -float lockteams; - float sv_maxidle; float sv_maxidle_spectatorsareidle; int sv_maxidle_slots; @@@ -404,67 -406,43 +402,43 @@@ const int MIF_GUIDED_CONFUSABLE = MIF_G .WepSet dual_weapons; IntrusiveList g_monsters; - STATIC_INIT(g_monsters) { g_monsters = IL_NEW(); } - IntrusiveList g_waypoints; - STATIC_INIT(g_waypoints) { g_waypoints = IL_NEW(); } - IntrusiveList g_vehicles; - STATIC_INIT(g_vehicles) { g_vehicles = IL_NEW(); } - IntrusiveList g_turrets; - STATIC_INIT(g_turrets) { g_turrets = IL_NEW(); } - IntrusiveList g_mines; - STATIC_INIT(g_mines) { g_mines = IL_NEW(); } - IntrusiveList g_projectiles; - STATIC_INIT(g_projectiles) { g_projectiles = IL_NEW(); } - IntrusiveList g_items; - STATIC_INIT(g_items) { g_items = IL_NEW(); } - IntrusiveList g_initforplayer; - STATIC_INIT(g_initforplayer) { g_initforplayer = IL_NEW(); } - IntrusiveList g_clones; - STATIC_INIT(g_clones) { g_clones = IL_NEW(); } - - IntrusiveList g_assault_destructibles; - STATIC_INIT(g_assault_destructibles) { g_assault_destructibles = IL_NEW(); } - - IntrusiveList g_assault_objectivedecreasers; - STATIC_INIT(g_assault_objectivedecreasers) { g_assault_objectivedecreasers = IL_NEW(); } - - IntrusiveList g_assault_objectives; - STATIC_INIT(g_assault_objectives) { g_assault_objectives = IL_NEW(); } - IntrusiveList g_spawnpoints; - STATIC_INIT(g_spawnpoints) { g_spawnpoints = IL_NEW(); } - IntrusiveList g_bot_targets; - STATIC_INIT(g_bot_targets) { g_bot_targets = IL_NEW(); } - IntrusiveList g_bot_dodge; - STATIC_INIT(g_bot_dodge) { g_bot_dodge = IL_NEW(); } - IntrusiveList g_damagedbycontents; - STATIC_INIT(g_damagedbycontents) { g_damagedbycontents = IL_NEW(); } - IntrusiveList g_railgunhit; - STATIC_INIT(g_railgunhit) { g_railgunhit = IL_NEW(); } - IntrusiveList g_ladders; - STATIC_INIT(g_ladders) { g_ladders = IL_NEW(); } - IntrusiveList g_locations; - STATIC_INIT(g_locations) { g_locations = IL_NEW(); } - IntrusiveList g_saved_team; - STATIC_INIT(g_saved_team) { g_saved_team = IL_NEW(); } - IntrusiveList g_monster_targets; - STATIC_INIT(g_monster_targets) { g_monster_targets = IL_NEW(); } - IntrusiveList g_pathlib_nodes; - STATIC_INIT(g_pathlib_nodes) { g_pathlib_nodes = IL_NEW(); } + STATIC_INIT(defs) + { + g_monsters = IL_NEW(); + g_waypoints = IL_NEW(); + g_vehicles = IL_NEW(); + g_turrets = IL_NEW(); + g_mines = IL_NEW(); + g_projectiles = IL_NEW(); + g_items = IL_NEW(); + g_initforplayer = IL_NEW(); + g_clones = IL_NEW(); + g_spawnpoints = IL_NEW(); + g_bot_targets = IL_NEW(); + g_bot_dodge = IL_NEW(); + g_damagedbycontents = IL_NEW(); + g_railgunhit = IL_NEW(); + g_ladders = IL_NEW(); + g_locations = IL_NEW(); + g_saved_team = IL_NEW(); + g_monster_targets = IL_NEW(); + g_pathlib_nodes = IL_NEW(); + } diff --combined qcsrc/server/mutators/events.qh index 37910cd28,0d801ec22..df7113bd6 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@@ -3,6 -3,9 +3,9 @@@ #include // register all possible hooks here + + // to use a hook, first register your mutator using REGISTER_MUTATOR + // then create your function using MUTATOR_HOOKFUNCTION /** called when a player becomes observer, after shared setup */ #define EV_MakePlayerObserver(i, o) \ @@@ -126,26 -129,22 +129,26 @@@ MUTATOR_HOOKABLE(GiveFragsForKill, EV_G /** called when the match ends */ MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS); -/** allows adjusting allowed teams */ -#define EV_CheckAllowedTeams(i, o) \ +/** Allows adjusting allowed teams. Return true to use the bitmask value and set + * non-empty string to use team entity name. Both behaviors can be active at the + * same time and will stack allowed teams. + */ +#define EV_TeamBalance_CheckAllowedTeams(i, o) \ /** mask of teams */ i(float, MUTATOR_ARGV_0_float) \ /**/ o(float, MUTATOR_ARGV_0_float) \ /** team entity name */ i(string, MUTATOR_ARGV_1_string) \ /**/ o(string, MUTATOR_ARGV_1_string) \ /** player checked */ i(entity, MUTATOR_ARGV_2_entity) \ /**/ -MUTATOR_HOOKABLE(CheckAllowedTeams, EV_CheckAllowedTeams); +MUTATOR_HOOKABLE(TeamBalance_CheckAllowedTeams, + EV_TeamBalance_CheckAllowedTeams); /** return true to manually override team counts */ -MUTATOR_HOOKABLE(GetTeamCounts, EV_NO_ARGS); +MUTATOR_HOOKABLE(TeamBalance_GetTeamCounts, EV_NO_ARGS); /** allow overriding of team counts */ -#define EV_GetTeamCount(i, o) \ - /** team to count */ i(float, MUTATOR_ARGV_0_float) \ +#define EV_TeamBalance_GetTeamCount(i, o) \ + /** team index to count */ i(float, MUTATOR_ARGV_0_float) \ /** player to ignore */ i(entity, MUTATOR_ARGV_1_entity) \ /** number of players in a team */ i(float, MUTATOR_ARGV_2_float) \ /**/ o(float, MUTATOR_ARGV_2_float) \ @@@ -156,16 -155,14 +159,16 @@@ /** lowest scoring bot in a team */ i(entity, MUTATOR_ARGV_5_entity) \ /**/ o(entity, MUTATOR_ARGV_5_entity) \ /**/ -MUTATOR_HOOKABLE(GetTeamCount, EV_GetTeamCount); +MUTATOR_HOOKABLE(TeamBalance_GetTeamCount, EV_TeamBalance_GetTeamCount); -/** allows overriding best teams */ -#define EV_FindBestTeams(i, o) \ +/** allows overriding the teams that will make the game most balanced if the + * player joins any of them. + */ +#define EV_TeamBalance_FindBestTeams(i, o) \ /** player checked */ i(entity, MUTATOR_ARGV_0_entity) \ /** bitmask of teams */ o(float, MUTATOR_ARGV_1_float) \ /**/ -MUTATOR_HOOKABLE(FindBestTeams, EV_FindBestTeams); +MUTATOR_HOOKABLE(TeamBalance_FindBestTeams, EV_TeamBalance_FindBestTeams); /** copies variables for spectating "spectatee" to "this" */ #define EV_SpectateCopy(i, o) \ @@@ -235,6 -232,14 +238,14 @@@ MUTATOR_HOOKABLE(SetStartItems, EV_NO_A /**/ MUTATOR_HOOKABLE(CustomizeWaypoint, EV_CustomizeWaypoint); + /** Check if items having the given definition are allowed to spawn. + * Return true to disallow spawning. + */ + #define EV_FilterItemDefinition(i, o) \ + /** item */ i(entity, MUTATOR_ARGV_0_entity) \ + /**/ + MUTATOR_HOOKABLE(FilterItemDefinition, EV_FilterItemDefinition); + /** * checks if the current item may be spawned (.items and .weapons may be read and written to, as well as the ammo_ fields) * return error to request removal @@@ -968,9 -973,9 +979,9 @@@ MUTATOR_HOOKABLE(MonsterModel, EV_Monst * Called before player changes their team. Return true to block team change. */ #define EV_Player_ChangeTeam(i, o) \ - /** player */ i(entity, MUTATOR_ARGV_0_entity) \ - /** current team */ i(float, MUTATOR_ARGV_1_float) \ - /** new team */ i(float, MUTATOR_ARGV_2_float) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /** current team index */ i(float, MUTATOR_ARGV_1_float) \ + /** new team index */ i(float, MUTATOR_ARGV_2_float) \ /**/ MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam); @@@ -978,9 -983,9 +989,9 @@@ * Called after player has changed their team. */ #define EV_Player_ChangedTeam(i, o) \ - /** player */ i(entity, MUTATOR_ARGV_0_entity) \ - /** old team */ i(float, MUTATOR_ARGV_1_float) \ - /** current team */ i(float, MUTATOR_ARGV_2_float) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /** old team index */ i(float, MUTATOR_ARGV_1_float) \ + /** current team index */ i(float, MUTATOR_ARGV_2_float) \ /**/ MUTATOR_HOOKABLE(Player_ChangedTeam, EV_Player_ChangedTeam); diff --combined qcsrc/server/mutators/mutator/gamemode_assault.qc index f3f104197,d43dc9999..2e703d1a8 --- a/qcsrc/server/mutators/mutator/gamemode_assault.qc +++ b/qcsrc/server/mutators/mutator/gamemode_assault.qc @@@ -5,6 -5,16 +5,16 @@@ .entity sprite; #define AS_ROUND_DELAY 5 + IntrusiveList g_assault_destructibles; + IntrusiveList g_assault_objectivedecreasers; + IntrusiveList g_assault_objectives; + STATIC_INIT(g_assault) + { + g_assault_destructibles = IL_NEW(); + g_assault_objectivedecreasers = IL_NEW(); + g_assault_objectives = IL_NEW(); + } + // random functions void assault_objective_use(entity this, entity actor, entity trigger) { @@@ -576,10 -586,10 +586,10 @@@ MUTATOR_HOOKFUNCTION(as, PlayHitsound return (frag_victim.classname == "func_assault_destructible"); } -MUTATOR_HOOKFUNCTION(as, CheckAllowedTeams) +MUTATOR_HOOKFUNCTION(as, TeamBalance_CheckAllowedTeams) { // assault always has 2 teams - c1 = c2 = 0; + M_ARGV(0, float) = BIT(0) | BIT(1); return true; } diff --combined qcsrc/server/mutators/mutator/gamemode_invasion.qc index 575fa308d,777b1b1e9..a69ad0fc4 --- a/qcsrc/server/mutators/mutator/gamemode_invasion.qc +++ b/qcsrc/server/mutators/mutator/gamemode_invasion.qc @@@ -6,13 -6,14 +6,14 @@@ #include IntrusiveList g_invasion_roundends; - STATIC_INIT(g_invasion_roundends) { g_invasion_roundends = IL_NEW(); } - IntrusiveList g_invasion_waves; - STATIC_INIT(g_invasion_waves) { g_invasion_waves = IL_NEW(); } - IntrusiveList g_invasion_spawns; - STATIC_INIT(g_invasion_spawns) { g_invasion_spawns = IL_NEW(); } + STATIC_INIT(g_invasion) + { + g_invasion_roundends = IL_NEW(); + g_invasion_waves = IL_NEW(); + g_invasion_spawns = IL_NEW(); + } float autocvar_g_invasion_round_timelimit; float autocvar_g_invasion_spawnpoint_spawn_delay; @@@ -546,10 -547,9 +547,10 @@@ MUTATOR_HOOKFUNCTION(inv, CheckRules_Wo return true; } -MUTATOR_HOOKFUNCTION(inv, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) +MUTATOR_HOOKFUNCTION(inv, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) { M_ARGV(0, float) = invasion_teams; + return true; } MUTATOR_HOOKFUNCTION(inv, AllowMobButcher) @@@ -560,7 -560,7 +561,7 @@@ void invasion_ScoreRules(int inv_teams) { - if(inv_teams) { CheckAllowedTeams(NULL); } + //if(inv_teams) { CheckAllowedTeams(NULL); } // Another bug? GameRules_score_enabled(false); GameRules_scoring(inv_teams, 0, 0, { if (inv_teams) {