entity ent;
for(ent = world; (ent = nextent(ent)); )
{
- if(clienttype(ent) == CLIENTTYPE_NOTACLIENT)
+ if(IS_NOT_A_CLIENT(ent))
{
- if(ent.team_saved == COLOR_TEAM1)
- ent.team_saved = COLOR_TEAM2;
- else if(ent.team_saved == COLOR_TEAM2)
- ent.team_saved = COLOR_TEAM1;
+ if(ent.team_saved == NUM_TEAM_1)
+ ent.team_saved = NUM_TEAM_2;
+ else if(ent.team_saved == NUM_TEAM_2)
+ ent.team_saved = NUM_TEAM_1;
}
}
--- /dev/null
- if(self.owner.classname != "player" || time < game_starttime)
+ float rune_numspawns;
+
+ float RUNE_FIRST = 1;
+ float RUNE_STRENGTH = 1;
+ float RUNE_DEFENSE = 2;
+ float RUNE_REGEN = 4;
+ float RUNE_SPEED = 8;
+ float RUNE_VAMPIRE = 16;
+ float RUNE_LAST = 16;
+
+ float CURSE_FIRST = 8192;
+ float CURSE_WEAK = 8192;
+ float CURSE_VULNER = 16384;
+ float CURSE_VENOM = 32768;
+ float CURSE_SLOW = 65536;
+ float CURSE_EMPATHY = 131072;
+ float CURSE_LAST = 131072;
+
+ float RUNE_COUNT = 5;
+
+ /* rune ideas:
+
+ Doom/Death
+ Rune: When you damage enemies, you have a slight chance of instant-killing them (porportional to damage dealt / their health)
+ Curse: When you are damaged, you have a chance of being instant-killed
+
+ Vengence/Slothful
+ Rune: The lower your health below 100, the more damage you deal (does not decrease your damage if you're above 100)
+ Curse: The higher your health (up to 100), the less damage you deal (at 100 hp deal 1/5th damage)
+
+ */
+
+ /*QUAKED spawnfunc_runematch_spawn_point (1 0 0) (-16 -16 -24) (16 16 24)
+ spawn point for runes in runematch
+ */
+
+ void spawnfunc_runematch_spawn_point()
+ {
+ if(!g_runematch || !autocvar_g_runematch_fixedspawns)
+ {
+ remove(self);
+ return;
+ }
+
+ setsize(self, '0 0 -35', '0 0 0');
+ droptofloor();
+ ++rune_numspawns;
+ }
+
+ // only used if using rune spawns at all
+ entity rune_find_spawnpoint()
+ {
+ entity e;
+
+ if(rune_numspawns < RUNE_COUNT)
+ return world;
+
+ RandomSelection_Init();
+
+ for(e = world; (e = find(e, classname, "runematch_spawn_point")); )
+ if(e.owner == world)
+ RandomSelection_Add(e, 0, string_null, e.cnt, 0);
+
+ return RandomSelection_chosen_ent;
+ }
+
+ float rune_spawn_somewhere(entity e)
+ {
+ entity spot;
+ spot = rune_find_spawnpoint();
+ if(spot)
+ {
+ spot.owner = e;
+ setorigin(e, spot.origin);
+
+ e.owner = spot;
+ spot.owner = e;
+
+ return TRUE;
+ }
+ else
+ {
+ if(MoveToRandomMapLocation(e, DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP, DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER, Q3SURFACEFLAG_SKY, 10, 1024, 256))
+ {
+ // great
+ makevectors(self.angles),
+ self.velocity = v_forward * 250;
+ self.angles = '0 0 0';
+ return TRUE;
+ }
+ else
+ {
+ // sorry, can't spawn, better luck next frame
+ return FALSE;
+ }
+ }
+ }
+
+ void rune_unmark_spot(entity e)
+ {
+ if(e.owner.classname == "runematch_spawn_point")
+ {
+ e.owner.owner = world;
+ e.owner = world;
+ }
+ }
+
+ string RuneName(float r)
+ {
+ if(r == RUNE_STRENGTH)
+ return "^1Strength^7";
+ if(r == RUNE_DEFENSE)
+ return "^4Defense^7";
+ if(r == RUNE_REGEN)
+ return "^2Vitality^7";
+ if(r == RUNE_SPEED)
+ return "^3Speed^7";
+ if(r == RUNE_VAMPIRE)
+ return "^6Vampire^7";
+
+ if(r == CURSE_WEAK)
+ return "^1Weakness^7";
+ if(r == CURSE_VULNER)
+ return "^4Vulnerability^7";
+ if(r == CURSE_VENOM)
+ return "^2Venom^7";
+ if(r == CURSE_SLOW)
+ return "^3Slow^7";
+ if(r == CURSE_EMPATHY)
+ return "^6Empathy^7";
+ return strcat("^8[unnamed", ftos(r), "]^7");
+ }
+
+ vector RuneColormod(float r)
+ {
+ vector _color = '255 0 255';
+
+ if(r == RUNE_STRENGTH)
+ _color = '255 0 0';
+ if(r == RUNE_DEFENSE)
+ _color = '0 0 255';//'0 102 255';//
+ if(r == RUNE_REGEN)
+ _color = '0 204 0';//'0 255 0';
+ if(r == RUNE_SPEED)
+ _color = 0.35*'185 185 0';//255 230 0';//'255 255 0';
+ if(r == RUNE_VAMPIRE)
+ _color = '64 0 128';//'108 0 217';//'128 0 255';//'179 0 204';//
+
+ if(r == CURSE_WEAK)
+ _color = '255 0 0';
+ if(r == CURSE_VULNER)
+ _color = '0 0 255';//'0 102 255';//
+ if(r == CURSE_VENOM)
+ _color = '0 204 0';//'0 255 0';
+ if(r == CURSE_SLOW)
+ _color = 0.5*'185 185 0';//'255 255 0';
+ if(r == CURSE_EMPATHY)
+ _color = '179 0 204';//'128 0 255';
+
+ return _color * (1 / 255) * autocvar_g_runematch_rune_color_strength;
+ }
+
+ void rune_respawn();
+
+ void RuneCarriedThink()
+ {
+ float rcount, rnum;
+ vector ang = '0 0 0';
+ entity rune;
+
- if(other.classname != "player" || other.health < 1)
++ if(!IS_PLAYER(self.owner) || time < game_starttime)
+ {
+ rune_respawn();
+ return;
+ }
+
+ self.nextthink = time + 0.1;
+
+ // count runes my owner holds
+ rcount = 0;
+ rune = find(world, classname, "rune");
+ rnum = -1;
+ while(rune)
+ {
+ if(rune.owner == self.owner)
+ rcount = rcount + 1;
+ if(rune == self)
+ rnum = rcount;
+ rune = find(rune, classname, "rune");
+ }
+
+ ang_y = rnum*(360 / rcount) + mod(time, 360)*45;//180;
+
+ makevectors(ang);
+
+ setorigin(self, v_forward*32);
+ }
+
+ void rune_touch()
+ {
+ if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+ {
+ self.think = rune_respawn;
+ self.nextthink = time;
+ return;
+ }
+
- if(rune.owner.classname == "player")
++ if(!IS_PLAYER(other) || other.health < 1)
+ return;
+ if(self.wait > time)
+ return; // "notouch" time isn't finished
+
+ // detach from the spawn point you're on
+ rune_unmark_spot(self);
+
+ self.owner = other;
+ self.enemy.owner = other;
+ setattachment(self, other, "");
+
+ other.runes = other.runes | self.runes | self.enemy.runes;
+
+ //self.think = func_null;
+ //self.nextthink = 0;
+ self.think = RuneCarriedThink;
+ self.nextthink = time;
+ self.touch = func_null;
+
+ self.solid = SOLID_NOT;
+ setorigin(self, self.origin);
+
+ //sprint(other, strcat("^3You have picked up ",
+ // RuneName(self.runes & (RUNE_LAST*2-1)), " and "));
+ //sprint(other, strcat(RuneName(self.enemy.runes & (CURSE_WEAK | CURSE_VULNER | CURSE_VENOM | CURSE_SLOW | CURSE_EMPATHY)), "\n"));
+
+ bprint("^3", other.netname, "^7 has picked up ",
+ RuneName(self.runes & (RUNE_LAST*2-1)), "^7 and ");
+ bprint(RuneName(self.enemy.runes & (CURSE_WEAK | CURSE_VULNER | CURSE_VENOM | CURSE_SLOW | CURSE_EMPATHY)), "\n");
+ }
+
+ void rune_respawn()
+ {
+ rune_unmark_spot(self);
+ if(rune_spawn_somewhere(self))
+ {
+ self.solid = SOLID_TRIGGER;
+ self.touch = rune_touch;
+ self.think = rune_respawn;
+ self.nextthink = time + autocvar_g_runematch_shuffletime;//30 + random()*5; // fixme: cvar
+ }
+ else
+ {
+ // try again later
+ self.think = rune_respawn;
+ self.nextthink = time;
+ }
+ }
+
+ entity FindRune(entity own, string clname, float r)
+ {
+ entity rune;
+ float _count, c;
+
+ c = _count = 0;
+ rune = world;
+
+ do
+ {
+ rune = find(rune, classname, clname);
+ if(!rune)
+ rune = find(rune, classname, clname);
+ if(!rune)
+ break;
+ if(rune.owner == own)
+ {
+ _count = _count + 1;
+ if(_count >= r)
+ return rune;
+ if(r <= 1)
+ return rune;
+ }
+ c = c + 1;
+ }while(c < 30);
+ return world;
+ }
+
+
+ void DropRune(entity pl, entity e)
+ {
+ //entity pl;
+
+ //pl = e.owner;
+ // detach from player
+ setattachment(e, world, "");
+ e.owner = world;
+ e.enemy.owner = world;
+ // don't instantly touch player again
+ e.wait = time + 1; // "notouch" time
+ e.movetype = MOVETYPE_TOSS;
+ e.solid = SOLID_TRIGGER;
+ // reposition itself if not picked up soon
+ e.think = rune_respawn;
+ e.nextthink = time + autocvar_g_runematch_respawntime;//15 + random()*5; // fixme: cvar
+ e.touch = rune_touch;
+
+ pl.runes = pl.runes - (pl.runes & (e.runes | e.enemy.runes));
+
+ // toss from player
+ setorigin(e, pl.origin + '0 0 10');
+ e.velocity = '0 0 200' + '0 100 0'*crandom() + '100 0 0'*crandom();
+
+
+ bprint("^3", pl.netname, "^7 has lost ",
+ RuneName(e.runes & (RUNE_LAST*2-1)), "^7 and ");
+ bprint(RuneName(e.enemy.runes & (CURSE_WEAK | CURSE_VULNER | CURSE_VENOM | CURSE_SLOW | CURSE_EMPATHY)), "\n");
+ }
+
+ float RuneMatchesCurse(float r, float c)
+ {
+ float cr;
+ if(r & RUNE_STRENGTH)
+ cr = CURSE_WEAK;
+ else if(r & RUNE_DEFENSE)
+ cr = CURSE_VULNER;
+ else if(r & RUNE_REGEN)
+ cr = CURSE_VENOM;
+ else if(r & RUNE_SPEED)
+ cr = CURSE_SLOW;
+ else if(r & RUNE_VAMPIRE)
+ cr = CURSE_EMPATHY;
+ else return FALSE; // fixme: error?
+
+ if(c & cr)
+ return TRUE;
+ return FALSE;
+ }
+
+ // player died, drop runes
+ // each rune should pair up with a random curse and then be tossed from the player
+ void DropAllRunes(entity pl)
+ {
+ entity rune, curse;
+ float rcount, ccount, r, c, rand, prevent_same, numtodrop, tries;
+
+ entity curse1, rune1, curse2, rune2;
+
+ rcount = ccount = r = c = 0;
+ rune = find(world, classname, "rune");
+ while(rune)
+ {
+ if(rune.owner == pl)
+ rcount = rcount + 1;
+ rune = find(rune, classname, "rune");
+ }
+ curse = find(world, classname, "curse");
+ while(curse)
+ {
+ if(curse.owner == pl)
+ ccount = ccount + 1;
+ curse = find(curse, classname, "curse");
+ }
+
+ numtodrop = autocvar_g_runematch_drop_runes_max;
+ prevent_same = !autocvar_g_runematch_allow_same;
+
+ do
+ {
+ rune = find(rune, classname, "rune");
+ if(!rune)
+ break;
+ if(rune.owner != pl)
+ continue;
+
+
+ // find a random curse
+ tries = 15;
+ if(ccount > 1 && prevent_same)
+ {
+ // avoid pairing runes and curses that match each other
+ do{
+ rand = floor(random()*ccount) + 1;
+ curse = FindRune(pl, "curse", rand);
+ tries = tries - 1;
+ }while(RuneMatchesCurse(rune.runes, curse.runes) && tries > 0);
+ if(tries <= 0)
+ {
+ bprint("warning: couldn't prevent same rune\n");
+ }
+ }
+ else
+ {
+ rand = floor(random()*ccount) + 1;
+ curse = FindRune(pl, "curse", rand);
+ }
+
+ if(!curse)
+ error("Couldn't fine curse to bind rune to\n");
+
+ // pair rune and curse
+
+ rune1 = rune;
+ curse1 = curse;
+ rune2 = curse1.enemy;
+ curse2 = rune1.enemy;
+
+ if(rune1 != rune2) // not already attached to each other
+ {
+ rune1.enemy = curse1;
+ curse1.enemy = rune1;
+ setattachment(curse1, rune1, "");
+ rune2.enemy = curse2;
+ curse2.enemy = rune2;
+ setattachment(curse2, rune2, "");
+ //DropRune(pl, rune2);
+ //ccount = ccount - 1;
+ //rcount = rcount - 1;
+ }
+ DropRune(pl, rune1);
+
+ if(numtodrop <=0)
+ {
+ rune1.think = rune_respawn;
+ rune1.nextthink = time;
+ }
+
+ numtodrop = numtodrop - 1;
+
+ ccount = ccount - 1;
+ rcount = rcount - 1;
+
+ }while(rune);
+ }
+
+ void rune_reset()
+ {
+ if(self.owner)
+ if(self.owner.classname != "runematch_spawn_point")
+ DropAllRunes(self.owner);
+ rune_respawn();
+ }
+
+ void spawn_runes()
+ {
+ float rn, cs, runes_used, curses_used, prevent_same, numrunes;
+ entity e;
+
+ if(self)
+ remove(self);
+
+ // fixme: instead of placing them all now, why not
+ // simply create them all and let them call rune_respawn() as their think?
+
+ runes_used = 0;
+ curses_used = 0;
+
+ prevent_same = !autocvar_g_runematch_allow_same;
+ numrunes = RUNE_COUNT;
+
+ while(numrunes > 0)
+ {
+ RandomSelection_Init();
+ for(rn = RUNE_FIRST; rn <= RUNE_LAST; rn *= 2)
+ if not(runes_used & rn)
+ RandomSelection_Add(world, rn, string_null, 1, 1);
+ rn = RandomSelection_chosen_float;
+
+ RandomSelection_Init();
+ for(cs = CURSE_FIRST; cs <= CURSE_LAST; cs *= 2)
+ if not(curses_used & cs)
+ if not(prevent_same && cs == RuneMatchesCurse(rn, cs))
+ RandomSelection_Add(world, cs, string_null, 1, 1);
+ cs = RandomSelection_chosen_float;
+
+ if(!rn || !cs)
+ error("No rune/curse left");
+
+ runes_used |= rn;
+ curses_used |= cs;
+
+ e = spawn();
+ e.runes = rn;
+ e.classname = "rune";
+ e.touch = rune_touch;
+ e.think = rune_respawn;
+ e.nextthink = time;
+ e.movetype = MOVETYPE_TOSS;
+ e.solid = SOLID_TRIGGER;
+ e.flags = FL_ITEM;
+ e.reset = rune_reset;
+ setmodel(e, "models/runematch/rune.mdl"); // precision set below
+ setsize(e, '0 0 -35', '0 0 0');
+
+ e.enemy = spawn();
+ e.enemy.enemy = e;
+ e.enemy.classname = "curse";
+ e.enemy.runes = cs;
+ //e.enemy.avelocity = '300 500 200';
+ setmodel(e.enemy, "models/runematch/curse.mdl"); // precision set below
+ setorigin(e, '0 0 0');
+ setattachment(e.enemy, e, "");
+
+ e.colormod = RuneColormod(rn);
+ e.enemy.colormod = RuneColormod(cs);
+
+ e.alpha = e.enemy.alpha = autocvar_g_runematch_rune_alpha;//0.78;
+ e.effects = e.enemy.effects = autocvar_g_runematch_rune_effects | EF_LOWPRECISION;//EF_ADDITIVE;// | EF_FULLBRIGHT;
+
+ //e.glow_size = e.enemy.glow_size = cvar("g_runematch_rune_glow_size");
+ //e.glow_color = e.enemy.glow_color = cvar("g_runematch_rune_glow_color");
+
+ //rn = RUNE_FIRST;
+ //cs = CURSE_FIRST;
+
+ numrunes = numrunes - 1;
+ }
+ }
+
+ void runematch_init()
+ {
+ if(!g_runematch)
+ return;
+
+ entity e;
+ e = spawn();
+ e.think = spawn_runes;
+ e.nextthink = time + 0.1;
+ }
+
+
+ float runematch_point_time;
+
+ // give points to players who are holding runes
+ void RuneMatchGivePoints()
+ {
+ entity rune;
+
+ if(!g_runematch || !autocvar_g_runematch_pointamt)
+ return;
+
+ if(gameover)
+ return;
+
+ if(runematch_point_time > time)
+ return;
+
+ runematch_point_time = time + autocvar_g_runematch_pointrate;
+
+ rune = world;
+ do
+ {
+ rune = find(rune, classname, "rune");
+ if(!rune)
+ return;
+
++ if(IS_PLAYER(rune.owner))
+ {
+ UpdateFrags(rune.owner, autocvar_g_runematch_pointamt);
+ }
+ }while(rune);
+ }
+
+ float RunematchHandleFrags(entity attacker, entity targ, float f)
+ {
+ entity head;
+ float arunes, trunes, newfrags;
+
+ if(f <= 0)
+ return f;
+ if(attacker == targ)
+ return f;
+
+ arunes = trunes = 0;
+
+ head = find(world, classname, "rune");
+ while(head)
+ {
+ if(head.owner == attacker)
+ {
+ arunes = arunes + 1;
+ }
+ else if(head.owner == targ)
+ {
+ trunes = trunes + 1;
+ }
+
+ head = find(head, classname, "rune");
+ }
+
+ if(!arunes && !trunes)
+ return f - 1 + autocvar_g_runematch_frags_norune; // don't give points to players when no runes are involved.
+
+ newfrags = 0;
+ if(arunes)
+ { // got a kill while holding runes
+ newfrags = newfrags + autocvar_g_runematch_frags_killedby_runeholder;//5;
+ }
+ if(trunes)
+ { // killed an enemy holding runes
+ newfrags = newfrags + autocvar_g_runematch_frags_killed_runeholder;//5;
+ }
+ if(newfrags)
+ f = f - 1 + newfrags;
+
+ return f;
+ }
FOR_EACH_REALCLIENT(head)
{
- if(IS_PLAYER(head) || g_lms || g_arena || g_ca)
- if(head.classname == "player" || g_lms || g_arena || head.caplayer == 1)
++ if(IS_PLAYER(head) || g_lms || g_arena || head.caplayer == 1)
++activerealplayers;
++realplayers;
}
if(gameover)
self.classname = "observer";
- if(IS_PLAYER(self) && (!g_ca || (g_ca && allowed_to_spawn))) {
- if(self.classname == "player") {
++ if(IS_PLAYER(self))
++ {
entity spot, oldself;
float j;
{
if(self.cnt <= 10)
setmodel(self, strcat("models/sprites/", ftos(self.cnt), ".spr32"));
- if(clienttype(self.owner) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(self.owner))
{
if(self.cnt <= 10)
- AnnounceTo(self.owner, strcat(ftos(self.cnt), ""));
+ { Send_Notification(NOTIF_ONE, self.owner, MSG_ANNCE, Announcer_PickNumber(self.cnt)); }
}
self.nextthink = time + 1;
self.cnt -= 1;
if(targetteam == 0) // just die
{
self.killindicator.colormod = '0 0 0';
- if(clienttype(self) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(self))
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "^1Suicide in %d seconds", 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SUICIDE, self.killindicator.cnt);
}
else if(targetteam == -1) // auto
{
self.killindicator.colormod = '0 1 0';
- if(clienttype(self) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(self))
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Changing team in %d seconds", 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_AUTO, self.killindicator.cnt);
}
else if(targetteam == -2) // spectate
{
self.killindicator.colormod = '0.5 0.5 0.5';
- if(clienttype(self) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(self))
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, "Spectating in %d seconds", 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_TEAMCHANGE_SPECTATE, self.killindicator.cnt);
}
else
{
- self.killindicator.colormod = TeamColor(targetteam);
+ self.killindicator.colormod = Team_ColorRGB(targetteam);
- if(clienttype(self) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(self))
if(self.killindicator.cnt > 0)
- Send_CSQC_Centerprint_Generic(self, CPID_TEAMCHANGE, strcat("Changing to ", ColoredTeamName(targetteam), " in %d seconds"), 1, self.killindicator.cnt);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, APP_TEAM_NUM_4(targetteam, CENTER_TEAMCHANGE_), self.killindicator.cnt);
}
}
void ClientKill (void)
{
- if (gameover)
- return;
-
- if((g_arena || g_ca) && ((champion && IS_PLAYER(champion) && player_count > 1) || player_count == 1)) // don't allow a kill in this case either
- {
- // do nothing
- }
- else if(self.freezetag_frozen)
- {
- // do nothing
- }
- else
- ClientKill_TeamChange(0);
+ if(gameover) return;
+ if(self.player_blocked) return;
+ if(self.freezetag_frozen) return;
-
++
+ ClientKill_TeamChange(0);
}
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
self.netname_previous = strzone(self.netname);
- bprint("^4", self.netname, "^4 connected");
-
- if(!IS_OBSERVER(self) && (g_domination || g_ctf))
- bprint(" and joined the ", ColoredTeamName(self.team));
-
- bprint("\n");
- if((self.classname == STR_PLAYER && teamplay))
++ if(IS_PLAYER(self) && teamplay)
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_ENT_4(self, INFO_JOIN_CONNECT_TEAM_), self.netname);
+ else
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_JOIN_CONNECT, self.netname);
stuffcmd(self, strcat(clientstuff, "\n"));
stuffcmd(self, "cl_particles_reloadeffects\n"); // TODO do we still need this?
self.jointime = time;
self.allowed_timeouts = autocvar_sv_timeout_number;
- if(clienttype(self) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(self))
{
+ if(!autocvar_g_campaign)
+ {
+ self.motd_actived_time = -1;
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
+ }
+
if(autocvar_g_bugrigs || WEPSET_EQ_AW(g_weaponarena_weapons, WEP_TUBA))
stuffcmd(self, "cl_cmd settemp chase_active 1\n");
}
CSQCMODEL_AUTOINIT();
self.model_randomizer = random();
-
- if not(IS_REAL_CLIENT(self))
- return;
-
- sv_notice_join();
-
- MUTATOR_CALLHOOK(ClientConnect);
+
- if(clienttype(self) == CLIENTTYPE_REAL)
++ if(IS_REAL_CLIENT(self))
+ sv_notice_join();
+
+ MUTATOR_CALLHOOK(ClientConnect);
}
/*
=============
return maxclients - totalClients;
float currentlyPlaying = 0;
- FOR_EACH_REALPLAYER(e)
- currentlyPlaying += 1;
+ FOR_EACH_REALCLIENT(e)
- if(e.classname == "player" || e.caplayer == 1)
++ if(IS_PLAYER(e) || e.caplayer == 1)
+ currentlyPlaying += 1;
if(currentlyPlaying < autocvar_g_maxplayers)
return min(maxclients - totalClients, autocvar_g_maxplayers - currentlyPlaying);
* g_maxplayers_spectator_blocktime seconds
*/
void checkSpectatorBlock() {
- if(self.classname == "spectator" || self.classname == "observer") {
+ if(IS_SPEC(self) || IS_OBSERVER(self)) {
if( time > (self.spectatortime + autocvar_g_maxplayers_spectator_blocktime) ) {
- sprint(self, "^7You were kicked from the server because you are spectator and spectators aren't allowed at the moment.\n");
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_INFO, INFO_QUIT_KICK_SPECTATING);
dropclient(self);
}
}
}
- .float motd_actived_time; // used for both motd and campaign_message
void PrintWelcomeMessage()
{
- if (self.motd_actived_time == 0) { // is there already a message showing?
+ if(self.motd_actived_time == 0)
+ {
if (autocvar_g_campaign) {
- if ((self.classname == "player" && self.BUTTON_INFO) || (self.classname != "player")) {
+ if ((IS_PLAYER(self) && self.BUTTON_INFO) || (!IS_PLAYER(self))) {
self.motd_actived_time = time;
- Send_CSQC_Centerprint_Generic(self, CPID_MOTD, campaign_message, -1, 0);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, campaign_message);
}
} else {
- if ((time - self.jointime > autocvar_welcome_message_time) && self.BUTTON_INFO) {
+ if (self.BUTTON_INFO) {
self.motd_actived_time = time;
- Send_CSQC_Centerprint_Generic(self, CPID_MOTD, getwelcomemessage(), -1, 0);
+ Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_MOTD, getwelcomemessage());
}
}
- } else { // showing MOTD or campaign message
+ }
+ else if(self.motd_actived_time > 0) // showing MOTD or campaign message
+ {
if (autocvar_g_campaign) {
if (self.BUTTON_INFO)
self.motd_actived_time = time;
- else if ((time - self.motd_actived_time > 2) && self.classname == "player") { // hide it some seconds after BUTTON_INFO has been released
+ else if ((time - self.motd_actived_time > 2) && IS_PLAYER(self)) { // hide it some seconds after BUTTON_INFO has been released
self.motd_actived_time = 0;
- Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD);
+ Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
}
} else {
- if ((time - self.jointime) > autocvar_welcome_message_time) {
- if (self.BUTTON_INFO)
- self.motd_actived_time = time;
- else if (time - self.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
- self.motd_actived_time = 0;
- Send_CSQC_Centerprint_Generic_Expire(self, CPID_MOTD);
- }
+ if (self.BUTTON_INFO)
+ self.motd_actived_time = time;
+ else if (time - self.motd_actived_time > 2) { // hide it some seconds after BUTTON_INFO has been released
+ self.motd_actived_time = 0;
+ Kill_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER_CPID, CPID_MOTD);
}
}
}
self.usekeypressed = self.BUTTON_USE;
}
- PrintWelcomeMessage();
- if(clienttype(self) == CLIENTTYPE_REAL)
++ if(IS_REAL_CLIENT(self))
+ PrintWelcomeMessage();
- if(IS_PLAYER(self)) {
- // if(self.netname == "Wazat")
- // bprint(self.classname, "\n");
- if(self.classname == "player") {
++ if(IS_PLAYER(self))
++ {
CheckRules_Player();
Portal_ClearAllLater(self);
- if(clienttype(self) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(self))
{
- stuffcmd(self, "-zoom\n");
self.fixangle = TRUE;
//msg_entity = self;
//WriteByte (MSG_ONE, SVC_SETANGLE);
//WriteAngle (MSG_ONE, 80);
}
- if(defer_ClientKill_Now_TeamChange) // TODO does this work with FreezeTag?
- ClientKill_Now_TeamChange();
-
- if(g_arena)
- Spawnqueue_Unmark(self);
+ if(defer_ClientKill_Now_TeamChange)
+ ClientKill_Now_TeamChange(); // can turn player into spectator
- if(g_freezetag)
+ // player could have been miraculously resuscitated ;)
+ // e.g. players in freezetag get frozen, they don't really die
- if(self.health >= 1 || self.classname != "player")
++ if(self.health >= 1 || !IS_PLAYER(self))
return;
// when we get here, player actually dies
else if(teamsay < 0) // spectator message, only sent to spectators
{
sprint(source, sourcemsgstr);
- //print(msgstr); // send to server console too
+ dedicated_print(msgstr); // send to server console too
- FOR_EACH_REALCLIENT(head) if(head.classname != "player")
+ FOR_EACH_REALCLIENT(head) if not(IS_PLAYER(head))
if(head != source)
sprint(head, msgstr);
}
if (!f)
{
if (complain)
- if(clienttype(cl) == CLIENTTYPE_REAL)
+ if(IS_REAL_CLIENT(cl))
{
play2(cl, "weapons/unavailable.wav");
- sprint(cl, strcat("You don't have any ammo for the ^2", W_Name(wpn), "\n"));
Send_WeaponComplain (cl, wpn, W_Name(wpn), 0);
}
return FALSE;
}
}
- if(self.classname == "player" && autocvar_sv_spectate == 1)
+ if(IS_PLAYER(self) && autocvar_sv_spectate == 1)
ClientKill_TeamChange(-2); // observe
-
+
// in CA, allow a dead player to move to spectators (without that, caplayer!=0 will be moved back to the player list)
// note: if arena game mode is ever done properly, this needs to be removed.
- if(g_ca && self.caplayer && (IS_SPEC(self) || IS_OBSERVER(self)))
- if(self.caplayer && (self.classname == "spectator" || self.classname == "observer"))
++ if(self.caplayer && (IS_SPEC(self) || IS_OBSERVER(self)))
{
sprint(self, "WARNING: you will spectate in the next round.\n");
self.caplayer = 0;
entity plr;
FOR_EACH_CLIENT(plr) //give every spectator <g_maxplayers_spectator_blocktime> seconds time to become a player
{
- if(plr.classname == "spectator" || plr.classname == "observer")
+ if(IS_SPEC(plr) || IS_OBSERVER(plr))
{
plr.spectatortime = time;
- sprint(plr, strcat("^7You have to become a player within the next ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds, otherwise you will be kicked, because spectators aren't allowed at this time!\n"));
+ Send_Notification(NOTIF_ONE_ONLY, plr, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime);
}
}
bprint(strcat("^7All spectators will be automatically kicked when not joining the game after ", ftos(autocvar_g_maxplayers_spectator_blocktime), " seconds!\n"));
&& ((self.autoscreenshot > 0) && (time > self.autoscreenshot)) )
{
self.autoscreenshot = -1;
- if(IS_REAL_CLIENT(self)) { stuffcmd(self, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"", GetMapname(), strftime(FALSE, "%s"))); }
- if(clienttype(self) == CLIENTTYPE_REAL) { stuffcmd(self, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), strftime(FALSE, "%s"))); }
++ if(IS_REAL_CLIENT(self)) { stuffcmd(self, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), strftime(FALSE, "%s"))); }
return;
}
{
s = strcat(":player:see-labels:", GetPlayerScoreString(other, 0), ":");
s = strcat(s, ftos(rint(time - other.jointime)), ":");
- if(IS_PLAYER(other) || g_arena || g_ca || g_lms)
- if(other.classname == "player" || g_arena || other.caplayer == 1 || g_lms)
++ if(IS_PLAYER(other) || g_arena || other.caplayer == 1 || g_lms)
s = strcat(s, ftos(other.team), ":");
else
s = strcat(s, "spectator:");
{
if(autocvar_g_ctf_pass_request && !player.flagcarried && head.flagcarried)
{
- if(clienttype(head) == CLIENTTYPE_BOT)
+ if(IS_BOT_CLIENT(head))
{
- centerprint(player, strcat("Requesting ", head.netname, " to pass you the ", head.flagcarried.netname));
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_CTF_PASS_REQUESTING, head.netname);
ctf_Handle_Throw(head, player, DROP_PASS);
}
else
MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
{
- if(self.freezetag_frozen == 0)
+ if(round_handler_IsActive())
+ if(round_handler_CountdownRunning())
{
- if(self.team == COLOR_TEAM1)
- --redalive;
- else if(self.team == COLOR_TEAM2)
- --bluealive;
- else if(self.team == COLOR_TEAM3)
- --yellowalive;
- else if(self.team == COLOR_TEAM4)
- --pinkalive;
- --totalalive;
+ if(self.freezetag_frozen)
+ freezetag_Unfreeze(world);
+ freezetag_count_alive_players();
+ return 1; // let the player die so that he can respawn whenever he wants
+ }
- freezetag_Freeze(frag_attacker);
+ // Cases DEATH_TEAMCHANGE and DEATH_AUTOTEAMCHANGE are needed to fix a bug whe
+ // you succeed changing team through the menu: you both really die (gibbing) and get frozen
+ if(ITEM_DAMAGE_NEEDKILL(frag_deathtype)
+ || frag_deathtype == DEATH_TEAMCHANGE || frag_deathtype == DEATH_AUTOTEAMCHANGE)
+ {
+ // let the player die, he will be automatically frozen when he respawns
+ if(!self.freezetag_frozen)
+ {
+ freezetag_Add_Score(frag_attacker);
+ freezetag_count_alive_players();
+ }
+ else
+ freezetag_Unfreeze(world); // remove ice
+ self.freezetag_frozen_timeout = -2; // freeze on respawn
+ return 1;
}
+ if(self.freezetag_frozen)
+ return 1;
+
+ freezetag_Freeze(frag_attacker);
+
if(frag_attacker == frag_target || frag_attacker == world)
{
- if(frag_target.classname == STR_PLAYER)
+ if(IS_PLAYER(frag_target))
- centerprint(frag_target, "^1You froze yourself.\n");
- bprint("^7", frag_target.netname, "^1 froze himself.\n");
+ Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_SELF);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_SELF, frag_target.netname);
}
else
{
- if(frag_target.classname == STR_PLAYER)
+ if(IS_PLAYER(frag_target))
- centerprint(frag_target, strcat("^1You were frozen by ^7", frag_attacker.netname, ".\n"));
+ Send_Notification(NOTIF_ONE, frag_target, MSG_CENTER, CENTER_FREEZETAG_FROZEN, frag_attacker.netname);
- if(frag_attacker.classname == STR_PLAYER)
+ if(IS_PLAYER(frag_attacker))
- centerprint(frag_attacker, strcat("^2You froze ^7", frag_target.netname, ".\n"));
- bprint("^7", frag_target.netname, "^1 was frozen by ^7", frag_attacker.netname, ".\n");
+ Send_Notification(NOTIF_ONE, frag_attacker, MSG_CENTER, CENTER_FREEZETAG_FREEZE, frag_target.netname);
+ Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_FREEZETAG_FREEZE, frag_target.netname, frag_attacker.netname);
}
frag_target.health = 1; // "respawn" the player :P
return;
}
- if (attacker.classname == "player")
+ if (IS_PLAYER(attacker))
{
nag = FALSE;
- if(self.team == COLOR_TEAM1)
+ if(self.team == NUM_TEAM_1)
{
if(time - ons_notification_time_team1 > 10)
{
s = strcat(s, ":human");
else
s = strcat(s, ":bot");
- if(!IS_PLAYER(p) && !g_arena && !g_ca && !g_lms)
- if(p.classname != "player" && !g_arena && p.caplayer != 1 && !g_lms)
++ if(!IS_PLAYER(p) && !g_arena && p.caplayer != 1 && !g_lms)
s = strcat(s, ":spectator");
}
else
{
- if(IS_PLAYER(p) || g_arena || g_ca || g_lms)
- if(p.classname == "player" || g_arena || p.caplayer == 1 || g_lms)
++ if(IS_PLAYER(p) || g_arena || p.caplayer == 1 || g_lms)
s = GetPlayerScoreString(p, 2);
else
s = "-666";
_switchweapon = TRUE;
// play some cool sounds ;)
- if (clienttype(player) == CLIENTTYPE_REAL)
+ if (IS_REAL_CLIENT(player))
{
if(player.health <= 5)
- AnnounceTo(player, "lastsecond");
+ Send_Notification(NOTIF_ONE, player, MSG_ANNCE, ANNCE_MINSTAGIB_LASTSECOND);
else if(player.health < 50)
- AnnounceTo(player, "narrowly");
+ Send_Notification(NOTIF_ONE, player, MSG_ANNCE, ANNCE_MINSTAGIB_NARROWLY);
}
// sound not available
// else if(item.items == IT_CELLS)
oldself = self;
self = e;
-- if not(g_minstagib)
- if (IS_PLAYER(other))
- {
- sprint (other, "You got the ^2");
- sprint (other, name);
- sprint (other, "\n");
- }
- if(other.classname == "player")
++ if(IS_PLAYER(other))
+ { Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); }
self = oldself;
}
if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
return; // we're already a stuck mine, why do we get called? TODO does this even happen?
- PROJECTILE_TOUCH;
+ if(WarpZone_Projectile_Touch())
+ {
+ if(wasfreed(self))
+ self.realowner.minelayer_mines -= 1;
+ return;
+ }
- if(other && other.classname == "player" && other.deadflag == DEAD_NO)
+ if(other && IS_PLAYER(other) && other.deadflag == DEAD_NO)
{
// hit a player
// don't stick