make_pure(this);
int sf = 0;
serialize(byte, 0, sf);
- if (sf & BIT(1))
+ if (sf & BIT(1)) // make all players survivors
{
for (int j = 0; j < maxclients; ++j)
if (playerslots[j])
playerslots[j].survival_status = SURV_STATUS_PREY;
}
- if (sf & BIT(0))
+ if (sf & BIT(0)) // reveal hunters (to hunters)
{
for (int i = 1; i <= maxclients; i += 8)
{
}
}
}
+
+ // we could check STAT(GAME_STOPPED) instead of this dedicated flag,
+ // unfortunately STAT(GAME_STOPPED) is still false right when we receive this
+ bool reveal_hunters_to_survivors = (sf & BIT(2)); // when a round ends
+
+ int mystatus = playerslots[player_localnum].survival_status;
+ for (int i = 1; i <= maxclients; ++i)
+ {
+ entity e = playerslots[i - 1];
+ if (!e) continue;
+
+ int plcolor = SURV_COLOR_PREY;
+ if(e.survival_status == SURV_STATUS_HUNTER && (mystatus == SURV_STATUS_HUNTER || reveal_hunters_to_survivors))
+ plcolor = SURV_COLOR_HUNTER;
+
+ e.colormap = 1024 + plcolor; // override scoreboard and player model colors
+ }
+
return true;
}
entity player = M_ARGV(0, entity);
entity e = playerslots[player.entnum - 1];
- int surv_status = ((e) ? e.survival_status : SURV_COLOR_PREY);
- int mystatus = playerslots[player_localnum].survival_status;
-
- int plcolor = SURV_COLOR_PREY; // default to survivor
- if((mystatus == SURV_STATUS_HUNTER || intermission || STAT(GAME_STOPPED)) && surv_status == SURV_STATUS_HUNTER)
- plcolor = SURV_COLOR_HUNTER;
-
- player.colormap = 1024 + plcolor;
+ if (e && e.colormap)
+ player.colormap = e.colormap;
+ else
+ player.colormap = 1024 + SURV_COLOR_PREY;
return true;
}
{
// SendFlags can be set to anything != 0, SurvivalStatuses_SendEntity won't use its value
survivalStatuses.SendFlags = 1;
+ survivalStatuses.nextthink = 0; // clear delayed send
+}
+
+void SurvivalStatuses_Send_Delayed()
+{
+ survivalStatuses.think = SurvivalStatuses_Send;
+ survivalStatuses.nextthink = time + 0.2;
}
bool SurvivalStatuses_SendEntity(entity this, entity dest, float sendflags)
Stream out = MSG_ENTITY;
WriteHeader(out, ENT_CLIENT_SURVIVALSTATUSES);
- sendflags = BIT(0) | BIT(1);
+ sendflags |= BIT(1); // make all players survivors
- // send hunter statuses only to hunters
- bool send_hunter_statuses = (dest.survival_status == SURV_STATUS_HUNTER || STAT(GAME_STOPPED));
- if (!send_hunter_statuses)
- sendflags &= !BIT(0);
+ if (dest.survival_status == SURV_STATUS_HUNTER);
+ sendflags |= BIT(0); // send hunter statuses
+
+ if (round_handler_AwaitingNextRound())
+ sendflags |= (BIT(0) | BIT(2)); // send hunter statuses and reveal hunters to survivors
serialize(byte, out, sendflags);
if (sendflags & BIT(0)) {
int f = 0;
entity e = edict_num(i);
for (int b = 0; b < 8; ++b, e = nextent(e)) {
- bool is_hunter = (IS_PLAYER(e) && e.survival_status == SURV_STATUS_HUNTER);
+ bool is_hunter = (INGAME(e) && e.survival_status == SURV_STATUS_HUNTER);
if (is_hunter)
f |= BIT(b);
}
allowed_to_spawn = false;
game_stopped = true;
round_handler_Init(5, autocvar_g_survival_warmup, autocvar_g_survival_round_timelimit);
+ SurvivalStatuses_Send();
return 1;
}
allowed_to_spawn = false;
game_stopped = true;
round_handler_Init(5, autocvar_g_survival_warmup, autocvar_g_survival_round_timelimit);
+ SurvivalStatuses_Send();
FOREACH_CLIENT(true,
{
M_ARGV(5, bool) = true; // anonymous attacker
}
-MUTATOR_HOOKFUNCTION(surv, PlayerPreThink)
-{
- entity player = M_ARGV(0, entity);
-
- if(IS_PLAYER(player) || INGAME(player))
- {
- // update the scoreboard colour display to out the real killer at the end of the round
- // running this every frame to avoid cheats
- int plcolor = SURV_COLOR_PREY;
- if(player.survival_status == SURV_STATUS_HUNTER && game_stopped)
- plcolor = SURV_COLOR_HUNTER;
- setcolor(player, plcolor);
- }
-}
-
MUTATOR_HOOKFUNCTION(surv, PlayerSpawn)
{
entity player = M_ARGV(0, entity);
if (!warmup_stage)
eliminatedPlayers.SendFlags |= 1;
+ // send statuses with a small delay to make sure a playerslot exists, otherwise
+ // personal colors for this player won't be overriden
+ // it also reduces network traffic when multiple clients join the server at once (at map start)
+ SurvivalStatuses_Send_Delayed();
}
MUTATOR_HOOKFUNCTION(surv, reset_map_players)
}
});
bot_relinkplayerlist();
+ // this will also clear scheduled SurvivalStatuses_Send set by PutClientInServer
SurvivalStatuses_Send();
return true;
}
// killed an ally! punishment is death
if(autocvar_g_survival_punish_teamkill && frag_attacker != frag_target && IS_PLAYER(frag_attacker) && IS_PLAYER(frag_target) && frag_attacker.survival_status == frag_target.survival_status && !ITEM_DAMAGE_NEEDKILL(frag_deathtype))
- if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted()) // don't autokill if the round hasn't
+ if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted()) // don't autokill if the round hasn't started yet
Damage(frag_attacker, frag_attacker, frag_attacker, 100000, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
return true;
}