bool autocvar_con_chat;
bool autocvar_con_chatrect;
float autocvar_con_chatsize;
-float autocvar_con_chattime;
float autocvar_con_notify;
float autocvar_con_notifysize;
string autocvar_crosshair;
#include "hud_config.qh"
#include "../mapvoting.qh"
#include "../teamradar.qh"
+#include <common/minigames/cl_minigames.qh>
#include <common/t_items.qh>
#include <common/deathtypes/all.qh>
#include <common/items/_mod.qh>
}
}
-bool HUD_Minigame_Showpanels();
-
void HUD_Panel_Draw(entity panent)
{
panel = panent;
}
bool draw_allowed = false;
- if (HUD_Minigame_Showpanels())
+ if (active_minigame && HUD_MinigameMenu_IsOpened())
{
if (panel.panel_showflags & PANEL_SHOW_MINIGAME)
draw_allowed = true;
if(autocvar__hud_configure)
{
- vector chatsize;
- chatsize = '1 1 0' * autocvar_con_chatsize;
+ vector chatsize = '1 1 0' * autocvar_con_chatsize;
cvar_set("con_chatrect_x", "9001"); // over 9000, we'll fake it instead for more control over alpha and such
- float i, a;
- for(i = 0; i < autocvar_con_chat; ++i)
+ string str = textShortenToWidth(_("^3Player^7: This is the chat area."), mySize.x, chatsize, stringwidth_colors);
+ for(int i = 0; i < autocvar_con_chat; ++i)
{
- if(i == autocvar_con_chat - 1)
- a = panel_fg_alpha;
- else
- a = panel_fg_alpha * floor(((i + 1) * 7 + autocvar_con_chattime)/45);
- drawcolorcodedstring(pos, textShortenToWidth(_("^3Player^7: This is the chat area."), mySize.x, chatsize, stringwidth_colors), chatsize, a, DRAWFLAG_NORMAL);
+ // engine displays chat text at full alpha
+ drawcolorcodedstring(pos, str, chatsize, 1, DRAWFLAG_NORMAL);
pos.y += chatsize.y;
}
}
// Score (#7)
-void Scoreboard_UpdatePlayerTeams();
void HUD_Score_Rankings(vector pos, vector mySize, entity me)
{
float score;
{
float Team;
entity pl, tmp;
- float num;
-
- num = 0;
+ //int num = 0;
for(pl = players.sort_next; pl; pl = pl.sort_next)
{
- num += 1;
+ //num += 1;
Team = entcs_GetScoreTeam(pl.sv_entnum);
if(SetTeam(pl, Team))
{
TC(int, argc);
int i, slash;
string str, pattern;
- float have_name = 0, have_primary = 0, have_secondary = 0, have_separator = 0;
- float missing;
+ bool have_name = false, have_primary = false, have_secondary = false, have_separator = false;
+ int missing;
if(!gametype)
return; // do nothing, we don't know gametype and scores yet
LABEL(found)
sbt_field[sbt_num_fields] = j;
if(j == ps_primary)
- have_primary = 1;
+ have_primary = true;
if(j == ps_secondary)
- have_secondary = 1;
+ have_secondary = true;
}
}
}
if(scores_flags(ps_primary) & SFL_ALLOW_HIDE)
- have_primary = 1;
+ have_primary = true;
if(scores_flags(ps_secondary) & SFL_ALLOW_HIDE)
- have_secondary = 1;
+ have_secondary = true;
if(ps_primary == ps_secondary)
- have_secondary = 1;
+ have_secondary = true;
missing = (!have_primary) + (!have_secondary) + (!have_separator) + (!have_name);
if(sbt_num_fields + missing < MAX_SBT_FIELDS)
return end_pos;
}
-float Scoreboard_WouldDraw() {
+bool Scoreboard_WouldDraw()
+{
if (QuickMenu_IsOpened())
- return 0;
+ return false;
else if (HUD_Radar_Clickable())
- return 0;
+ return false;
else if (scoreboard_showscores)
- return 1;
+ return true;
else if (intermission == 1)
- return 1;
+ return true;
else if (intermission == 2)
- return 0;
+ return false;
else if (spectatee_status != -1 && STAT(HEALTH) <= 0 && autocvar_cl_deathscoreboard && gametype != MAPINFO_TYPE_CTS && !active_minigame)
- return 1;
+ return true;
else if (scoreboard_showscores_force)
- return 1;
- return 0;
+ return true;
+ return false;
}
float average_accuracy;
#pragma once
#include "../panel.qh"
-float scoreboard_active;
+bool scoreboard_active;
float scoreboard_fade_alpha;
void Cmd_Scoreboard_SetFields(float argc);
void Scoreboard_Draw();
void Scoreboard_InitScores();
+void Scoreboard_UpdatePlayerTeams();
void Scoreboard_UpdatePlayerPos(entity pl);
void Scoreboard_UpdateTeamPos(entity Team);
-float Scoreboard_WouldDraw();
+bool Scoreboard_WouldDraw();
void PostInit();
void CSQC_Demo_Camera();
-float Scoreboard_WouldDraw();
float camera_mode;
const float CAMERA_FREE = 1;
const float CAMERA_CHASE = 2;
if(autocvar__hud_configure)
HUD_Panel_Mouse();
- else if ( HUD_MinigameMenu_IsOpened() || minigame_isactive() )
+ else if (HUD_MinigameMenu_IsOpened() || active_minigame)
HUD_Minigame_Mouse();
else if(QuickMenu_IsOpened())
QuickMenu_Mouse();
# define TAG_VIEWLOC_NAME tag_networkviewloc
# define TAG_VIEWLOC_TYPE int
.float tag_networkviewloc;
-
-# define MOVETYPE_NAME move_movetype
#else
# define TAG_ENTITY_NAME tag_entity
# define TAG_ENTITY_TYPE entity
# define TAG_VIEWLOC_NAME viewloc
# define TAG_VIEWLOC_TYPE entity
-
-# define MOVETYPE_NAME move_movetype
#endif
// new fields
CSQCMODEL_PROPERTY(BIT(13), int, ReadInt24_t, WriteInt24_t, dphitcontentsmask) \
CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
CSQCMODEL_PROPERTY(BIT(15), int, ReadByte, WriteByte, multijump_count) \
- CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, MOVETYPE_NAME)
+ CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, move_movetype)
// TODO get rid of colormod/glowmod here; also get rid of some useless properties on non-players that only exist for CopyBody
// add hook function calls here
// minigame_player representing this client
entity minigame_self;
-// Whethere there's an active minigame
-float minigame_isactive()
-{
- return active_minigame != NULL;
-}
-
// Execute a minigame command
#define minigame_cmd(...) minigame_cmd_workaround(0,__VA_ARGS__)
void minigame_cmd_workaround(float dummy, string...cmdargc);
float HUD_MinigameMenu_IsOpened();
void HUD_MinigameMenu_Close(entity this, entity actor, entity trigger);
-float HUD_Minigame_Showpanels();
+
// Adds a game-specific entry to the menu
void HUD_MinigameMenu_CustomEntry(entity parent, string message, string event_arg);
{
mousepos_x = nPrimary;
mousepos_y = nSecondary;
- if ( minigame_isactive() && HUD_mouse_over(HUD_PANEL(MINIGAME_BOARD)) )
+ if ( active_minigame && HUD_mouse_over(HUD_PANEL(MINIGAME_BOARD)) )
active_minigame.minigame_event(active_minigame,"mouse_moved",mousepos);
return true;
return false;
}
- if ( minigame_isactive() && ( bInputType == 0 || bInputType == 1 ) )
+ if ( active_minigame && ( bInputType == 0 || bInputType == 1 ) )
{
string device = "";
string action = bInputType == 0 ? "pressed" : "released";
draw_cursor_normal(mousepos, '1 1 1', panel_fg_alpha);
}
-
-bool HUD_Minigame_Showpanels()
-{
- return (HUD_MinigameMenu_IsOpened() && minigame_isactive());
-}
this.TD(this, 1, 3, e = makeXonoticCheckBox(0, "cl_damagetext_friendlyfire", _("Draw damage numbers for friendly fire")));
setDependent(e, "cl_damagetext", 1, 1);
this.TR(this);
- this.TD(this, 1, 1, e = makeXonoticTextLabel(0, _("Color (Friendly Fire):")));
+ this.TD(this, 1, 1, e = makeXonoticTextLabel(0, _("Color:")));
setDependentAND(e, "cl_damagetext", 1, 1, "cl_damagetext_friendlyfire", 1, 1);
this.TD(this, 2, 2, e = makeXonoticColorpickerString("cl_damagetext_friendlyfire_color", "cl_damagetext_friendlyfire_color"));
setDependentAND(e, "cl_damagetext", 1, 1, "cl_damagetext_friendlyfire", 1, 1);
// used for notification system multi-team identifiers
#define APP_TEAM_NUM(num, prefix) ((num == NUM_TEAM_1) ? prefix##_RED : ((num == NUM_TEAM_2) ? prefix##_BLUE : ((num == NUM_TEAM_3) ? prefix##_YELLOW : prefix##_PINK)))
-/** @deprecated use APP_TEAM_NUM */
-#define APP_TEAM_ENT(ent, prefix) APP_TEAM_NUM(ent.team, prefix)
+#define APP_NUM(num, prefix) ((num) ? APP_TEAM_NUM(num, prefix) : prefix##_NEUTRAL)
#define EIGHT_VARS_TO_VARARGS_VARLIST \
VARITEM(1, 0, s1) \
.entity hook;
// TODO
- #define IS_CLIENT(s) ((s).isplayermodel)
+ #define IS_CLIENT(s) ((s).isplayermodel || (s) == csqcplayer)
#define IS_PLAYER(s) ((s).isplayermodel)
- #define IS_NOT_A_CLIENT(s) (!(s).isplayermodel)
+ #define IS_NOT_A_CLIENT(s) (!(s).isplayermodel && (s) != csqcplayer)
#define isPushable(s) ((s).isplayermodel || (s).pushable || ((s).flags & FL_PROJECTILE))
//float player_multijump;
}
vector old_camera_angle = '0 0 0';
+bool autocvar_cam_snap_close;
+bool autocvar_cam_track;
+bool autocvar_cam_snap_hard;
+bool autocvar_cam_snap_unlock;
void viewloc_SetViewLocation()
{
entity view = CSQCModel_server2csqc(player_localentnum - 1);
//NOTE: the "cam_" cvars sould probably be changed out with a spawnflag or an entity key. I have it like this for my testing -- Player_2
if(view.viewloc && !wasfreed(view.viewloc) && view.viewloc.enemy && view.viewloc.goalentity)
{
- vector position_a, position_b, camera_position, camera_angle, forward, backward;
+ vector position_a, position_b, camera_position, camera_angle = '0 0 0', forward, backward;
//vector scratch;
position_a = view.viewloc.enemy.origin;
camera_position = vec_bounds_in(view.origin, position_a, position_b);
- camera_angle = '0 0 0';
-
// a tracking camera follows the player when it leaves the world box
- if (cvar("cam_track")) {
+ if (autocvar_cam_track) {
camera_angle = aim_vec (camera_position, view.origin);
}
// hard snap changes the angle as soon as it crosses over the nearest 90 degree mark
- if (cvar("cam_snap_hard")){
+ if (autocvar_cam_snap_hard){
camera_angle = angle_snap_vec(aim_vec(camera_position, view.origin), 90);
}
// tries to avoid snapping unless it *really* needs to
- if (cvar("cam_snap_close")){
+ if (autocvar_cam_snap_close){
// like hard snap, but don't snap angles yet.
camera_angle = aim_vec(camera_position, view.origin);
}
//unlocking this allows the camera to look up and down. this also allows a top-down view.
- if (!cvar("cam_snap_unlock")) {
+ if (!autocvar_cam_snap_unlock) {
camera_angle_x = 0;
camera_angle_z = 0;
}
else
me.previewImage.src = me.currentMapPreviewImage;
- for(i = 0; i < GameType_GetCount(); ++i)
+ for(i = 0; i < GameType_GetTotalCount(); ++i)
{
entity e;
e = me.(typeLabels[i]);
me.TR(me);
me.TD(me, 1, w, e = makeXonoticTextLabel(0, _("Game types:")));
- n = ceil(GameType_GetCount() / (me.rows - 6));
+ n = ceil(GameType_GetTotalCount() / (me.rows - 6));
wgt = (w - 0.2) / n;
- for(i = 0; i < GameType_GetCount(); ++i)
+ for(i = 0; i < GameType_GetTotalCount(); ++i)
{
if(mod(i, n) == 0)
{
if(SKINBOOL_GAMETYPELIST_ICON_BLUR)
{
- for(int i = 0; i < GameType_GetCount(); ++i)
+ for(int i = 0; i < GameType_GetTotalCount(); ++i)
draw_PreloadPictureWithFlags(GameType_GetIcon(i), PRECACHE_PIC_MIPMAP);
}
GAMETYPE(MAPINFO_TYPE_NEXBALL) \
GAMETYPE(MAPINFO_TYPE_ONSLAUGHT) \
GAMETYPE(MAPINFO_TYPE_ASSAULT) \
- if (cvar("developer")) GAMETYPE(MAPINFO_TYPE_RACE) \
- if (cvar("developer")) GAMETYPE(MAPINFO_TYPE_CTS) \
/* GAMETYPE(MAPINFO_TYPE_INVASION) */ \
/**/
+// hidden gametypes come last so indexing always works correctly
+#define HIDDEN_GAMETYPES \
+ GAMETYPE(MAPINFO_TYPE_RACE) \
+ GAMETYPE(MAPINFO_TYPE_CTS) \
+ /**/
+
Gametype GameType_GetID(int cnt)
{
int i = 0;
#define GAMETYPE(it) { if (i++ == cnt) return it; }
GAMETYPES
+ HIDDEN_GAMETYPES
#undef GAMETYPE
return NULL;
}
#define GAMETYPE(id) ++i;
GAMETYPES
#undef GAMETYPE
+ #define GAMETYPE(it) if (cvar("developer")) ++i;
+ HIDDEN_GAMETYPES
+ #undef GAMETYPE
+ return i;
+}
+
+int GameType_GetTotalCount()
+{
+ int i = 0;
+ #define GAMETYPE(id) ++i;
+ GAMETYPES
+ HIDDEN_GAMETYPES
+ #undef GAMETYPE
return i;
}
string GameType_GetIcon(int cnt);
//string GameType_GetTeams(float cnt);
int GameType_GetCount();
+int GameType_GetTotalCount();
void dialog_hudpanel_common_notoggle(entity me, string panelname);
#define DIALOG_HUDPANEL_COMMON_NOTOGGLE() \
this.netname_previous = strzone(this.netname);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && IS_PLAYER(this)) ? APP_TEAM_ENT(this, INFO_JOIN_CONNECT_TEAM) : INFO_JOIN_CONNECT), this.netname);
+ if(teamplay && IS_PLAYER(this))
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_CONNECT_TEAM), this.netname);
+ else
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_CONNECT, this.netname);
stuffcmd(this, clientstuff, "\n");
stuffcmd(this, "cl_particles_reloadeffects\n"); // TODO do we still need this?
bool SpectateUpdate(entity this)
{
if(!this.enemy)
- return false;
+ return false;
if(!IS_PLAYER(this.enemy) || this == this.enemy)
{
}
}
-.float caplayer;
-
-void LeaveSpectatorMode(entity this)
+.bool team_selected;
+bool ShowTeamSelection(entity this)
{
- if(this.caplayer)
- return;
- if(nJoinAllowed(this, this))
- {
- if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (this.wasplayer && autocvar_g_changeteam_banned) || this.team_forced > 0)
- {
- TRANSMUTE(Player, this);
-
- SetSpectatee(this, NULL);
+ if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || this.team_selected || (this.wasplayer && autocvar_g_changeteam_banned) || this.team_forced > 0)
+ return false;
+ stuffcmd(this, "menu_showteamselect\n");
+ return true;
+}
+void Join(entity this)
+{
+ TRANSMUTE(Player, this);
- if(autocvar_g_campaign || autocvar_g_balance_teams)
- { JoinBestTeam(this, false, true); }
+ if(!this.team_selected)
+ if(autocvar_g_campaign || autocvar_g_balance_teams)
+ JoinBestTeam(this, false, true);
- if(autocvar_g_campaign)
- { campaign_bots_may_start = true; }
+ if(autocvar_g_campaign)
+ campaign_bots_may_start = true;
- Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_PREVENT_JOIN);
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_PREVENT_JOIN);
- PutClientInServer(this);
+ PutClientInServer(this);
- if(IS_PLAYER(this)) { Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && this.team != -1) ? APP_TEAM_ENT(this, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), this.netname); }
- }
- else
- stuffcmd(this, "menu_showteamselect\n");
- }
+ if(teamplay && this.team != -1)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
else
- {
- // Player may not join because g_maxplayers is set
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT);
- }
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname);
+ this.team_selected = false;
}
/**
* it checks whether the number of currently playing players exceeds g_maxplayers.
* @return int number of free slots for players, 0 if none
*/
-bool nJoinAllowed(entity this, entity ignore)
+int nJoinAllowed(entity this, entity ignore)
{
if(!ignore)
// this is called that way when checking if anyone may be able to join (to build qcstatus)
// so report 0 free slots if restricted
{
if(autocvar_g_forced_team_otherwise == "spectate")
- return false;
+ return 0;
if(autocvar_g_forced_team_otherwise == "spectator")
- return false;
+ return 0;
}
- if(this.team_forced < 0)
- return false; // forced spectators can never join
+ if(this && this.team_forced < 0)
+ return 0; // forced spectators can never join
// TODO simplify this
int totalClients = 0;
++currentlyPlaying;
));
+ float free_slots = 0;
if (!autocvar_g_maxplayers)
- return maxclients - totalClients;
+ free_slots = maxclients - totalClients;
+ else if(currentlyPlaying < autocvar_g_maxplayers)
+ free_slots = min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying);
- if(currentlyPlaying < autocvar_g_maxplayers)
- return min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying);
+ static float join_prevent_msg_time = 0;
+ if(this && ignore && !free_slots && time > join_prevent_msg_time)
+ {
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_JOIN_PREVENT);
+ join_prevent_msg_time = time + 3;
+ }
- return false;
+ return free_slots;
}
/**
}
}
+bool joinAllowed(entity this)
+{
+ if (this.version_mismatch) return false;
+ if (!nJoinAllowed(this, this)) return false;
+ if (teamplay && lockteams) return false;
+ if (ShowTeamSelection(this)) return false;
+ if (MUTATOR_CALLHOOK(ForbidSpawn, this)) return false;
+ return true;
+}
+
void ObserverThink(entity this)
{
if ( this.impulse )
MinigameImpulse(this, this.impulse);
this.impulse = 0;
}
+
if (this.flags & FL_JUMPRELEASED) {
- if (PHYS_INPUT_BUTTON_JUMP(this) && !this.version_mismatch) {
+ if (PHYS_INPUT_BUTTON_JUMP(this) && joinAllowed(this)) {
this.flags &= ~FL_JUMPRELEASED;
this.flags |= FL_SPAWNING;
} else if(PHYS_INPUT_BUTTON_ATCK(this) && !this.version_mismatch) {
if(this.flags & FL_SPAWNING)
{
this.flags &= ~FL_SPAWNING;
- LeaveSpectatorMode(this);
+ Join(this);
return;
}
}
return;
}
}
+
if (this.flags & FL_JUMPRELEASED) {
- if (PHYS_INPUT_BUTTON_JUMP(this) && !this.version_mismatch) {
+ if (PHYS_INPUT_BUTTON_JUMP(this) && joinAllowed(this)) {
this.flags &= ~FL_JUMPRELEASED;
this.flags |= FL_SPAWNING;
} else if(PHYS_INPUT_BUTTON_ATCK(this) || this.impulse == 10 || this.impulse == 15 || this.impulse == 18 || (this.impulse >= 200 && this.impulse <= 209)) {
if(this.flags & FL_SPAWNING)
{
this.flags &= ~FL_SPAWNING;
- LeaveSpectatorMode(this);
+ Join(this);
return;
}
}
}
}
+bool joinAllowed(entity this);
+void Join(entity this);
void ClientCommand_join(entity caller, float request)
{
switch (request)
{
case CMD_REQUEST_COMMAND:
{
- if (IS_CLIENT(caller))
- {
- if (!IS_PLAYER(caller) && !lockteams && !gameover)
- {
- if (caller.caplayer) return;
- if (nJoinAllowed(caller, caller))
- {
- if (autocvar_g_campaign) campaign_bots_may_start = true;
- TRANSMUTE(Player, caller);
- PlayerScore_Clear(caller);
- Kill_Notification(NOTIF_ONE_ONLY, caller, MSG_CENTER, CPID_PREVENT_JOIN);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((teamplay && caller.team != -1) ? APP_TEAM_ENT(caller, INFO_JOIN_PLAY_TEAM) : INFO_JOIN_PLAY), caller.netname);
- PutClientInServer(caller);
- }
- else
- {
- // player may not join because of g_maxplayers is set
- Send_Notification(NOTIF_ONE_ONLY, caller, MSG_CENTER, CENTER_JOIN_PREVENT);
- }
- }
- }
+ if (!gameover)
+ if (IS_CLIENT(caller) && !IS_PLAYER(caller))
+ if (joinAllowed(caller))
+ Join(caller);
+
return; // never fall through to usage
}
}
}
+.bool team_selected;
void ClientCommand_selectteam(entity caller, float request, float argc)
{
switch (request)
if (selection)
{
- if (caller.team == selection && !IS_DEAD(caller))
+ if (caller.team == selection && selection != -1 && !IS_DEAD(caller))
{
sprint(caller, "^7You already are on that team.\n");
}
}
ClientKill_TeamChange(caller, selection);
}
+ if(!IS_PLAYER(caller))
+ caller.team_selected = true; // avoids asking again for team selection on join
}
}
else
/**/
MUTATOR_HOOKABLE(PutClientInServer, EV_PutClientInServer);
+/**
+ * return true to prevent a spectator/observer to spawn as player
+ */
+ #define EV_ForbidSpawn(i, o) \
+ /** player */ i(entity, MUTATOR_ARGV_0_entity) \
+ /**/
+MUTATOR_HOOKABLE(ForbidSpawn, EV_ForbidSpawn);
+
/** called when a player spawns as player, after shared setup, before his weapon is chosen (so items may be changed in here) */
#define EV_PlayerSpawn(i, o) \
/** player spawning */ i(entity, MUTATOR_ARGV_0_entity) \
eliminatedPlayers.SendFlags |= 1;
}
+MUTATOR_HOOKFUNCTION(ca, 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 && player.caplayer)
+ return true;
+ return false;
+}
+
MUTATOR_HOOKFUNCTION(ca, PutClientInServer)
{
entity player = M_ARGV(0, entity);
return true;
}
-MUTATOR_HOOKFUNCTION(ca, ForbidPlayerScore_Clear)
-{
- return true;
-}
-
MUTATOR_HOOKFUNCTION(ca, MakePlayerObserver)
{
entity player = M_ARGV(0, entity);
if (!IS_DEAD(player))
ca_LastPlayerForTeam_Notify(player);
- if (player.killindicator_teamchange == -2)
+ if (player.killindicator_teamchange == -2) // player wants to spectate
player.caplayer = 0;
if (player.caplayer)
player.frags = FRAGS_LMS_LOSER;
- else
- player.frags = FRAGS_SPECTATOR;
if (!warmup_stage)
eliminatedPlayers.SendFlags |= 1;
+ if (!player.caplayer)
+ return false; // allow team reset
return true; // prevent team reset
}
string refername = db_get(ServerProgsDB, strcat(GetMapname(), "/captimerecord/netname"));
// notify about shit
- if(ctf_oneflag) { Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_CTF_CAPTURE_NEUTRAL, player.netname); }
- else if(!ctf_captimerecord) { Send_Notification(NOTIF_ALL, NULL, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_CAPTURE_TIME), player.netname, (cap_time * 100)); }
- else if(cap_time < cap_record) { Send_Notification(NOTIF_ALL, NULL, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_CAPTURE_BROKEN), player.netname, refername, (cap_time * 100), (cap_record * 100)); }
- else { Send_Notification(NOTIF_ALL, NULL, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_CAPTURE_UNBROKEN), player.netname, refername, (cap_time * 100), (cap_record * 100)); }
+ if(ctf_oneflag)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_CTF_CAPTURE_NEUTRAL, player.netname);
+ else if(!ctf_captimerecord)
+ Send_Notification(NOTIF_ALL, NULL, MSG_CHOICE, APP_TEAM_NUM(flag.team, CHOICE_CTF_CAPTURE_TIME), player.netname, (cap_time * 100));
+ else if(cap_time < cap_record)
+ Send_Notification(NOTIF_ALL, NULL, MSG_CHOICE, APP_TEAM_NUM(flag.team, CHOICE_CTF_CAPTURE_BROKEN), player.netname, refername, (cap_time * 100), (cap_record * 100));
+ else
+ Send_Notification(NOTIF_ALL, NULL, MSG_CHOICE, APP_TEAM_NUM(flag.team, CHOICE_CTF_CAPTURE_UNBROKEN), player.netname, refername, (cap_time * 100), (cap_record * 100));
// write that shit in the database
if(!ctf_oneflag) // but not in 1-flag mode
flag.ctf_status = FLAG_DROPPED;
// messages and sounds
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_LOST) : INFO_CTF_LOST_NEUTRAL), player.netname);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_LOST), player.netname);
_sound(flag, CH_TRIGGER, flag.snd_flag_dropped, VOL_BASE, ATTEN_NONE);
ctf_EventLog("dropped", player.team, player);
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), LAMBDA(
if(it == sender)
- Send_Notification(NOTIF_ONE, it, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT(flag, CENTER_CTF_PASS_SENT) : CENTER_CTF_PASS_SENT_NEUTRAL), player.netname);
+ Send_Notification(NOTIF_ONE, it, MSG_CENTER, APP_NUM(flag.team, CENTER_CTF_PASS_SENT), player.netname);
else if(it == player)
- Send_Notification(NOTIF_ONE, it, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT(flag, CENTER_CTF_PASS_RECEIVED) : CENTER_CTF_PASS_RECEIVED_NEUTRAL), sender.netname);
+ Send_Notification(NOTIF_ONE, it, MSG_CENTER, APP_NUM(flag.team, CENTER_CTF_PASS_RECEIVED), sender.netname);
else if(SAME_TEAM(it, sender))
- Send_Notification(NOTIF_ONE, it, MSG_CENTER, ((flag.team) ? APP_TEAM_ENT(flag, CENTER_CTF_PASS_OTHER) : CENTER_CTF_PASS_OTHER_NEUTRAL), sender.netname, player.netname);
+ Send_Notification(NOTIF_ONE, it, MSG_CENTER, APP_NUM(flag.team, CENTER_CTF_PASS_OTHER), sender.netname, player.netname);
));
// create new waypoint
player.throw_count = 0;
// messages and sounds
- Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((enemy_flag.team) ? APP_TEAM_ENT(enemy_flag, CENTER_CTF_CAPTURE) : CENTER_CTF_CAPTURE_NEUTRAL));
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_NUM(enemy_flag.team, CENTER_CTF_CAPTURE));
ctf_CaptureRecord(enemy_flag, player);
_sound(player, CH_TRIGGER, ((ctf_oneflag) ? player_team_flag.snd_flag_capture : ((DIFF_TEAM(player, flag)) ? enemy_flag.snd_flag_capture : flag.snd_flag_capture)), VOL_BASE, ATTEN_NONE);
// messages and sounds
if(IS_MONSTER(player))
{
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(flag, INFO_CTF_RETURN_MONSTER), player.monster_name);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(flag.team, INFO_CTF_RETURN_MONSTER), player.monster_name);
}
else if(flag.team)
{
- Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT(flag, CENTER_CTF_RETURN));
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(flag, INFO_CTF_RETURN), player.netname);
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_NUM(flag.team, CENTER_CTF_RETURN));
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(flag.team, INFO_CTF_RETURN), player.netname);
}
_sound(player, CH_TRIGGER, flag.snd_flag_returned, VOL_BASE, ATTEN_NONE);
ctf_EventLog("return", flag.team, player);
}
// messages and sounds
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_PICKUP) : INFO_CTF_PICKUP_NEUTRAL), player.netname);
- if(ctf_stalemate) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER); }
- if(!flag.team) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PICKUP_NEUTRAL); }
- else if(CTF_DIFFTEAM(player, flag)) { Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_ENT(flag, CENTER_CTF_PICKUP)); }
- else { Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((SAME_TEAM(player, flag)) ? CENTER_CTF_PICKUP_TEAM : CENTER_CTF_PICKUP_TEAM_ENEMY), Team_ColorCode(flag.team)); }
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_PICKUP), player.netname);
+ if(ctf_stalemate)
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_STALEMATE_CARRIER);
+ if(!flag.team)
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PICKUP_NEUTRAL);
+ else if(CTF_DIFFTEAM(player, flag))
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, APP_TEAM_NUM(flag.team, CENTER_CTF_PICKUP));
+ else
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, ((SAME_TEAM(player, flag)) ? CENTER_CTF_PICKUP_TEAM : CENTER_CTF_PICKUP_TEAM_ENEMY), Team_ColorCode(flag.team));
- Send_Notification(NOTIF_TEAM_EXCEPT, player, MSG_CHOICE, ((flag.team) ? APP_TEAM_ENT(flag, CHOICE_CTF_PICKUP_TEAM) : CHOICE_CTF_PICKUP_TEAM_NEUTRAL), Team_ColorCode(player.team), player.netname);
+ Send_Notification(NOTIF_TEAM_EXCEPT, player, MSG_CHOICE, APP_NUM(flag.team, CHOICE_CTF_PICKUP_TEAM), Team_ColorCode(player.team), player.netname);
if(!flag.team)
FOREACH_CLIENT(IS_PLAYER(it) && it != player && DIFF_TEAM(it, player), LAMBDA(Send_Notification(NOTIF_ONE, it, MSG_CHOICE, CHOICE_CTF_PICKUP_ENEMY_NEUTRAL, Team_ColorCode(player.team), player.netname)));
FOREACH_CLIENT(IS_PLAYER(it) && it != player, LAMBDA(
if(CTF_SAMETEAM(flag, it))
if(SAME_TEAM(player, it))
- Send_Notification(NOTIF_ONE, it, MSG_CHOICE, APP_TEAM_ENT(flag, CHOICE_CTF_PICKUP_TEAM), Team_ColorCode(player.team), player.netname);
+ Send_Notification(NOTIF_ONE, it, MSG_CHOICE, APP_TEAM_NUM(flag.team, CHOICE_CTF_PICKUP_TEAM), Team_ColorCode(player.team), player.netname);
else
Send_Notification(NOTIF_ONE, it, MSG_CHOICE, ((SAME_TEAM(flag, player)) ? CHOICE_CTF_PICKUP_ENEMY_TEAM : CHOICE_CTF_PICKUP_ENEMY), Team_ColorCode(player.team), player.netname);
));
{
switch(returntype)
{
- case RETURN_DROPPED: Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_DROPPED) : INFO_CTF_FLAGRETURN_DROPPED_NEUTRAL)); break;
- case RETURN_DAMAGE: Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_DAMAGED) : INFO_CTF_FLAGRETURN_DAMAGED_NEUTRAL)); break;
- case RETURN_SPEEDRUN: Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_SPEEDRUN) : INFO_CTF_FLAGRETURN_SPEEDRUN_NEUTRAL), ctf_captimerecord); break;
- case RETURN_NEEDKILL: Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_NEEDKILL) : INFO_CTF_FLAGRETURN_NEEDKILL_NEUTRAL)); break;
-
+ case RETURN_DROPPED:
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_FLAGRETURN_DROPPED)); break;
+ case RETURN_DAMAGE:
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_FLAGRETURN_DAMAGED)); break;
+ case RETURN_SPEEDRUN:
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_FLAGRETURN_SPEEDRUN), ctf_captimerecord); break;
+ case RETURN_NEEDKILL:
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_FLAGRETURN_NEEDKILL)); break;
default:
case RETURN_TIMEOUT:
- { Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((flag.team) ? APP_TEAM_ENT(flag, INFO_CTF_FLAGRETURN_TIMEOUT) : INFO_CTF_FLAGRETURN_TIMEOUT_NEUTRAL)); break; }
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(flag.team, INFO_CTF_FLAGRETURN_TIMEOUT)); break;
}
_sound(flag, CH_TRIGGER, flag.snd_flag_respawn, VOL_BASE, ATTEN_NONE);
ctf_EventLog("returned", flag.team, NULL);
if(player.flagcarried)
{
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, ((player.flagcarried.team) ? APP_TEAM_ENT(player.flagcarried, INFO_CTF_FLAGRETURN_ABORTRUN) : INFO_CTF_FLAGRETURN_ABORTRUN_NEUTRAL));
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_NUM(player.flagcarried.team, INFO_CTF_FLAGRETURN_ABORTRUN));
ctf_RespawnFlag(player.flagcarried);
return true;
}
PlayerScore_Add(player, SP_KH_PICKUPS, 1);
}
key.kh_dropperteam = 0;
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(key, INFO_KEYHUNT_PICKUP), player.netname);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(key.team, INFO_KEYHUNT_PICKUP), player.netname);
kh_Key_AssignTo(key, player); // this also updates .kh_state
}
}
}
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(lostkey, INFO_KEYHUNT_LOST), lostkey.kh_previous_owner.netname);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(lostkey.team, INFO_KEYHUNT_LOST), lostkey.kh_previous_owner.netname);
play2all(SND(KH_DESTROY));
te_tarexplosion(lostkey.origin);
kh_Scores_Event(player, key, "dropkey", 0, 0);
PlayerScore_Add(player, SP_KH_LOSSES, 1);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(key, INFO_KEYHUNT_DROP), player.netname);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(key.team, INFO_KEYHUNT_DROP), player.netname);
kh_Key_AssignTo(key, NULL);
makevectors(player.v_angle);
{
kh_Scores_Event(player, key, "losekey", 0, 0);
PlayerScore_Add(player, SP_KH_LOSSES, 1);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_ENT(key, INFO_KEYHUNT_LOST), player.netname);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(key.team, INFO_KEYHUNT_LOST), player.netname);
kh_Key_AssignTo(key, NULL);
makevectors('-1 0 0' * (45 + 45 * random()) + '0 360 0' * random());
key.velocity = W_CalculateProjectileVelocity(player, player.velocity, autocvar_g_balance_keyhunt_dropvelocity * v_forward, false);