#include "bot/api.qh"
#include "../common/ent_cs.qh"
+#include "../common/wepent.qh"
#include <common/state.qh>
#include <common/effects/qc/globalsound.qh>
this.view_ofs = '0 0 0';
}
- RemoveGrapplingHook(this);
+ RemoveGrapplingHooks(this);
Portal_ClearAll(this);
Unfreeze(this);
SetSpectatee(this, NULL);
this.istypefrag = 0;
setthink(this, func_null);
this.nextthink = 0;
- this.hook_time = 0;
this.deadflag = DEAD_NO;
this.crouch = false;
this.revival_time = 0;
this.weapons = '0 0 0';
this.drawonlytoclient = this;
- this.weaponname = "";
this.weaponmodel = "";
for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
+ this.weaponentities[slot].hook_time = 0;
+ this.weaponentities[slot].weaponname = "";
this.weaponentities[slot] = NULL;
}
this.exteriorweaponentity = NULL;
it.wr_resetplayer(it, this);
// reload all reloadable weapons
if (it.spawnflags & WEP_FLAG_RELOADABLE) {
- this.weapon_load[it.m_id] = it.reloading_ammo;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ this.(weaponentity).weapon_load[it.m_id] = it.reloading_ammo;
+ }
}
));
delete(spot); // usefull for checking if there are spawnpoints, that let drop through the floor
}
- PS(this).m_switchweapon = w_getbestweapon(this);
- this.cnt = -1; // W_LastWeapon will not complain
- PS(this).m_weapon = WEP_Null;
- this.weaponname = "";
- PS(this).m_switchingweapon = WEP_Null;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(slot == 0)
+ this.(weaponentity).m_switchweapon = w_getbestweapon(this, weaponentity);
+ else
+ this.(weaponentity).m_switchweapon = WEP_Null;
+ this.(weaponentity).weaponname = "";
+ this.(weaponentity).m_switchingweapon = WEP_Null;
+ this.(weaponentity).cnt = -1;
+ }
if (!warmup_stage && !this.alivetime)
this.alivetime = time;
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?
Unfreeze(this);
- RemoveGrapplingHook(this);
+ RemoveGrapplingHooks(this);
// Here, everything has been done that requires this player to be a client.
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;
}
}
{
if ((this.respawn_flags & RESPAWN_FORCE) && !(this.respawn_time < this.respawn_time_max))
this.deadflag = DEAD_RESPAWNING;
- else if (!button_pressed || (this.respawn_flags & RESPAWN_FORCE))
+ else if (!button_pressed || (time >= this.respawn_time_max && (this.respawn_flags & RESPAWN_FORCE)))
this.deadflag = DEAD_DEAD;
break;
}
{
this.items &= ~this.items_added;
- //for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- //{
- //.entity weaponentity = weaponentities[slot];
- //W_WeaponFrame(this, weaponentity);
- //}
- .entity weaponentity = weaponentities[0]; // TODO
- W_WeaponFrame(this, weaponentity);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ W_WeaponFrame(this, weaponentity);
+
+ if(slot == 0)
+ {
+ this.clip_load = this.(weaponentity).clip_load;
+ this.clip_size = this.(weaponentity).clip_size;
+ }
+ }
this.items_added = 0;
if (this.items & ITEM_Jetpack.m_itemid && (this.items & ITEM_JetpackRegen.m_itemid || this.ammo_fuel >= 0.01))
// WEAPONTODO: Add a weapon request for this
// rot vortex charge to the charge limit
- if (WEP_CVAR(vortex, charge_rot_rate) && this.vortex_charge > WEP_CVAR(vortex, charge_limit) && this.vortex_charge_rottime < time)
- this.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time)
+ this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+ }
if (frametime) player_anim(this);
// WEAPONTODO: Add weapon request for this
if (!zoomstate_set) {
- SetZoomState(this,
- PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this)
- || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_VORTEX)
- || (PHYS_INPUT_BUTTON_ATCK2(this) && PS(this).m_weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)
- );
+ bool wep_zoomed = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ Weapon thiswep = this.(weaponentity).m_weapon;
+ if(thiswep != WEP_Null && thiswep.wr_zoom)
+ wep_zoomed += thiswep.wr_zoom(thiswep, this);
+ }
+ SetZoomState(this, PHYS_INPUT_BUTTON_ZOOM(this) || PHYS_INPUT_BUTTON_ZOOMSCRIPT(this) || wep_zoomed);
}
if (this.teamkill_soundtime && time > this.teamkill_soundtime)
// WEAPONTODO: Move into weaponsystem somehow
// if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
- if (PS(this).m_weapon == WEP_Null)
- this.clip_load = this.clip_size = 0;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).m_weapon == WEP_Null)
+ this.(weaponentity).clip_load = this.(weaponentity).clip_size = 0;
+ }
}
void DrownPlayer(entity this)