#include <common/effects/qc/globalsound.qh>
#include <common/ent_cs.qh>
#include <common/gamemodes/_mod.qh>
-#include <common/gamemodes/gamemode/lms/sv_lms.qh>
#include <common/gamemodes/gamemode/nexball/sv_nexball.qh>
#include <common/items/_mod.qh>
#include <common/items/inventory.qh>
WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
+void send_TeamNames(int channel, entity to) {
+ msg_entity = to;
+
+ WriteHeader(channel, TE_CSQC_TEAMNAMES);
+ WriteString(channel, autocvar_g_teamnames_red);
+ WriteString(channel, autocvar_g_teamnames_blue);
+ WriteString(channel, autocvar_g_teamnames_yellow);
+ WriteString(channel, autocvar_g_teamnames_pink);
+}
+
int CountSpectators(entity player, entity to)
{
if(!player) { return 0; } // not sure how, but best to be safe
}
/** putting a client as observer in the server */
-void PutObserverInServer(entity this)
+void PutObserverInServer(entity this, bool is_forced)
{
- bool mutator_returnvalue = MUTATOR_CALLHOOK(MakePlayerObserver, this);
+ bool mutator_returnvalue = MUTATOR_CALLHOOK(MakePlayerObserver, this, is_forced);
PlayerState_detach(this);
if (IS_PLAYER(this))
setcolor(player, stof(autocvar_sv_defaultplayercolors));
}
+void ResetPlayerResources(entity this)
+{
+ if (warmup_stage) {
+ SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
+ SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
+ SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
+ SetResource(this, RES_CELLS, warmup_start_ammo_cells);
+ SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
+ SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
+ SetResource(this, RES_HEALTH, warmup_start_health);
+ SetResource(this, RES_ARMOR, warmup_start_armorvalue);
+ STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
+ } else {
+ SetResource(this, RES_SHELLS, start_ammo_shells);
+ SetResource(this, RES_BULLETS, start_ammo_nails);
+ SetResource(this, RES_ROCKETS, start_ammo_rockets);
+ SetResource(this, RES_CELLS, start_ammo_cells);
+ SetResource(this, RES_PLASMA, start_ammo_plasma);
+ SetResource(this, RES_FUEL, start_ammo_fuel);
+ SetResource(this, RES_HEALTH, start_health);
+ SetResource(this, RES_ARMOR, start_armorvalue);
+ STAT(WEAPONS, this) = start_weapons;
+ if (MUTATOR_CALLHOOK(ForbidRandomStartWeapons, this) == false)
+ {
+ GiveRandomWeapons(this, random_start_weapons_count,
+ autocvar_g_random_start_weapons, random_start_ammo);
+ }
+ }
+}
+
void PutPlayerInServer(entity this)
{
if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
this.takedamage = DAMAGE_AIM;
this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
- if (warmup_stage) {
- SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
- SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
- SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
- SetResource(this, RES_CELLS, warmup_start_ammo_cells);
- SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
- SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
- SetResource(this, RES_HEALTH, warmup_start_health);
- SetResource(this, RES_ARMOR, warmup_start_armorvalue);
- STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
- } else {
- SetResource(this, RES_SHELLS, start_ammo_shells);
- SetResource(this, RES_BULLETS, start_ammo_nails);
- SetResource(this, RES_ROCKETS, start_ammo_rockets);
- SetResource(this, RES_CELLS, start_ammo_cells);
- SetResource(this, RES_PLASMA, start_ammo_plasma);
- SetResource(this, RES_FUEL, start_ammo_fuel);
- SetResource(this, RES_HEALTH, start_health);
- SetResource(this, RES_ARMOR, start_armorvalue);
- STAT(WEAPONS, this) = start_weapons;
- if (MUTATOR_CALLHOOK(ForbidRandomStartWeapons, this) == false)
- {
- GiveRandomWeapons(this, random_start_weapons_count,
- autocvar_g_random_start_weapons, random_start_ammo);
- }
- }
+ ResetPlayerResources(this);
+
SetSpectatee_status(this, 0);
PS(this).dual_weapons = '0 0 0';
+ if(STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS)
+ StatusEffects_apply(STATUSEFFECT_Superweapons, this, time + autocvar_g_balance_superweapons_time, 0);
+
this.items = start_items;
- this.spawnshieldtime = time + autocvar_g_spawnshieldtime;
+ float shieldtime = time + autocvar_g_spawnshieldtime;
+
this.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn;
this.pauserothealth_finished = time + autocvar_g_balance_pause_health_rot_spawn;
this.pauserotfuel_finished = time + autocvar_g_balance_pause_fuel_rot_spawn;
if (!sv_ready_restart_after_countdown && time < game_starttime)
{
float f = game_starttime - time;
- this.spawnshieldtime += f;
+ shieldtime += f;
this.pauserotarmor_finished += f;
this.pauserothealth_finished += f;
this.pauseregen_finished += f;
}
+ StatusEffects_apply(STATUSEFFECT_SpawnShield, this, shieldtime, 0);
+
this.damageforcescale = autocvar_g_player_damageforcescale;
this.death_time = 0;
this.respawn_flags = 0;
this.respawn_time = 0;
STAT(RESPAWN_TIME, this) = 0;
- bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox;
- this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale);
+ this.scale = ((q3compat && autocvar_sv_q3compat_changehitbox) ? 0.9 : autocvar_sv_player_scale);
this.fade_time = 0;
this.pain_finished = 0;
this.pushltime = 0;
MUTATOR_CALLHOOK(PutClientInServer, this);
if (IS_OBSERVER(this)) {
- PutObserverInServer(this);
+ PutObserverInServer(this, false);
} else if (IS_PLAYER(this)) {
PutPlayerInServer(this);
}
-
+ // send team names
+ if(teamplay && IS_REAL_CLIENT(this))
+ send_TeamNames(MSG_ONE, this);
bot_relinkplayerlist();
}
WriteByte(channel, this.cnt * 255.0); // g_balance_damagepush_speedfactor
WriteByte(channel, serverflags);
WriteCoord(channel, autocvar_g_trueaim_minrange);
+
+ // z411 send full hostname
+ WriteString(channel, (autocvar_hostname_full != "" ? autocvar_hostname_full : autocvar_hostname));
+ WriteString(channel, autocvar_sv_motd_permanent);
}
void ClientInit_CheckUpdate(entity this)
modifications = strcat(modifications, ", Weapons stay");
if(autocvar_g_jetpack)
modifications = strcat(modifications, ", Jet pack");
- if(autocvar_g_powerups == 0)
- modifications = strcat(modifications, ", No powerups");
- if(autocvar_g_powerups > 0)
- modifications = strcat(modifications, ", Powerups");
modifications = substring(modifications, 2, strlen(modifications) - 2);
- string versionmessage = GetClientVersionMessage(this);
- string s = strcat(versionmessage, "^8\n^8\nserver is ^9", autocvar_hostname, "^8\n");
+ //string versionmessage = GetClientVersionMessage(this);
+ //string s = strcat(versionmessage, "^8\n^9", (autocvar_hostname_full ? autocvar_hostname_full : autocvar_hostname));
+ //string s = strcat(versionmessage, "^8\n^8\nserver is ^9", autocvar_hostname, "^8\n");
+ string s = (autocvar_hostname_full != "" ? autocvar_hostname_full : autocvar_hostname);
- s = strcat(s, "^8\nmatch type is ^1", gamemode_name, "^8\n");
+ s = strcat(s, "^8\n^7", gamemode_name);
if(modifications != "")
- s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
+ s = strcat(s, "^7 | ^3", modifications);
if(cache_lastmutatormsg != autocvar_g_mutatormsg)
{
}
if (cache_mutatormsg != "") {
- s = strcat(s, "\n\n^8special gameplay tips: ^7", cache_mutatormsg);
+ s = strcat(s, "\n^8tips: ^7", cache_mutatormsg);
}
string mutator_msg = "";
string motd = autocvar_sv_motd;
if (motd != "") {
- s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd));
+ s = strcat(s, "\n\n^7", strreplace("\\n", "\n", motd));
}
return s;
}
-bool autocvar_sv_qcphysics = true; // TODO this is for testing - remove when qcphysics work
-
/**
=============
ClientConnect
void player_powerups_remove_all(entity this)
{
- if (this.items & (ITEM_Strength.m_itemid | ITEM_Shield.m_itemid | IT_SUPERWEAPON))
+ if (this.items & IT_SUPERWEAPON)
{
// don't play the poweroff sound when the game restarts or the player disconnects
if (time > game_starttime + 1 && IS_CLIENT(this))
sound(this, CH_INFO, SND_POWEROFF, VOL_BASE, ATTEN_NORM);
stopsound(this, CH_TRIGGER_SINGLE); // get rid of the pickup sound
- this.items &= ~ITEM_Strength.m_itemid;
- this.items &= ~ITEM_Shield.m_itemid;
this.items -= (this.items & IT_SUPERWEAPON);
}
}
else
this.modelflags &= ~MF_ROCKET;
- this.effects &= ~(EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_NODEPTHTEST);
+ this.effects &= ~EF_NODEPTHTEST;
if (IS_DEAD(this))
player_powerups_remove_all(this);
if (!MUTATOR_IS_ENABLED(mutator_instagib))
{
- if (this.items & ITEM_Strength.m_itemid)
- {
- play_countdown(this, StatusEffects_gettime(STATUSEFFECT_Strength, this), SND_POWEROFF);
- this.effects = this.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
- if (time > StatusEffects_gettime(STATUSEFFECT_Strength, this))
- {
- this.items = this.items - (this.items & ITEM_Strength.m_itemid);
- //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_STRENGTH, this.netname);
- Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERDOWN_STRENGTH);
- }
- }
- else
- {
- if (time < StatusEffects_gettime(STATUSEFFECT_Strength, this))
- {
- this.items = this.items | ITEM_Strength.m_itemid;
- if(!g_cts)
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_STRENGTH, this.netname);
- Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_STRENGTH);
- }
- }
- if (this.items & ITEM_Shield.m_itemid)
- {
- play_countdown(this, StatusEffects_gettime(STATUSEFFECT_Shield, this), SND_POWEROFF);
- this.effects = this.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
- if (time > StatusEffects_gettime(STATUSEFFECT_Shield, this))
- {
- this.items = this.items - (this.items & ITEM_Shield.m_itemid);
- //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERDOWN_SHIELD, this.netname);
- Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERDOWN_SHIELD);
- }
- }
- else
- {
- if (time < StatusEffects_gettime(STATUSEFFECT_Shield, this))
- {
- this.items = this.items | ITEM_Shield.m_itemid;
- if(!g_cts)
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_POWERUP_SHIELD, this.netname);
- Send_Notification(NOTIF_ONE, this, MSG_CENTER, CENTER_POWERUP_SHIELD);
- }
- }
+ // NOTE: superweapons are a special case and as such are handled here instead of the status effects system
if (this.items & IT_SUPERWEAPON)
{
if (!(STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
if(autocvar_g_fullbrightplayers)
this.effects = this.effects | EF_FULLBRIGHT;
- if (time >= game_starttime)
- if (time < this.spawnshieldtime)
- this.effects = this.effects | (EF_ADDITIVE | EF_FULLBRIGHT);
-
MUTATOR_CALLHOOK(PlayerPowerups, this, items_prev);
}
return max(stable, current + (stable - current) * rotfactor * rotframetime);
}
-void RotRegen(entity this, int res, float regenstable, float regenfactor, float regenlinear, float regenframetime, float rotstable, float rotfactor, float rotlinear, float rotframetime, float limit_mod)
+void RotRegen(entity this, int res, float limit_mod,
+ float regenstable, float regenfactor, float regenlinear, float regenframetime,
+ float rotstable, float rotfactor, float rotlinear, float rotframetime)
{
float old = GetResource(this, res);
float current = old;
regen_health_stable = M_ARGV(9, float);
regen_health_rotstable = M_ARGV(10, float);
+ float rotstable, regenstable, rotframetime, regenframetime;
+
if(!mutator_returnvalue)
if(!STAT(FROZEN, this))
{
- float maxa = autocvar_g_balance_armor_rotstable;
- float mina = autocvar_g_balance_armor_regenstable;
-
- RotRegen(this, RES_ARMOR, mina, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear,
- regen_mod * frametime * (time > this.pauseregen_finished), maxa, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear,
- rot_mod * frametime * (time > this.pauserotarmor_finished), limit_mod);
+ regenstable = autocvar_g_balance_armor_regenstable;
+ rotstable = autocvar_g_balance_armor_rotstable;
+ regenframetime = (time > this.pauseregen_finished) ? (regen_mod * frametime) : 0;
+ rotframetime = (time > this.pauserotarmor_finished) ? (rot_mod * frametime) : 0;
+ RotRegen(this, RES_ARMOR, limit_mod,
+ regenstable, autocvar_g_balance_armor_regen, autocvar_g_balance_armor_regenlinear, regenframetime,
+ rotstable, autocvar_g_balance_armor_rot, autocvar_g_balance_armor_rotlinear, rotframetime);
- RotRegen(this, RES_HEALTH, regen_health_stable * max_mod, regen_health, regen_health_linear,
- regen_mod * frametime * (time > this.pauseregen_finished), regen_health_rotstable * max_mod, regen_health_rot, regen_health_rotlinear,
- rot_mod * frametime * (time > this.pauserothealth_finished), limit_mod);
+ // NOTE: max_mod is only applied to health
+ regenstable = regen_health_stable * max_mod;
+ rotstable = regen_health_rotstable * max_mod;
+ regenframetime = (time > this.pauseregen_finished) ? (regen_mod * frametime) : 0;
+ rotframetime = (time > this.pauserothealth_finished) ? (rot_mod * frametime) : 0;
+ RotRegen(this, RES_HEALTH, limit_mod,
+ regenstable, regen_health, regen_health_linear, regenframetime,
+ rotstable, regen_health_rot, regen_health_rotlinear, rotframetime);
}
// if player rotted to death... die!
if (!(this.items & IT_UNLIMITED_AMMO))
{
- float maxf = autocvar_g_balance_fuel_rotstable;
- float minf = autocvar_g_balance_fuel_regenstable;
-
- RotRegen(this, RES_FUEL, minf, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear,
- frametime * (time > this.pauseregen_finished) * ((this.items & ITEM_JetpackRegen.m_itemid) != 0),
- maxf, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, frametime * (time > this.pauserotfuel_finished), 1);
+ regenstable = autocvar_g_balance_fuel_regenstable;
+ rotstable = autocvar_g_balance_fuel_rotstable;
+ regenframetime = ((time > this.pauseregen_finished) && (this.items & ITEM_JetpackRegen.m_itemid)) ? frametime : 0;
+ rotframetime = (time > this.pauserotfuel_finished) ? frametime : 0;
+ RotRegen(this, RES_FUEL, 1,
+ regenstable, autocvar_g_balance_fuel_regen, autocvar_g_balance_fuel_regenlinear, regenframetime,
+ rotstable, autocvar_g_balance_fuel_rot, autocvar_g_balance_fuel_rotlinear, rotframetime);
}
}
accuracy_resend(this);
if(!SpectateUpdate(this))
- PutObserverInServer(this);
+ PutObserverInServer(this, false);
return true;
}
else
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname);
this.team_selected = false;
+
+ // z411
+ // send constant ready notification
+ if(warmup_stage)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MISSING_READY);
}
int GetPlayerLimit()
FOREACH_CLIENT(true, {
if(it != ignore)
++totalClients;
- if(IS_REAL_CLIENT(it))
- if(IS_PLAYER(it) || it.caplayer)
+ if(IS_REAL_CLIENT(it) && (IS_PLAYER(it) || INGAME(it)))
++currentlyPlaying;
});
free_slots = min(maxclients - totalClients, player_limit - currentlyPlaying);
static float msg_time = 0;
- if(this && !this.caplayer && ignore && !free_slots && time > msg_time)
+ if(this && !INGAME(this) && ignore && !free_slots && time > msg_time)
{
Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT);
msg_time = time + 0.5;
return false;
}
- if (timeout_status == TIMEOUT_ACTIVE) {
- // don't allow the player to turn around while game is paused
+ if (game_timeout) {
+ // don't allow the player to turn around while game is paused
// FIXME turn this into CSQC stuff
this.v_angle = this.lastV_angle;
this.angles = this.lastV_angle;
this.fixangle = true;
+ return false;
}
if (frametime) player_powerups(this);
TRANSMUTE(Observer, this);
PutClientInServer(this);
} else if(!SpectateUpdate(this) && !SpectateNext(this)) {
- PutObserverInServer(this);
+ PutObserverInServer(this, false);
this.would_spectate = true;
}
}
}
}
if(is_spec && !SpectateUpdate(this))
- PutObserverInServer(this);
+ PutObserverInServer(this, false);
}
if (is_spec)
this.flags |= FL_CLIENT | FL_NOTARGET;
// WORKAROUND: only use dropclient in server frames (frametime set).
// Never use it in cl_movement frames (frametime zero).
if (blockSpectators && IS_REAL_CLIENT(this)
- && (IS_SPEC(this) || IS_OBSERVER(this)) && !this.caplayer
+ && (IS_SPEC(this) || IS_OBSERVER(this)) && !INGAME(this)
&& time > (CS(this).spectatortime + autocvar_g_maxplayers_spectator_blocktime))
{
if (dropclient_schedule(this))
int totalClients = 0;
if(autocvar_sv_maxidle > 0 && autocvar_sv_maxidle_slots > 0)
{
- FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_maxidle_slots_countbots,
+ // maxidle disabled in local matches by not counting clients (totalClients 0)
+ if (server_is_dedicated)
+ {
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_maxidle_slots_countbots,
+ {
+ ++totalClients;
+ });
+ if (maxclients - totalClients > autocvar_sv_maxidle_slots)
+ totalClients = 0;
+ }
+ }
+ else if (IS_PLAYER(this) && autocvar_sv_maxidle_playertospectator > 0)
+ {
+ FOREACH_CLIENT(IS_REAL_CLIENT(it),
{
++totalClients;
});
}
- if (autocvar_sv_maxidle > 0 && autocvar_sv_maxidle_slots > 0 && (maxclients - totalClients) > autocvar_sv_maxidle_slots)
- { /* do nothing */ }
+ if (totalClients < autocvar_sv_maxidle_minplayers)
+ {
+ // idle kick disabled
+ CS(this).parm_idlesince = time;
+ }
else if (time - CS(this).parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
{
if (CS(this).idlekick_lasttimeleft)
if (IS_PLAYER(this) && autocvar_sv_maxidle_playertospectator > 0)
{
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_MOVETOSPEC_IDLING, this.netname, maxidle_time);
- if (this.caplayer)
- this.caplayer = 0;
- this.lms_spectate_warning = 2; // TODO: mutator hook for players forcibly moved to spectator?
- PutObserverInServer(this);
+ PutObserverInServer(this, true);
}
else
{