X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Fserver%2Fcl_client.qc;h=f34e22b0d9a15224940df81013b852c705091e33;hb=57356786644b16c2a56f5127ba6fadd60aa8d742;hp=a69a656f317967354099c8890444a14d3d292d0d;hpb=efab64ab443b4182a8dda35f0fb517eb78897ea0;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index a69a656f3..f34e22b0d 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -404,8 +404,7 @@ void PutObserverInServer (void) DropAllRunes(self); MUTATOR_CALLHOOK(MakePlayerObserver); - if (g_minstagib) - minstagib_stop_countdown(); + minstagib_stop_countdown(self); Portal_ClearAll(self); @@ -421,9 +420,6 @@ void PutObserverInServer (void) if(self.flagcarried) DropFlag(self.flagcarried, world, world); - if(self.ballcarried && g_nexball) - DropBall(self.ballcarried, self.origin + self.ballcarried.origin, self.velocity); - WaypointSprite_PlayerDead(); if not(g_ca) // don't reset teams when moving a ca player to the spectators @@ -456,7 +452,7 @@ void PutObserverInServer (void) self.health = -666; self.takedamage = DAMAGE_NO; self.solid = SOLID_NOT; - self.movetype = MOVETYPE_FLY_WORLDONLY; //(self.cvar_cl_clippedspectating ? MOVETYPE_NOCLIP : MOVETYPE_FLY); // it's too early for this anyway, lets just set it in playerprethink + self.movetype = MOVETYPE_FLY_WORLDONLY; // user preference is controlled by playerprethink self.flags = FL_CLIENT | FL_NOTARGET; self.armorvalue = 666; self.effects = 0; @@ -466,7 +462,7 @@ void PutObserverInServer (void) self.pauseregen_finished = 0; self.damageforcescale = 0; self.death_time = 0; - self.dead_frame = 0; + self.respawn_time = 0; self.alpha = 0; self.scale = 0; self.fade_time = 0; @@ -474,6 +470,7 @@ void PutObserverInServer (void) self.pain_finished = 0; self.strength_finished = 0; self.invincible_finished = 0; + self.superweapons_finished = 0; self.pushltime = 0; self.think = SUB_Null; self.nextthink = 0; @@ -485,10 +482,10 @@ void PutObserverInServer (void) self.fixangle = TRUE; self.crouch = FALSE; - setorigin (self, spot.origin); + setorigin (self, (spot.origin + PL_VIEW_OFS)); // offset it so that the spectator spawns higher off the ground, looks better this way self.prevorigin = self.origin; self.items = 0; - self.weapons = 0; + WEPSET_CLEAR_E(self); self.model = ""; FixPlayermodel(); setmodel(self, "null"); @@ -644,11 +641,14 @@ Called when a client spawns in the server ============= */ //void() ctf_playerchanged; + void PutClientInServer (void) { if(clienttype(self) == CLIENTTYPE_BOT) { self.classname = "player"; + if(g_ca) + self.caplayer = 1; } else if(clienttype(self) == CLIENTTYPE_REAL) { @@ -656,7 +656,7 @@ void PutClientInServer (void) WriteByte(MSG_ONE, SVC_SETVIEW); WriteEntity(MSG_ONE, self); } - + // reset player keys self.itemkeys = 0; @@ -668,8 +668,7 @@ void PutClientInServer (void) self.classname = "observer"; } - if(g_arena || (g_ca && !allowed_to_spawn)) - if(!self.spawned) + if((g_arena && !self.spawned) || (g_ca && !allowed_to_spawn)) self.classname = "observer"; if(gameover) @@ -736,7 +735,7 @@ void PutClientInServer (void) self.ammo_fuel = warmup_start_ammo_fuel; self.health = warmup_start_health; self.armorvalue = warmup_start_armorvalue; - self.weapons = warmup_start_weapons; + WEPSET_COPY_EA(self, warmup_start_weapons); } else { @@ -747,20 +746,24 @@ void PutClientInServer (void) self.ammo_fuel = start_ammo_fuel; self.health = start_health; self.armorvalue = start_armorvalue; - self.weapons = start_weapons; + WEPSET_COPY_EA(self, start_weapons); } + if(WEPSET_CONTAINS_ANY_EA(self, WEPBIT_SUPERWEAPONS)) // exception for minstagib, as minstanex is a superweapon + self.superweapons_finished = time + autocvar_g_balance_superweapons_time; + else + self.superweapons_finished = 0; + if(g_weaponarena_random) { if(g_weaponarena_random_with_laser) - self.weapons &~= WEPBIT_LASER; - self.weapons = randombits(self.weapons, g_weaponarena_random, FALSE); + WEPSET_ANDNOT_EW(self, WEP_LASER); + W_RandomWeapons(self, g_weaponarena_random); if(g_weaponarena_random_with_laser) - self.weapons |= WEPBIT_LASER; + WEPSET_OR_EW(self, WEP_LASER); } self.items = start_items; - self.jump_interval = time; self.spawnshieldtime = time + autocvar_g_spawnshieldtime; self.pauserotarmor_finished = time + autocvar_g_balance_pause_armor_rot_spawn; @@ -776,8 +779,7 @@ void PutClientInServer (void) } self.damageforcescale = 2; self.death_time = 0; - self.dead_frame = 0; - self.alpha = 0; + self.respawn_time = 0; self.scale = 0; self.fade_time = 0; self.pain_frame = 0; @@ -830,13 +832,12 @@ void PutClientInServer (void) self.lastrocket = world; // stop rocket guiding, no revenge from the grave! self.lastteleporttime = time; // prevent insane speeds due to changing origin self.hud = HUD_NORMAL; - + if(g_arena) { Spawnqueue_Remove(self); Spawnqueue_Mark(self); } - else if(g_ca) self.caplayer = 1; @@ -920,7 +921,7 @@ void PutClientInServer (void) self.alivetime = time; antilag_clear(self); - } else if(self.classname == "observer" || (g_ca && !allowed_to_spawn)) { + } else if(self.classname == "observer") { PutObserverInServer (); } @@ -963,6 +964,7 @@ float ClientInit_SendEntity(entity to, float sf) WriteByte(MSG_ENTITY, autocvar_g_balance_minelayer_limit); // minelayer max mines WriteByte(MSG_ENTITY, autocvar_g_balance_hagar_secondary_load_max); // hagar max loadable rockets WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange); + WriteByte(MSG_ENTITY, autocvar_g_balance_porto_secondary); return TRUE; } @@ -1116,7 +1118,7 @@ void KillIndicator_Think() return; } - if (self.owner.effects & CSQCMODEL_EF_INVISIBLE) + if (self.owner.alpha < 0) { self.owner.killindicator = world; remove(self); @@ -1504,8 +1506,6 @@ void ClientConnect (void) else stuffcmd(self, "set _teams_available 0\n"); - stuffcmd(self, strcat("set gametype ", ftos(game), "\n")); - if(g_arena || g_ca) { self.classname = "observer"; @@ -1532,7 +1532,7 @@ void ClientConnect (void) if(clienttype(self) == CLIENTTYPE_REAL) { - if(autocvar_g_bugrigs || g_weaponarena == WEPBIT_TUBA) + if(autocvar_g_bugrigs || WEPSET_EQ_AW(g_weaponarena_weapons, WEP_TUBA)) stuffcmd(self, "cl_cmd settemp chase_active 1\n"); } @@ -1593,8 +1593,12 @@ void ClientConnect (void) CSQCMODEL_AUTOINIT(); self.model_randomizer = random(); + + if(clienttype(self) != CLIENTTYPE_REAL) + return; + + sv_notice_join(); } - /* ============= ClientDisconnect @@ -1650,8 +1654,6 @@ void ClientDisconnect (void) RemoveGrapplingHook(self); if(self.flagcarried) DropFlag(self.flagcarried, world, world); - if(self.ballcarried && g_nexball) - DropBall(self.ballcarried, self.origin + self.ballcarried.origin, self.velocity); // Here, everything has been done that requires this player to be a client. @@ -1700,7 +1702,7 @@ void ClientDisconnect (void) void ChatBubbleThink() { self.nextthink = time; - if ((self.owner.effects & CSQCMODEL_EF_INVISIBLE) || self.owner.chatbubbleentity != self) + if ((self.owner.alpha < 0) || self.owner.chatbubbleentity != self) { if(self.owner) // but why can that ever be world? self.owner.chatbubbleentity = world; @@ -1719,7 +1721,7 @@ void ChatBubbleThink() void UpdateChatBubble() { - if (self.effects & CSQCMODEL_EF_INVISIBLE) + if (self.alpha < 0) return; // spawn a chatbubble entity if needed if (!self.chatbubbleentity) @@ -1756,31 +1758,24 @@ void UpdateChatBubble() else self.colormod = '1 1 1'; }*/ -.float oldcolormap; void respawn(void) { - if(!(self.effects & CSQCMODEL_EF_INVISIBLE) && autocvar_g_respawn_ghosts) + if(self.alpha >= 0 && autocvar_g_respawn_ghosts) { self.solid = SOLID_NOT; self.takedamage = DAMAGE_NO; self.movetype = MOVETYPE_FLY; self.velocity = '0 0 1' * autocvar_g_respawn_ghosts_speed; self.avelocity = randomvec() * autocvar_g_respawn_ghosts_speed * 3 - randomvec() * autocvar_g_respawn_ghosts_speed * 3; - self.effects |= EF_ADDITIVE; - self.oldcolormap = self.colormap; - self.colormap = 0; // this originally was 512, but raises a warning in the engine, so get rid of it + self.effects |= CSQCMODEL_EF_RESPAWNGHOST; pointparticles(particleeffectnum("respawn_ghost"), self.origin, '0 0 0', 1); if(autocvar_g_respawn_ghosts_maxtime) SUB_SetFade (self, time + autocvar_g_respawn_ghosts_maxtime / 2 + random () * (autocvar_g_respawn_ghosts_maxtime - autocvar_g_respawn_ghosts_maxtime / 2), 1.5); } CopyBody(1); + self.effects |= EF_NODRAW; // prevent another CopyBody - if(self.oldcolormap) - { - self.colormap = self.oldcolormap; - self.oldcolormap = 0; - } PutClientInServer(); } @@ -1810,7 +1805,7 @@ void player_powerups (void) self.effects &~= (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT | EF_FLAME | EF_NODEPTHTEST); - if((self.effects & CSQCMODEL_EF_INVISIBLE) || self.deadflag) // don't apply the flags if the player is gibbed + if(self.alpha < 0 || self.deadflag) // don't apply the flags if the player is gibbed return; Fire_ApplyDamage(self); @@ -1898,26 +1893,66 @@ void player_powerups (void) sprint(self, "^3Shield surrounds you\n"); } } + if (self.items & IT_SUPERWEAPON) + { + if (!WEPSET_CONTAINS_ANY_EA(self, WEPBIT_SUPERWEAPONS)) + { + self.superweapons_finished = 0; + self.items = self.items - (self.items & IT_SUPERWEAPON); + sprint(self, "^3Superweapons have been lost\n"); + } + else if (self.items & IT_UNLIMITED_SUPERWEAPONS) + { + // don't let them run out + } + else + { + play_countdown(self.superweapons_finished, "misc/poweroff.wav"); + if (time > self.superweapons_finished) + { + self.items = self.items - (self.items & IT_SUPERWEAPON); + WEPSET_ANDNOT_EA(self, WEPBIT_SUPERWEAPONS); + sprint(self, "^3Superweapons have broken down\n"); + } + } + } + else if(WEPSET_CONTAINS_ANY_EA(self, WEPBIT_SUPERWEAPONS)) + { + if (time < self.superweapons_finished || (self.items & IT_UNLIMITED_SUPERWEAPONS)) + { + self.items = self.items | IT_SUPERWEAPON; + sprint(self, "^3You now have a superweapon\n"); + } + else + { + self.superweapons_finished = 0; + WEPSET_ANDNOT_EA(self, WEPBIT_SUPERWEAPONS); + } + } + else + { + self.superweapons_finished = 0; + } + } + + if(autocvar_g_nodepthtestplayers) + self.effects = self.effects | EF_NODEPTHTEST; - if(autocvar_g_nodepthtestplayers) - self.effects = self.effects | EF_NODEPTHTEST; - - if(autocvar_g_fullbrightplayers) - self.effects = self.effects | EF_FULLBRIGHT; + if(autocvar_g_fullbrightplayers) + self.effects = self.effects | EF_FULLBRIGHT; - // midair gamemode: damage only while in the air - // if in midair mode, being on ground grants temporary invulnerability - // (this is so that multishot weapon don't clear the ground flag on the - // first damage in the frame, leaving the player vulnerable to the - // remaining hits in the same frame) - if (self.flags & FL_ONGROUND) - if (g_midair) - self.spawnshieldtime = max(self.spawnshieldtime, time + autocvar_g_midair_shieldtime); + // midair gamemode: damage only while in the air + // if in midair mode, being on ground grants temporary invulnerability + // (this is so that multishot weapon don't clear the ground flag on the + // first damage in the frame, leaving the player vulnerable to the + // remaining hits in the same frame) + if (self.flags & FL_ONGROUND) + if (g_midair) + self.spawnshieldtime = max(self.spawnshieldtime, time + autocvar_g_midair_shieldtime); - if (time >= game_starttime) - if (time < self.spawnshieldtime) - self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); - } + if (time >= game_starttime) + if (time < self.spawnshieldtime) + self.effects = self.effects | (EF_ADDITIVE | EF_FULLBRIGHT); MUTATOR_CALLHOOK(PlayerPowerups); } @@ -2118,7 +2153,7 @@ void SpectateCopy(entity spectatee) { self.strength_finished = spectatee.strength_finished; self.invincible_finished = spectatee.invincible_finished; self.pressedkeys = spectatee.pressedkeys; - self.weapons = spectatee.weapons; + WEPSET_COPY_EE(self, spectatee); self.switchweapon = spectatee.switchweapon; self.switchingweapon = spectatee.switchingweapon; self.weapon = spectatee.weapon; @@ -2261,13 +2296,13 @@ void ShowRespawnCountdown() return; else { - number = ceil(self.death_time - time); + number = ceil(self.respawn_time - time); if(number <= 0) return; if(number <= self.respawn_countdown) { self.respawn_countdown = number - 1; - if(ceil(self.death_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds + if(ceil(self.respawn_time - (time + 0.5)) == number) // only say it if it is the same number even in 0.5s; to prevent overlapping sounds AnnounceTo(self, strcat(ftos(number), "")); } } @@ -2276,7 +2311,7 @@ void ShowRespawnCountdown() .float prevent_join_msgtime; void LeaveSpectatorMode() { - if(nJoinAllowed(1)) { + if(nJoinAllowed(self)) { if(!teamplay || autocvar_g_campaign || autocvar_g_balance_teams || (self.wasplayer && autocvar_g_changeteam_banned) || self.team_forced > 0) { self.classname = "player"; @@ -2326,26 +2361,36 @@ void LeaveSpectatorMode() * it checks whether the number of currently playing players exceeds g_maxplayers. * @return int number of free slots for players, 0 if none */ -float nJoinAllowed(float includeMe) { +float nJoinAllowed(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 0; + if(autocvar_g_forced_team_otherwise == "spectator") + return 0; + } + if(self.team_forced < 0) - return FALSE; // forced spectators can never join + return 0; // forced spectators can never join // TODO simplify this entity e; - float totalClients; FOR_EACH_CLIENT(e) - totalClients += 1; + if(e != ignore) + totalClients += 1; if (!autocvar_g_maxplayers) - return maxclients - totalClients + includeMe; + return maxclients - totalClients; float currentlyPlaying; FOR_EACH_REALPLAYER(e) currentlyPlaying += 1; if(currentlyPlaying < autocvar_g_maxplayers) - return min(maxclients - totalClients + includeMe, autocvar_g_maxplayers - currentlyPlaying); + return min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying); return 0; } @@ -2643,9 +2688,9 @@ void PlayerPreThink (void) float button_pressed, force_respawn; if(self.personal && g_race_qualifying) { - if(time > self.death_time) + if(time > self.respawn_time) { - self.death_time = time + 1; // only retry once a second + self.respawn_time = time + 1; // only retry once a second respawn(); self.impulse = 141; } @@ -2675,9 +2720,9 @@ void PlayerPreThink (void) } else if (self.deadflag == DEAD_RESPAWNING) { - if(time > self.death_time) + if(time > self.respawn_time) { - self.death_time = time + 1; // only retry once a second + self.respawn_time = time + 1; // only retry once a second respawn(); } } @@ -3003,8 +3048,6 @@ void PlayerPostThink (void) } */ - Arena_Warmup(); - //pointparticles(particleeffectnum("machinegun_impact"), self.origin + self.view_ofs + '0 0 7', '0 0 0', 1); if(self.waypointsprite_attachedforcarrier)