1 void info_player_start (void)
\r
3 if (self.allowteams != "")
\r
5 if (self.allowteams == "blue")
\r
7 if (self.allowteams == "red")
\r
9 if (!self.goal_state)
\r
10 self.goal_state = 1;
\r
18 self.classname = "info_player_deathmatch";
\r
22 void info_player_deathmatch (void)
\r
27 Find Team Spawn Point (NexTF!)
\r
30 entity (float team_num) FindTeamSpawnPoint =
\r
33 local entity at_spot;
\r
34 local float spot_found;
\r
35 local float attempts;
\r
37 if ((team_num == 1))
\r
39 spot = lastspawn_team1;
\r
43 attempts = (attempts + 1);
\r
44 spot = find (spot, team_str_home, "ts1");
\r
45 if ((spot == world))
\r
47 spot = find (world, team_str_home, "ts1");
\r
49 if ((spot == world))
\r
53 at_spot = findradius (spot.origin, 40);
\r
55 while ((at_spot != world))
\r
57 if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))
\r
61 at_spot = at_spot.chain;
\r
63 if (!Activated (spot, self))
\r
67 if ((spot_found || (attempts >= 30)))
\r
69 lastspawn_team1 = spot;
\r
76 if ((team_num == 2))
\r
78 spot = lastspawn_team2;
\r
82 attempts = (attempts + 1);
\r
83 spot = find (spot, team_str_home, "ts2");
\r
84 if ((spot == world))
\r
86 spot = find (world, team_str_home, "ts2");
\r
88 if ((spot == world))
\r
92 at_spot = findradius (spot.origin, 40);
\r
94 while ((at_spot != world))
\r
96 if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))
\r
100 at_spot = at_spot.chain;
\r
102 if (!Activated (spot, self))
\r
106 if ((spot_found || (attempts >= 30)))
\r
108 lastspawn_team2 = spot;
\r
115 if ((team_num == 3))
\r
117 spot = lastspawn_team3;
\r
121 attempts = (attempts + 1);
\r
122 spot = find (spot, team_str_home, "ts3");
\r
123 if ((spot == world))
\r
125 spot = find (world, team_str_home, "ts3");
\r
127 if ((spot == world))
\r
131 at_spot = findradius (spot.origin, 40);
\r
133 while ((at_spot != world))
\r
135 if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))
\r
139 at_spot = at_spot.chain;
\r
141 if (!Activated (spot, self))
\r
145 if ((spot_found || (attempts >= 30)))
\r
147 lastspawn_team3 = spot;
\r
154 if ((team_num == 4))
\r
156 spot = lastspawn_team4;
\r
160 attempts = (attempts + 1);
\r
161 spot = find (spot, team_str_home, "ts4");
\r
162 if ((spot == world))
\r
164 spot = find (world, team_str_home, "ts4");
\r
166 if ((spot == world))
\r
170 at_spot = findradius (spot.origin, 40);
\r
172 while ((at_spot != world))
\r
174 if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))
\r
178 at_spot = at_spot.chain;
\r
180 if (!Activated (spot, self))
\r
184 if ((spot_found || (attempts >= 30)))
\r
186 lastspawn_team4 = spot;
\r
201 Finds a point to respawn
\r
204 entity () SelectSpawnPoint =
\r
207 local entity at_spot;
\r
208 local float spot_found;
\r
209 local float attempts;
\r
211 if (self.team_no < 1)
\r
213 // self.origin_z = self.origin_z + 30;
\r
214 if (!cvar("g_teamnexuiz_version"))
\r
215 self.current_menu = MENU_NEED_TN;
\r
217 stuffcmd(self, "alias menu_showteamselect \"set scmenu_directmenu TeamSelect; togglemenu\"\n");
\r
218 stuffcmd(self, "set scmenu_directmenu TeamSelect; togglemenu\n");
\r
220 stuffcmd(self, "alias classmenu \"impulse 73\"\n");
\r
221 // spot = find (world, classname, "item_tfgoal");
\r
224 self.is_dead = 0; //TEMP
\r
226 if ((self.team_no != 0))
\r
228 spot = FindTeamSpawnPoint (self.team_no);
\r
229 if ((spot != world))
\r
236 lastspawn = find (lastspawn, classname, "info_player_coop");
\r
237 if ((lastspawn == world))
\r
239 lastspawn = find (world, classname, "info_player_coop");
\r
241 if ((lastspawn != world))
\r
243 return (lastspawn);
\r
250 spot = find (lastspawn, classname, "info_player_deathmatch");
\r
251 if ((spot == world))
\r
253 spot = find (world, classname, "info_player_deathmatch");
\r
256 while (((spot != world) && (attempts < 100)))
\r
258 attempts = (attempts + 1);
\r
259 at_spot = findradius (spot.origin, 40);
\r
263 if (((at_spot.classname == "player") && (at_spot.deadflag == 0)))
\r
267 at_spot = at_spot.chain;
\r
269 if ((spot_found || (attempts >= 10)))
\r
274 spot = find (spot, classname, "info_player_deathmatch");
\r
275 if ((spot == world))
\r
277 spot = find (world, classname, "info_player_deathmatch");
\r
284 spot = find (world, classname, "info_player_start2");
\r
290 spot = find (world, classname, "info_player_start");
\r
293 spot = find (world, is_converted_goal, "yes");
\r
295 spot = find(world, classname, "info_player_start");
\r
298 spot = find (world, classname, "info_player_intermission");
\r
302 // spot = find (world, classname, "info_tfgoal");
\r
306 error ("PutClientInServer: no info_player_start on level\n");
\r
311 /*entity SelectSpawnPoint (void) // Old, non-tf code
\r
313 local entity spot, thing;
\r
314 local float pcount;
\r
316 spot = find (world, classname, "testplayerstart");
\r
323 spot = find(spot, classname, "info_player_deathmatch");
\r
326 if (spot == lastspawn)
\r
329 thing = findradius(spot.origin, 70);
\r
332 if (thing.classname == "player")
\r
333 pcount = pcount + 1;
\r
334 thing = thing.chain;
\r
344 spot = find (world, classname, "info_player_start");
\r
346 error ("PutClientInServer: no info_player_start on level");
\r
355 Checks if the argument string can be a valid playermodel.
\r
356 Returns a valid one in doubt.
\r
359 string CheckPlayerModel(string playermodel) {
\r
360 if( substring(playermodel,0,13) != "models/class/") playermodel = "models/class/scout.zym";
\r
362 /* Possible Fixme: Check if server can open the model?
\r
363 This would kill custom models, however. */
\r
365 return playermodel;
\r
373 Called when a client spawns in the server
\r
376 void PutClientInServer (void)
\r
380 if (self.team_no < 1)
\r
384 self.flags = FL_CLIENT;
\r
385 self.takedamage = DAMAGE_AIM;
\r
387 self.health = cvar("g_balance_health_start");
\r
388 self.max_health = cvar("g_balance_health_stable");
\r
389 self.armorvalue = cvar("g_balance_armor_start");
\r
390 self.max_armor = self.armorvalue;
\r
391 self.damageforcescale = 2;
\r
392 self.death_time = 0;
\r
393 self.dead_time = 0;
\r
394 self.dead_frame = 0;
\r
395 self.die_frame = 0;
\r
398 self.fade_time = 0;
\r
399 self.pain_frame = 0;
\r
400 self.pain_finished = 0;
\r
401 self.strength_finished = 0;
\r
402 self.invincible_finished = 0;
\r
403 //self.speed_finished = 0;
\r
404 //self.slowmo_finished = 0;
\r
405 // players have no think function
\r
406 self.think = SUB_Null;
\r
407 self.nextthink = 0;
\r
410 spot = SelectSpawnPoint();
\r
411 // setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z + 24));
\r
412 // setorigin (self, spot.origin + '-2 0 4' * (1 - self.mins_z + 24));
\r
413 // self.angles_y = self.angles_y + 180;
\r
416 if (self.playerclass < 1)
\r
418 stuffcmd(self, "set scmenu_directmenu ClassSelect; togglemenu\n");
\r
422 // fixme: are these the right teams & colors?
\r
423 /*if(self.team == 5) // Wazat -- I'm using TeamFortress_TeamSet for this now
\r
427 if(self.team == 14)
\r
435 if(self.team == 13)
\r
442 // spot = SelectSpawnPoint (); // moved down
\r
443 self.classname = "player";
\r
444 self.movetype = MOVETYPE_WALK;
\r
445 self.solid = SOLID_SLIDEBOX;
\r
446 self.flags = FL_CLIENT;
\r
447 self.takedamage = DAMAGE_AIM;
\r
449 self.health = cvar("g_balance_health_start");
\r
450 self.max_health = cvar("g_balance_health_stable");
\r
451 self.armorvalue = cvar("g_balance_armor_start");
\r
452 self.max_armor = self.armorvalue;
\r
453 self.damageforcescale = 2;
\r
454 self.death_time = 0;
\r
455 self.dead_time = 0;
\r
456 self.dead_frame = 0;
\r
457 self.die_frame = 0;
\r
460 self.fade_time = 0;
\r
461 self.pain_frame = 0;
\r
462 self.pain_finished = 0;
\r
463 self.strength_finished = 0;
\r
464 self.invincible_finished = 0;
\r
465 //self.speed_finished = 0;
\r
466 //self.slowmo_finished = 0;
\r
467 // players have no think function
\r
468 self.think = SUB_Null;
\r
469 self.nextthink = 0;
\r
472 //self.wpn5 = 0; // not carrying an extra weapon
\r
473 ResetExtraWeapon(); // not carrying an extra weapon
\r
475 DelayHealthRegen(self);
\r
476 DelayArmorRegen(self);
\r
477 DelayHealthRot(self);
\r
478 DelayArmorRot(self);
\r
481 self.special_active = 0;
\r
482 self.special_time = 0;
\r
484 self.grenade_time = 0;
\r
486 if(self.onfire != world)
\r
487 remove(self.onfire);
\r
488 self.onfire = world;
\r
489 self.flame_heat = 0;
\r
490 self.flame_heat_time = 0;
\r
492 self.poison_damage = 0;
\r
493 self.poison_rate = 0;
\r
495 self.is_feigning = 0;
\r
496 self.current_menu = 0;
\r
498 // if the player is supposed to change model (and hence class) on respawn, do it.
\r
499 if(self.change_mdl_on_respawn != "")
\r
501 self.playermodel = self.change_mdl_on_respawn;
\r
502 //strunzone(self.change_mdl_on_respawn); // can't unzone or it'll crash later
\r
504 // set the class. If he changed classes while dead it will take effect now.
\r
505 oldcl = self.class;
\r
506 self.class = GetPlayerClass();
\r
507 Do_TFClass_Conversion();
\r
508 ChangeClass((oldcl != self.class), FALSE);
\r
512 self.deadflag = DEAD_NO;
\r
514 spot = SelectSpawnPoint (); // maybe temp
\r
515 self.angles = spot.angles;
\r
516 self.fixangle = TRUE; // turn this way immediately
\r
517 self.velocity = '0 0 0';
\r
518 self.avelocity = '0 0 0';
\r
519 self.punchangle = '0 0 0';
\r
520 self.punchvector = '0 0 0';
\r
522 self.viewzoom = 0.6;
\r
525 self.playermodel = CheckPlayerModel(self.playermodel);
\r
527 precache_model (self.playermodel);
\r
528 setmodel (self, self.playermodel);
\r
529 self.skin = stof(self.playerskin);
\r
530 self.mdl = strzone(self.playermodel);
\r
532 self.crouch = FALSE;
\r
533 self.view_ofs = PL_VIEW_OFS;
\r
534 setsize (self, PL_MIN, PL_MAX);
\r
535 setorigin (self, spot.origin + '0 0 1' * (1 - self.mins_z - 24));
\r
536 // don't reset back to last position, even if new position is stuck in solid
\r
537 self.oldorigin = self.origin;
\r
539 // self.items = IT_LASER | IT_UZI| IT_SHOTGUN | IT_GRENADE_LAUNCHER | IT_ELECTRO | IT_CRYLINK | IT_NEX | IT_HAGAR | IT_ROCKET_LAUNCHER;
\r
540 // self.weapon = IT_UZI;
\r
543 // fixme: move this to Become<Class> code
\r
544 /* self.items = IT_WEP1 | IT_WEP2 | IT_WEP3 | IT_WEP4;
\r
546 self.switchweapon = IT_WEP2;
\r
547 self.ammo_shells = 50;
\r
548 self.ammo_nails = 0;
\r
549 self.ammo_rockets = 0;
\r
550 self.ammo_cells = 0;*/
\r
552 if (cvar("g_fullbrightplayers") == 1)
\r
553 self.effects = EF_FULLBRIGHT;
\r
555 self.event_damage = PlayerDamage;
\r
557 self.statdraintime = time + 5;
\r
558 self.button0 = self.button1 = self.button2 = self.button3 = 0;
\r
564 CL_SpawnWeaponentity();
\r
565 self.weaponentity.alpha = self.exteriorweaponentity.alpha = 0;
\r
566 self.weaponentity.colormod = '0 0 0';
\r
567 self.weaponentity.scale = 0;
\r
569 //stuffcmd(self, "chase_active 0");
\r
577 void SetNewParms (void)
\r
587 void SetChangeParms (void)
\r
596 Called when a client types 'kill' in the console
\r
599 void ClientKill (void)
\r
601 Damage(self, self, self, 100000, DEATH_KILL, self.origin, '0 0 0');
\r
608 Called when a client connects to the server
\r
611 void ClientConnect (void)
\r
613 //ClientInRankings();
\r
614 bprint ("^4",self.netname);
\r
615 bprint (" connected\n");
\r
616 stuffcmd(self, strcat("exec maps/", mapname, ".cfg\n"));
\r
617 // send prediction settings to the client
\r
618 stuffcmd(self, strcat("cl_movement_maxspeed ", ftos(cvar("sv_maxspeed")), "\n"));
\r
619 stuffcmd(self, strcat("cl_movement_maxairspeed ", ftos(cvar("sv_maxairspeed")), "\n"));
\r
620 stuffcmd(self, strcat("cl_movement_accelerate ", ftos(cvar("sv_accelerate")), "\n"));
\r
621 stuffcmd(self, strcat("cl_movement_friction ", ftos(cvar("sv_friction")), "\n"));
\r
622 stuffcmd(self, strcat("cl_movement_stopspeed ", ftos(cvar("sv_stopspeed")), "\n"));
\r
623 stuffcmd(self, strcat("cl_movement_jumpvelocity ", ftos(cvar("g_balance_jumpheight")), "\n"));
\r
624 stuffcmd(self, strcat("cl_movement_stepheight ", ftos(cvar("sv_stepheight")), "\n"));
\r
625 stuffcmd(self, strcat("cl_movement_edgefriction 0\n"));
\r
626 // TEMP FOR TESTING PURPOSES!
\r
627 //teamplay = 21?TeamFortress;
\r
628 DecodeLevelParms ();
\r
629 //cvar_set ("teamplay", "21?TeamFortress");
\r
630 // teamplay = cvar ("teamplay");
\r
632 /* joinorder = joinorder + 1; // old temp autoteam, but now we have a menu instead :P
\r
633 if (joinorder == 1 || joinorder == 3 || joinorder == 5 || joinorder == 7)
\r
634 TeamFortress_TeamSet (1);
\r
636 TeamFortress_TeamSet (2);
\r
644 Called when a client disconnects from the server
\r
647 .entity chatbubbleentity;
\r
648 void ClientDisconnect (void)
\r
650 //ClientDisconnected();
\r
651 self.has_disconnected = 1;
\r
652 bprint ("^4",self.netname);
\r
653 bprint (" disconnected\n");
\r
655 if (self.chatbubbleentity)
\r
657 remove (self.chatbubbleentity);
\r
658 self.chatbubbleentity = world;
\r
661 if (self.teambubble_friendly)
\r
663 remove (self.teambubble_friendly);
\r
664 self.teambubble_friendly = world;
\r
666 if (self.teambubble_needhealth)
\r
668 remove (self.teambubble_needhealth);
\r
669 self.teambubble_needhealth = world;
\r
673 .entity chatbubbleentity;
\r
675 void() ChatBubbleThink =
\r
677 self.nextthink = time;
\r
678 if (!self.owner.modelindex || self.owner.chatbubbleentity != self)
\r
683 setorigin(self, self.owner.origin + '0 0 15' + self.owner.maxs_z * '0 0 1');
\r
684 if (self.owner.buttonchat)
\r
687 self.effects = EF_NODRAW;
\r
690 void() UpdateChatBubble =
\r
692 if (!self.modelindex)
\r
694 // spawn a chatbubble entity if needed
\r
695 if (!self.chatbubbleentity)
\r
697 self.chatbubbleentity = spawn();
\r
698 self.chatbubbleentity.owner = self;
\r
699 self.chatbubbleentity.think = ChatBubbleThink;
\r
700 self.chatbubbleentity.nextthink = time;
\r
701 setmodel(self.chatbubbleentity, "models/misc/chatbubble.spr");
\r
702 setorigin(self.chatbubbleentity, self.origin + '0 0 15' + self.maxs_z * '0 0 1');
\r
703 self.chatbubbleentity.effects = EF_NODRAW;
\r
707 // LordHavoc: this hack will be removed when proper _pants/_shirt layers are
\r
708 // added to the model skins
\r
709 void() UpdateColorModHack =
\r
712 c = self.clientcolors & 15;
\r
713 // LordHavoc: only bothering to support white, green, red, yellow, blue
\r
714 if (teamplay == 0) self.colormod = '0 0 0';
\r
715 else if (c == 0) self.colormod = '1.00 1.00 1.00';
\r
716 else if (c == 3) self.colormod = '0.10 1.73 0.10';
\r
717 else if (c == 4) self.colormod = '1.73 0.10 0.10';
\r
718 else if (c == 12) self.colormod = '1.22 1.22 0.10';
\r
719 else if (c == 13) self.colormod = '0.10 0.10 1.73';
\r
720 else self.colormod = '1 1 1';
\r
727 When you press the jump key
\r
730 void PlayerJump (void)
\r
732 if (self.waterlevel >= 2)
\r
734 if (self.watertype == CONTENT_WATER)
\r
735 self.velocity_z = 200;
\r
736 else if (self.watertype == CONTENT_SLIME)
\r
737 self.velocity_z = 80;
\r
739 self.velocity_z = 50;
\r
746 // self.jump_pad = 0;
\r
747 CapPlayerVelocity(self, self.speed);
\r
750 if (!(self.flags & FL_ONGROUND))
\r
753 if (!(self.flags & FL_JUMPRELEASED))
\r
756 self.velocity_z = self.velocity_z + cvar("g_balance_jumpheight");
\r
758 self.flags = self.flags - FL_ONGROUND;
\r
759 self.flags = self.flags - FL_JUMPRELEASED;
\r
762 .float watersound_finished;
\r
765 if (self.movetype == MOVETYPE_NOCLIP)
\r
767 if (self.health < 0)
\r
770 if (self.waterlevel != 3)
\r
772 self.air_finished = time + 12;
\r
775 else if (self.air_finished < time)
\r
777 if (self.pain_finished < time)
\r
779 Damage (self, world, world, 5, DEATH_DROWN, self.origin, '0 0 0');
\r
780 self.pain_finished = time + 0.5;
\r
784 if (!self.waterlevel)
\r
786 if (self.flags & FL_INWATER)
\r
788 // play leave water sound
\r
789 self.flags = self.flags - FL_INWATER;
\r
794 if (self.watersound_finished < time)
\r
796 self.watersound_finished = time + 0.5;
\r
797 if (self.watertype == CONTENT_LAVA)
\r
798 sound (self, CHAN_BODY, "player/lava.wav", 1, ATTN_NORM);
\r
799 if (self.watertype == CONTENT_SLIME)
\r
800 sound (self, CHAN_BODY, "player/slime.wav", 1, ATTN_NORM);
\r
801 //if (self.watertype == CONTENT_WATER)
\r
802 // sound (self, CHAN_BODY, "player/water.wav", 1, ATTN_NORM);
\r
805 if (self.watertype == CONTENT_LAVA)
\r
808 // lava sets me to the maximum heat level, so I'll catch fire easily
\r
809 self.flame_heat = cvar("g_balance_maxheat");
\r
811 if (self.dmgtime < time)
\r
813 self.dmgtime = time + 0.1;
\r
814 Damage (self, world, world, 3 * self.waterlevel, DEATH_LAVA, self.origin, '0 0 0');
\r
817 else if (self.watertype == CONTENT_SLIME)
\r
821 self.flame_heat = 0;
\r
823 if (self.dmgtime < time)
\r
825 self.dmgtime = time + 0.1;
\r
826 Damage (self, world, world, 1 * self.waterlevel, DEATH_SLIME, self.origin, '0 0 0');
\r
829 else if (self.watertype == CONTENT_WATER)
\r
832 self.flame_heat = 0;
\r
835 if ( !(self.flags & FL_INWATER) )
\r
838 //if (self.watertype == CONTENT_LAVA)
\r
839 // sound (self, CHAN_BODY, "player/inlava.wav", 1, ATTN_NORM);
\r
840 //if (self.watertype == CONTENT_WATER)
\r
841 // sound (self, CHAN_BODY, "player/inh2o.wav", 1, ATTN_NORM);
\r
842 //if (self.watertype == CONTENT_SLIME)
\r
843 // sound (self, CHAN_BODY, "player/slimbrn2.wav", 1, ATTN_NORM);
\r
845 self.flags = self.flags + FL_INWATER;
\r
850 void() CheckWaterJump =
\r
852 local vector start, end;
\r
854 // check for a jump-out-of-water
\r
855 makevectors (self.angles);
\r
856 start = self.origin;
\r
857 start_z = start_z + 8;
\r
859 normalize(v_forward);
\r
860 end = start + v_forward*24;
\r
861 traceline (start, end, TRUE, self);
\r
862 if (trace_fraction < 1)
\r
863 { // solid at waist
\r
864 start_z = start_z + self.maxs_z - 8;
\r
865 end = start + v_forward*24;
\r
866 self.movedir = trace_plane_normal * -50;
\r
867 traceline (start, end, TRUE, self);
\r
868 if (trace_fraction == 1)
\r
869 { // open at eye level
\r
870 self.flags = self.flags | FL_WATERJUMP;
\r
871 self.velocity_z = 225;
\r
872 self.flags = self.flags - (self.flags & FL_JUMPRELEASED);
\r
873 self.teleport_time = time + 2; // safety net
\r
883 PutClientInServer();
\r
886 void player_powerups (void)
\r
888 self.effects = self.effects - (self.effects & (EF_RED | EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT));
\r
889 if (self.items & IT_STRENGTH)
\r
891 self.effects = self.effects | (EF_BLUE | EF_ADDITIVE | EF_FULLBRIGHT);
\r
892 if (time > self.strength_finished)
\r
894 self.items = self.items - (self.items & IT_STRENGTH);
\r
895 sprint(self, "^3Strength has worn off\n");
\r
900 if (time < self.strength_finished)
\r
902 self.items = self.items | IT_STRENGTH;
\r
903 sprint(self, "^3Strength infuses your weapons with devestating power\n");
\r
906 if (self.items & IT_INVINCIBLE)
\r
908 self.effects = self.effects | (EF_RED | EF_ADDITIVE | EF_FULLBRIGHT);
\r
909 if (time > self.invincible_finished)
\r
911 self.items = self.items - (self.items & IT_INVINCIBLE);
\r
912 sprint(self, "^3Shield has worn off\n");
\r
917 if (time < self.invincible_finished)
\r
919 self.items = self.items | IT_INVINCIBLE;
\r
920 sprint(self, "^3Shield surrounds you\n");
\r
925 void player_regen_health (float maxh, float regen_rate_mod)
\r
927 if (self.health < maxh && time > self.health_regen_delay && self.health > 2) // dont regen is HP is 2
\r
928 self.health = bound(0, self.health + regen_rate_mod*(maxh- self.health) * cvar("g_balance_health_regen") * frametime, 1000);
\r
930 void player_rot_health (float maxh, float rot_rate_mod)
\r
932 if (self.health > maxh && time > self.health_rot_delay)
\r
933 self.health = bound(0, self.health + rot_rate_mod*(maxh - self.health) * cvar("g_balance_health_rot") * frametime, 1000);
\r
935 void player_regen_armor (float maxa, float regen_rate_mod)
\r
937 if (self.armorvalue < maxa && time > self.armor_regen_delay)
\r
938 self.armorvalue = bound(0, self.armorvalue + regen_rate_mod*(maxa - self.armorvalue) * cvar("g_balance_armor_regen") * frametime, 1000);
\r
940 void player_rot_armor (float maxa, float regen_rot_mod)
\r
942 if (self.armorvalue > maxa && time > self.armor_rot_delay)
\r
943 self.armorvalue = bound(0, self.armorvalue + regen_rot_mod*(maxa - self.armorvalue) * cvar("g_balance_armor_rot") * frametime, 1000);
\r
946 void player_clearpoison(entity targ)
\r
948 targ.poison_damage = targ.poison_rate = 0;
\r
951 void DelayHealthRegen(entity e) { e.health_regen_delay = time + cvar("g_balance_regen_wait");}
\r
952 void DelayHealthRot(entity e) { e.health_rot_delay = time + cvar("g_balance_rot_wait");}
\r
953 void DelayArmorRegen(entity e) { e.armor_regen_delay = time + cvar("g_balance_regen_wait");}
\r
954 void DelayArmorRot(entity e) { e.armor_rot_delay = time + cvar("g_balance_rot_wait");}
\r
957 void player_takepoison()
\r
959 float oldhealth, take;
\r
960 if(self.health <= 5)
\r
962 player_clearpoison(self);
\r
965 oldhealth = self.health;
\r
967 take = bound(0, self.poison_rate * frametime, self.health - 5);
\r
970 player_clearpoison(self);
\r
974 DelayHealthRegen(self);
\r
975 self.health = self.health - take;
\r
976 self.poison_damage = self.poison_damage - take;
\r
978 if(self.health <= 5 || self.poison_damage <= 0)
\r
980 player_clearpoison(self);
\r
985 // cool off so you're not so vulnerable to fire
\r
986 void player_cooloff ()
\r
988 if(self.flame_heat_time > time)//heat up
\r
989 self.flame_heat = bound(0, self.flame_heat + self.flame_heat * cvar("g_balance_heatup_rate") * frametime, cvar("g_balance_maxheat"));
\r
991 self.flame_heat = bound(0, self.flame_heat - self.flame_heat * cvar("g_balance_cooloff_rate") * frametime, cvar("g_balance_maxheat"));
\r
994 void player_regen (void)
\r
998 maxh = self.max_health;//cvar("g_balance_health_stable");
\r
999 maxa = self.max_armor;//cvar("g_balance_armor_stable");
\r
1001 if(self.poison_damage)
\r
1003 player_takepoison();
\r
1007 if(self.class == CLASS_SPY)
\r
1008 {// don't let spy regenerate if cloaked, but do allow rot if above max
\r
1009 if(self.special_active)
\r
1011 //if(self.health > maxh)
\r
1012 player_rot_health(maxh, 1.0);
\r
1013 //if(self.armorvalue > maxa)
\r
1014 player_rot_armor(maxa, 1.0);
\r
1018 player_regen_health(maxh, 0.1); // spies regenerate slowly, and mostly rely on health packs
\r
1019 player_regen_armor(maxa, 1.0);
\r
1020 player_rot_health(maxh, 1.0);
\r
1021 player_rot_armor(maxa, 1.0);
\r
1026 player_regen_health(maxh, 1.0);
\r
1027 player_regen_armor(maxa, 1.0);
\r
1028 player_rot_health(maxh, 1.0);
\r
1029 player_rot_armor(maxa, 1.0);
\r
1039 Called every frame for each client before the physics are run
\r
1042 .float attack_finished;
\r
1043 void PlayerPreThink (void)
\r
1045 local vector m1, m2;
\r
1047 CheckRules_Player();
\r
1049 if (intermission_running)
\r
1051 IntermissionThink (); // otherwise a button could be missed between
\r
1052 return; // the think tics
\r
1055 if (self.deadflag != DEAD_NO)
\r
1059 if (self.deadflag == DEAD_DYING)
\r
1061 if (time > self.dead_time)
\r
1062 self.deadflag = DEAD_DEAD;
\r
1064 else if (self.deadflag == DEAD_DEAD)
\r
1066 if (!self.button0 && !self.button2 && !self.button3)
\r
1067 self.deadflag = DEAD_RESPAWNABLE;
\r
1069 else if (self.deadflag == DEAD_RESPAWNABLE)
\r
1071 if (self.button0 || self.button2 || self.button3 || self.button4)
\r
1081 self.crouch = TRUE;
\r
1082 self.view_ofs = PL_CROUCH_VIEW_OFS;
\r
1083 setsize (self, PL_CROUCH_MIN, PL_CROUCH_MAX);
\r
1090 tracebox(self.origin, PL_MIN, PL_MAX, self.origin, FALSE, self);
\r
1091 if (!trace_startsolid)
\r
1093 self.crouch = FALSE;
\r
1094 self.view_ofs = PL_VIEW_OFS;
\r
1095 setsize (self, PL_MIN, PL_MAX);
\r
1100 if (self.playermodel != self.mdl)
\r
1102 //bprint("playermodel changed\n");
\r
1103 self.playermodel = CheckPlayerModel(self.playermodel);
\r
1104 if(CheckForClassChange()) // check if we'll allow it
\r
1105 return; // if there's a return value, drop what you're doing and let the player respawn
\r
1107 if(self.playermodel != self.mdl) // if change has been allowed
\r
1111 precache_model (self.playermodel);
\r
1112 if(self.model != "")
\r
1114 setmodel (self, self.playermodel);
\r
1115 setsize (self, m1, m2);
\r
1117 self.mdl = strzone(self.playermodel);
\r
1123 if (self.skin != stof(self.playerskin))
\r
1124 self.skin = stof(self.playerskin);
\r
1126 if(self.class == CLASS_SCOUT)
\r
1127 GrapplingHookFrame();
\r
1131 if (self.button4 || (self.weapon == WEP_NEX && self.button3))
\r
1133 if (self.viewzoom > 0.4)
\r
1134 self.viewzoom = max (0.4, self.viewzoom - frametime * 2);
\r
1136 else if (self.viewzoom < 1.0)
\r
1137 self.viewzoom = min (1.0, self.viewzoom + frametime);
\r
1143 self.flags = self.flags | FL_JUMPRELEASED;
\r
1146 player_powerups();
\r
1150 //self.angles_y=self.v_angle_y + 90; // temp
\r
1153 if (self.waterlevel == 2)
\r
1154 CheckWaterJump ();
\r
1156 //if (TetrisPreFrame()) return;
\r
1158 PlayerLasergatePreThink();
\r
1161 // Update weapon colors
\r
1162 void UpdatePlayerColors () {
\r
1163 if(self.weaponentity) {
\r
1164 self.weaponentity.colormap = self.colormap;
\r
1165 self.exteriorweaponentity.colormap = self.colormap;
\r
1173 Called every frame for each client after the physics are run
\r
1176 void PlayerPostThink (void)
\r
1178 float soundrandom;
\r
1179 CheckRules_Player();
\r
1180 UpdateChatBubble();
\r
1181 UpdateColorModHack();
\r
1182 UpdateTeamBubble();
\r
1183 UpdatePlayerColors();
\r
1184 if (self.deadflag == DEAD_NO)
\r
1186 ImpulseCommands ();
\r
1187 if (intermission_running)
\r
1188 return; // intermission or finale
\r
1190 // VorteX: landing on floor, landing damage etc.
\r
1191 // LordHavoc: removed 'big fall' death code that VorteX added
\r
1192 if (self.flags & FL_ONGROUND || (self.waterlevel >= 2 && self.velocity_z <= 0))
\r
1193 self.jump_pad = 0;
\r
1195 if (self.flags & FL_ONGROUND)
\r
1197 CapPlayerVelocity(self, self.speed);
\r
1199 if (self.jump_flag < -100 && !self.watertype == CONTENT_WATER) // HitGround
\r
1201 soundrandom = random() * 4;
\r
1203 self.air_time = time; //temp BH var
\r
1205 if (soundrandom < 1)
\r
1206 sound (self, CHAN_BODY, "misc/hitground1.wav", 1, ATTN_NORM);
\r
1207 else if (soundrandom < 2)
\r
1208 sound (self, CHAN_BODY, "misc/hitground2.wav", 1, ATTN_NORM);
\r
1209 else if (soundrandom < 3)
\r
1210 sound (self, CHAN_BODY, "misc/hitground3.wav", 1, ATTN_NORM);
\r
1211 else if (soundrandom < 4)
\r
1212 sound (self, CHAN_BODY, "misc/hitground4.wav", 1, ATTN_NORM);
\r
1213 if (self.jump_flag < -650) // landing damage
\r
1216 dm = bound(0, 0.1*(fabs(self.jump_flag) - 600), 5);
\r
1217 Damage (self, world, world, dm, DEATH_FALL, self.origin, '0 0 0');
\r
1219 self.jump_flag = 0;
\r
1223 self.jump_flag = self.velocity_z;
\r
1227 //if (TetrisPostFrame()) return;
\r
1228 PlayerLasergatePostThink();
\r
1231 // Parse team join, class etc.
\r
1232 void SV_ParseClientCommand (string s)
\r
1241 args = tokenize(s);
\r
1252 if (c == "changeclass")
\r
1254 stuffcmd(self, "set scmenu_directmenu ClassSelect; togglemenu\n");
\r
1257 if (c == "selectteam")
\r
1259 if (self.team_no > 0)
\r
1261 sprint(self, "You are already on a team!\n");
\r
1264 if (d == "auto" || d == "5")
\r
1266 TeamFortress_TeamPutPlayerInTeam();
\r
1267 PutClientInServer ();
\r
1269 if (d == "blue" || d == "1")
\r
1271 TeamFortress_TeamSet (1);
\r
1272 PutClientInServer ();
\r
1274 if (d == "red" || d == "2")
\r
1276 TeamFortress_TeamSet (2);
\r
1277 PutClientInServer ();
\r
1279 if (d == "yellow" || d == "3")
\r
1281 TeamFortress_TeamSet (3);
\r
1282 PutClientInServer ();
\r
1284 if (d == "green" || d == "pink" || d == "4") // Morphed set it to Pink in the menus. I think
\r
1285 { // we should make it white instead.
\r
1286 TeamFortress_TeamSet (4);
\r
1287 PutClientInServer ();
\r
1291 if (c == "selectclass")
\r
1293 if (self.team_no < 1)
\r
1295 sprint(self, "You must select a team to join first!\n");
\r
1298 if (TeamFortress_TeamIsCivilian (self.team_no))
\r
1301 TeamFortress_ChangeClass ();
\r
1304 if (self.playerclass > 0) // if a class is already chosen
\r
1306 self.tfstate = self.tfstate - (self.tfstate & 8);
\r
1307 local string cname;
\r
1308 if (d == ftos(TF_CLASS_SCOUT))
\r
1312 if (d == ftos(TF_CLASS_SOLDIER))
\r
1314 cname = "soldier";
\r
1316 if (d == ftos(TF_CLASS_MEDIC))
\r
1320 if (d == ftos(TF_CLASS_PYRO))
\r
1324 if (d == ftos(TF_CLASS_ENGINEER))
\r
1326 cname = "engineer";
\r
1328 if (d == ftos(TF_CLASS_SPY))
\r
1332 if (d == ftos(TF_CLASS_RANDOM))
\r
1334 self.tfstate = self.tfstate | 8;
\r
1335 sprint(self, "You will respawn as a random class.\n");
\r
1339 // stuffcmd(self, "_cl_playermodel \"models/class/");
\r
1340 // stuffcmd(self, cname);
\r
1341 // stuffcmd(self, "_mechanical.zym\"\n");
\r
1342 if (cname == "engineer")
\r
1344 self.playermodel = strcat("models/class/",cname,"_other.zym");
\r
1348 self.playermodel = strcat("models/class/",cname,"_mechanical.zym");
\r
1350 if (self.is_dead == 1) // if player is dead, can change class
\r
1351 CheckForClassChange();
\r
1354 else // if no class is chosen
\r
1356 if (d == ftos(TF_CLASS_SCOUT))
\r
1358 self.impulse = TF_CLASS_SCOUT;
\r
1360 if (d == ftos(TF_CLASS_SOLDIER))
\r
1362 self.impulse = TF_CLASS_SOLDIER;
\r
1364 if (d == ftos(TF_CLASS_MEDIC))
\r
1366 self.impulse = TF_CLASS_MEDIC;
\r
1368 if (d == ftos(TF_CLASS_PYRO))
\r
1370 self.impulse = TF_CLASS_PYRO;
\r
1372 if (d == ftos(TF_CLASS_ENGINEER))
\r
1374 self.impulse = TF_CLASS_ENGINEER;
\r
1376 if (d == ftos(TF_CLASS_SPY))
\r
1378 self.impulse = TF_CLASS_SPY;
\r
1380 if (d == ftos(TF_CLASS_RANDOM))
\r
1382 self.impulse = TF_CLASS_RANDOM;
\r
1384 TeamFortress_ChangeClass();
\r
1388 else if (c == "check_val")
\r
1390 if (d == "r_bloom")
\r
1393 self.uses_bloom = 1;
\r
1395 self.uses_bloom = 0;
\r
1400 clientcommand(self, s);
\r