newmodel_extension = substring(self.playermodel, strlen(self.playermodel) - 4, 4);\r
\r
float vore_state;\r
- if(self.stomach_load > ceil(g_balance_vore_swallow_limit * 0.666666666666))\r
+ if(self.stomach_load > self.stomach_maxload * 0.6)\r
vore_state = 3;\r
- else if(self.stomach_load > ceil(g_balance_vore_swallow_limit * 0.333333333333))\r
+ else if(self.stomach_load > self.stomach_maxload * 0.3)\r
vore_state = 2;\r
else if(self.stomach_load)\r
vore_state = 1;\r
// this is only visible to the prey however, otherwise players would appear as a floating stomach to everyone (ewww)\r
stomachmodel = strcat(substring(self.playermodel, 0, strlen(self.playermodel) - 4), "_stomach.md3"); // 4 is the extension length\r
\r
- if(other.spectatee_status)\r
+ float chase;\r
+ chase = other.cvar_chase_active;\r
+\r
+ if(other.spectatee_status && other.spectatee_status == num_for_edict(other.enemy))\r
other = other.enemy; // also do this for the player we are spectating\r
\r
// don't do this if we have chase_active enabled, as we'd be seeing a floating stomach from third person view\r
- if not(other.cvar_chase_active || other.classname == "observer") // the observer check prevents a bug\r
+ if not(chase || other.classname == "observer") // the observer check prevents a bug\r
if(other.predator == self || other.fakepredator == self)\r
{\r
Client_setmodel(stomachmodel);\r
+ self.effects |= EF_NODEPTHTEST; // don't hide behind walls\r
self.alpha = other.cvar_cl_vore_stomachmodel;\r
return TRUE;\r
}\r
\r
Client_setmodel(setmodel_state());\r
+ self.effects &~= EF_NODEPTHTEST;\r
if not(self.stat_eaten || self.fakeprey)\r
self.alpha = default_player_alpha;\r
- else if(cvar("g_vore_neighborprey_distance") && !self.fakeprey && (self.predator == other.predator || self.predator == other.fakepredator) && !(other.cvar_chase_active || other.classname == "observer"))\r
+ else if(cvar("g_vore_neighborprey_distance") && !self.fakeprey && (self.predator == other.predator || self.predator == other.fakepredator) && !(chase || other.classname == "observer"))\r
+ {\r
self.alpha = default_player_alpha; // allow seeing neighboring prey\r
+ self.effects |= EF_NODEPTHTEST; // don't hide behind the stomach's own EF_NODEPTHTEST\r
+ }\r
else\r
self.alpha = -1; // hide prey\r
return TRUE;\r
\r
Vore_DeadPrey_Detach(self);\r
self.fakeprey = FALSE; // clear the fakeprey status\r
+ self.swallow_progress_pred = self.swallow_progress_prey = 0;\r
\r
self.classname = "player";\r
self.wasplayer = TRUE;\r
\r
if (cvar("g_spawnsound"))\r
sound (self, CHAN_TRIGGER, "misc/spawn.wav", VOL_BASE, ATTN_NORM);\r
+ pointparticles(particleeffectnum("player_respawn"), self.origin, '0 0 0', 1);\r
\r
if(g_assault) {\r
if(self.team == assault_attacker_team)\r
WriteString(MSG_ENTITY, world.fog);\r
else\r
WriteString(MSG_ENTITY, "");\r
- WriteCoord(MSG_ENTITY, cvar("g_campaign"));\r
+ WriteShort(MSG_ENTITY, cvar("g_campaign"));\r
WriteByte(MSG_ENTITY, cvar("g_balance_armor_blockpercent") * 255.0);\r
WriteByte(MSG_ENTITY, cvar("g_balance_weaponswitchdelay") * 255.0);\r
\r
- WriteCoord(MSG_ENTITY, cvar("g_vore"));\r
- WriteCoord(MSG_ENTITY, g_balance_vore_swallow_limit);\r
+ WriteShort(MSG_ENTITY, cvar("g_vore"));\r
+ WriteShort(MSG_ENTITY, cvar("g_healthsize"));\r
+ WriteShort(MSG_ENTITY, cvar("g_healthsize_min"));\r
+ WriteShort(MSG_ENTITY, cvar("g_healthsize_max"));\r
+\r
+ // tell the client if this server uses armor\r
+ float armor_max;\r
+ if(cvar("g_balance_armor_start") || (cvar("g_lms") && cvar("g_lms_start_armor")) /*|| (inWarmupStage && cvar("g_warmup_start_armor"))*/ || cvar("g_balance_armor_regen") || cvar("g_balance_armor_regenlinear"))\r
+ armor_max = cvar("g_balance_armor_limit");\r
+ WriteCoord(MSG_ENTITY, armor_max);\r
+\r
+ float teamheal_max;\r
+ if(cvar("g_vore") && cvar("g_vore_teamvore") && cvar("g_balance_vore_teamheal"))\r
+ teamheal_max = cvar("g_balance_vore_teamheal_stable");\r
+ WriteCoord(MSG_ENTITY, teamheal_max);\r
+\r
return TRUE;\r
}\r
\r
=============\r
*/\r
\r
+.float clientkill_nexttime;\r
void ClientKill_Now_TeamChange()\r
{\r
if(self.killindicator_teamchange == -1)\r
self.team = -1;\r
JoinBestTeam( self, FALSE, FALSE );\r
}\r
+ else if(self.killindicator_teamchange == -2)\r
+ {\r
+ if(g_ca)\r
+ self.caplayer = 0;\r
+ if(blockSpectators)\r
+ sprint(self, strcat("^7You have to become a player within the next ", ftos(cvar("g_maxplayers_spectator_blocktime")), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));\r
+ PutObserverInServer();\r
+ }\r
else\r
SV_ChangeTeam(self.killindicator_teamchange - 1);\r
}\r
\r
void ClientKill_Now()\r
-{\r
+{ \r
+ if(self.killindicator && !wasfreed(self.killindicator))\r
+ remove(self.killindicator);\r
+ \r
+ self.killindicator = world;\r
+\r
if(self.killindicator_teamchange)\r
ClientKill_Now_TeamChange();\r
\r
// in any case:\r
Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');\r
\r
- if(self.killindicator)\r
- {\r
- dprint("Cleaned up after a leaked kill indicator.\n");\r
- remove(self.killindicator);\r
- self.killindicator = world;\r
- }\r
+ // now I am sure the player IS dead\r
}\r
void KillIndicator_Think()\r
{\r
ClientKill_Now(); // no oldself needed\r
return;\r
}\r
+ else if(g_cts && self.health == 1) // health == 1 means that it's silent\r
+ {\r
+ self.nextthink = time + 1;\r
+ self.cnt -= 1;\r
+ }\r
else\r
{\r
if(self.cnt <= 10)\r
{\r
if(self.owner.killindicator_teamchange == -1)\r
centerprint(self.owner, strcat("Changing team in ", ftos(self.cnt), " seconds"));\r
+ else if(self.owner.killindicator_teamchange == -2)\r
+ centerprint(self.owner, strcat("Spectating in ", ftos(self.cnt), " seconds"));\r
else\r
centerprint(self.owner, strcat("Changing to ", ColoredTeamName(self.owner.killindicator_teamchange), " in ", ftos(self.cnt), " seconds"));\r
}\r
}\r
}\r
\r
-void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto\r
+void ClientKill_TeamChange (float targetteam) // 0 = don't change, -1 = auto, -2 = spec\r
{\r
float killtime;\r
entity e;\r
killtime = cvar("g_balance_kill_delay");\r
\r
- if(g_race_qualifying)\r
+ if(g_race_qualifying || g_cts)\r
killtime = 0;\r
\r
+ if(g_cts && self.killindicator && self.killindicator.health == 1) // self.killindicator.health == 1 means that the kill indicator was spawned by CTS_ClientKill\r
+ {\r
+ remove(self.killindicator);\r
+ self.killindicator = world;\r
+\r
+ ClientKill_Now(); // allow instant kill in this case\r
+ return;\r
+ }\r
+\r
self.killindicator_teamchange = targetteam;\r
\r
- if(!self.killindicator)\r
+ if(!self.killindicator)\r
{\r
+ if(self.modelindex && self.deadflag == DEAD_NO)\r
+ {\r
+ killtime = max(killtime, self.clientkill_nexttime - time);\r
+ self.clientkill_nexttime = time + killtime + cvar("g_balance_kill_antispam");\r
+ }\r
+\r
if(killtime <= 0 || !self.modelindex || self.deadflag != DEAD_NO)\r
{\r
ClientKill_Now();\r
self.killindicator.nextthink = time + (self.lip) * 0.05;\r
self.killindicator.cnt = ceil(killtime);\r
self.killindicator.count = bound(0, ceil(killtime), 10);\r
- sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n"));\r
+ //sprint(self, strcat("^1You'll be dead in ", ftos(self.killindicator.cnt), " seconds\n"));\r
\r
for(e = world; (e = find(e, classname, "body")) != world; )\r
{\r
}\r
if(self.killindicator)\r
{\r
- if(targetteam)\r
- self.killindicator.colormod = TeamColor(targetteam);\r
- else\r
+ if(targetteam == 0) // just die\r
self.killindicator.colormod = '0 0 0';\r
+ else if(targetteam == -1) // auto\r
+ self.killindicator.colormod = '0 1 0';\r
+ else if(targetteam == -2) // spectate\r
+ self.killindicator.colormod = '0.5 0.5 0.5';\r
+ else\r
+ self.killindicator.colormod = TeamColor(targetteam);\r
}\r
}\r
\r
void ClientKill (void)\r
{\r
- ClientKill_TeamChange(0);\r
+ if((g_arena || g_ca) && ((champion && champion.classname == "player" && player_count > 1) || player_count == 1)) // don't allow a kill in this case either\r
+ {\r
+ // do nothing\r
+ }\r
+ else\r
+ ClientKill_TeamChange(0);\r
+}\r
+\r
+void CTS_ClientKill (entity e) // silent version of ClientKill, used when player finishes a CTS run. Useful to prevent cheating by running back to the start line and starting out with more speed\r
+{\r
+ e.killindicator = spawn();\r
+ e.killindicator.owner = e;\r
+ e.killindicator.think = KillIndicator_Think;\r
+ e.killindicator.nextthink = time + (e.lip) * 0.05;\r
+ e.killindicator.cnt = ceil(cvar("g_cts_finish_kill_delay"));\r
+ e.killindicator.health = 1; // this is used to indicate that it should be silent\r
+ e.lip = 0;\r
}\r
\r
void DoTeamChange(float destteam)\r
{\r
float t, c0;\r
- if(!teams_matter)\r
+ if(!teamplay)\r
{\r
if(destteam >= 0)\r
SetPlayerColors(self, destteam);\r
ctf_clientconnect();\r
}*/\r
\r
- if(teams_matter || radar_showennemies)\r
- attach_entcs();\r
+ attach_entcs();\r
\r
bot_relinkplayerlist();\r
\r
=============\r
*/\r
.entity chatbubbleentity;\r
-.entity teambubbleentity;\r
void ReadyCount();\r
void ClientDisconnect (void)\r
{\r
if (self.chatbubbleentity)\r
remove (self.chatbubbleentity);\r
\r
- if (self.teambubbleentity)\r
- remove (self.teambubbleentity);\r
-\r
if (self.killindicator)\r
remove (self.killindicator);\r
\r
}\r
}\r
\r
-void TeamBubbleThink()\r
-{\r
- self.nextthink = time;\r
- if (!self.owner.modelindex || self.owner.teambubbleentity != self)\r
- {\r
- if(self.owner) // but why can that ever be world?\r
- self.owner.teambubbleentity = world;\r
- remove(self);\r
- return;\r
- }\r
-// setorigin(self, self.owner.origin + '0 0 15' + self.owner.maxs_z * '0 0 1'); // bandwidth hog. setattachment does this now\r
- if (self.owner.BUTTON_CHAT || self.owner.deadflag || self.owner.killindicator || self.owner.stat_eaten)\r
- self.model = "";\r
- else\r
- {\r
- if(cvar("g_balance_vore_teamheal") && cvar("g_vore_teamvore"))\r
- if(self.owner.health < cvar("g_balance_vore_teamheal_stable"))\r
- setmodel(self, "models/misc/teambubbleheal.spr"); // indicate that this player can be teamhealed\r
- else\r
- setmodel(self, "models/misc/teambubble.spr");\r
- }\r
-};\r
-\r
-float TeamBubble_customizeentityforclient()\r
-{\r
- return (self.owner != other && self.owner.team == other.team && other.killcount > -666);\r
-}\r
-\r
-void UpdateTeamBubble()\r
-{\r
- if (!self.modelindex || !teams_matter)\r
- return;\r
- // spawn a teambubble entity if needed\r
- if (!self.teambubbleentity && teams_matter)\r
- {\r
- self.teambubbleentity = spawn();\r
- self.teambubbleentity.owner = self;\r
- self.teambubbleentity.exteriormodeltoclient = self;\r
- self.teambubbleentity.think = TeamBubbleThink;\r
- self.teambubbleentity.nextthink = time;\r
- setmodel(self.teambubbleentity, "models/misc/teambubble.spr"); // precision set below\r
-// setorigin(self.teambubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');\r
- setorigin(self.teambubbleentity, '0 0 15' + self.maxs_z * '0 0 1');\r
- setattachment(self.teambubbleentity, self, ""); // sticks to moving player better, also conserves bandwidth\r
-// self.teambubbleentity.mdl = self.teambubbleentity.model;\r
-// self.teambubbleentity.model = self.teambubbleentity.mdl;\r
- self.teambubbleentity.customizeentityforclient = TeamBubble_customizeentityforclient;\r
- self.teambubbleentity.effects = EF_LOWPRECISION;\r
- }\r
-}\r
-\r
// LordHavoc: this hack will be removed when proper _pants/_shirt layers are\r
// added to the model skins\r
/*void UpdateColorModHack()\r
self.stomach_load = spectatee.stomach_load;\r
self.stat_eaten = spectatee.stat_eaten;\r
self.stat_stomachload = spectatee.stat_stomachload;\r
+ self.stomach_maxload = spectatee.stomach_maxload;\r
self.stat_digesting = spectatee.stat_digesting;\r
self.stat_canleave = spectatee.stat_canleave;\r
self.stat_canswallow = spectatee.stat_canswallow;\r
if(self.classname == "player") {\r
CheckRules_Player();\r
UpdateChatBubble();\r
- UpdateTeamBubble();\r
if (self.impulse)\r
ImpulseCommands();\r
if (intermission_running)\r