void SendWelcomemessage(entity this, bool force_centerprint)
{
msg_entity = this;
- WriteHeader(MSG_ONE, TE_CSQC_SERVERINFO);
- WriteByte(MSG_ONE, force_centerprint);
- WriteString(MSG_ONE, autocvar_hostname);
- WriteString(MSG_ONE, autocvar_g_xonoticversion);
- WriteByte(MSG_ONE, CS(this).version_mismatch);
- WriteByte(MSG_ONE, (CS(this).version < autocvar_gameversion));
+ WriteHeader(MSG_ONE, TE_CSQC_SERVERWELCOME);
+ SendWelcomemessage_msg_type(this, force_centerprint, MSG_ONE);
+}
+
+// NOTE csqc uses the active mutators list sent by this function
+// to understand which mutators are enabled
+// also note that they aren't all registered mutators, e.g. jetpack, low gravity
+void SendWelcomemessage_msg_type(entity this, bool force_centerprint, int msg_type)
+{
+ WriteByte(msg_type, boolean(autocvar_g_campaign));
+ if (boolean(autocvar_g_campaign))
+ {
+ WriteString(msg_type, Campaign_GetTitle());
+ WriteByte(msg_type, Campaign_GetLevelNum());
+ WriteString(msg_type, Campaign_GetMessage());
+ return;
+ }
+ WriteByte(msg_type, force_centerprint);
+ WriteString(msg_type, autocvar_hostname);
+ WriteString(msg_type, autocvar_g_xonoticversion);
+ WriteByte(msg_type, CS(this).version_mismatch);
+ WriteByte(msg_type, (CS(this).version < autocvar_gameversion));
MUTATOR_CALLHOOK(BuildMutatorsPrettyString, "");
string modifications = M_ARGV(0, string);
modifications = strcat(modifications, ", Jetpack");
modifications = substring(modifications, 2, strlen(modifications) - 2);
- WriteString(MSG_ONE, modifications);
+ WriteString(msg_type, modifications);
- WriteString(MSG_ONE, g_weaponarena_list);
+ WriteString(msg_type, g_weaponarena_list);
if(cache_lastmutatormsg != autocvar_g_mutatormsg)
{
strcpy(cache_mutatormsg, cache_lastmutatormsg);
}
- WriteString(MSG_ONE, cache_mutatormsg);
+ WriteString(msg_type, cache_mutatormsg);
- string mutator_msg = "";
- MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
- mutator_msg = M_ARGV(0, string);
-
- WriteString(MSG_ONE, mutator_msg); // trust that the mutator will do proper formatting
- WriteString(MSG_ONE, strreplace("\\n", "\n", autocvar_sv_motd));
-}
-
-void SendWelcomemessage_onConnection_think(entity this)
-{
- SendWelcomemessage(this, false);
-}
-
-void SendWelcomemessage_onConnection(entity this)
-{
- // give the client time to sent its version
- defer(this, 0.5, SendWelcomemessage_onConnection_think);
+ WriteString(msg_type, strreplace("\\n", "\n", autocvar_sv_motd));
}
/**
CS(this).model_randomizer = random();
if (IS_REAL_CLIENT(this))
- {
- if (!autocvar_g_campaign)
- SendWelcomemessage_onConnection(this);
sv_notice_join(this);
- }
this.move_qcphysics = autocvar_sv_qcphysics;
MUTATOR_CALLHOOK(ClientConnect, this);
+ if (player_count == 1)
+ localcmd("\nsv_hook_firstjoin\n");
+
if (IS_REAL_CLIENT(this) && !IS_PLAYER(this) && !autocvar_g_campaign)
CS(this).motd_actived_time = -1; // the welcome message is shown by the client
}
player_powerups_remove_all(this); // stop powerup sound
ONREMOVE(this);
+
+ if (player_count == 0)
+ localcmd("\nsv_hook_lastleave\n");
}
void ChatBubbleThink(entity this)
void play_countdown(entity this, float finished, Sound samp)
{
TC(Sound, samp);
- if(IS_REAL_CLIENT(this))
- if(floor(finished - time - frametime) != floor(finished - time))
- if(finished - time < 6)
- sound (this, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
+ float time_left = finished - time;
+ if(IS_REAL_CLIENT(this) && time_left < 6 && floor(time_left - frametime) != floor(time_left))
+ sound(this, CH_INFO, samp, VOL_BASE, ATTEN_NORM);
}
// it removes special powerups not handled by StatusEffects
if (this.items & (IT_SUPERWEAPON | IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS))
{
// don't play the poweroff sound when the game restarts or the player disconnects
- if (time > game_starttime + 1 && IS_CLIENT(this))
+ if (time > game_starttime + 1 && IS_CLIENT(this)
+ && !(start_items & (IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS)))
+ {
sound(this, CH_INFO, SND_POWEROFF, VOL_BASE, ATTEN_NORM);
+ }
if (this.items & (IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS))
stopsound(this, CH_TRIGGER_SINGLE); // get rid of the pickup sound
this.items -= (this.items & (IT_SUPERWEAPON | IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS));
}
void Join(entity this)
{
+ if (autocvar_g_campaign && !campaign_bots_may_start && !game_stopped && time >= game_starttime)
+ ReadyRestart(true);
+
TRANSMUTE(Player, this);
if(!this.team_selected)
if (autocvar_g_campaign) {
if ((IS_PLAYER(this) && PHYS_INPUT_BUTTON_INFO(this)) || (!IS_PLAYER(this))) {
CS(this).motd_actived_time = time;
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_CAMPAIGN_MESSAGE, Campaign_GetMessage(), Campaign_GetLevelNum());
+ SendWelcomemessage(this, false);
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this)) {
CS(this).motd_actived_time = time;
else if ((time - CS(this).motd_actived_time > 2) && IS_PLAYER(this)) { // hide it some seconds after BUTTON_INFO has been released
CS(this).motd_actived_time = 0;
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_CAMPAIGN_MESSAGE);
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
} else {
if (PHYS_INPUT_BUTTON_INFO(this))
{
// instantly hide MOTD
CS(this).motd_actived_time = 0;
- if (autocvar_g_campaign)
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_CAMPAIGN_MESSAGE);
- else
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD);
}
else if (IS_PLAYER(this) || IS_SPEC(this))
{
|| (!(autocvar_sv_spectate || autocvar_g_campaign || (Player_GetForcedTeamIndex(this) == TEAM_FORCE_SPECTATOR))
&& (!teamplay || autocvar_g_balance_teams)))
{
- campaign_bots_may_start = true;
if(joinAllowed(this))
Join(this);
return;