From: Mario Date: Tue, 7 May 2013 05:49:31 +0000 (+1000) Subject: Merge branch 'master' into Mario/classname_checks X-Git-Tag: xonotic-v0.7.0~57^2^2~3 X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=30e9db455abe691a3560555a989beb382b3b2531 Merge branch 'master' into Mario/classname_checks --- 30e9db455abe691a3560555a989beb382b3b2531 diff --cc qcsrc/server/assault.qc index fe5fb5ef04,7a5662c979..71ac7239a6 --- a/qcsrc/server/assault.qc +++ b/qcsrc/server/assault.qc @@@ -361,12 -361,12 +361,12 @@@ void assault_new_round( 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; } } diff --cc qcsrc/server/attic/runematch.qc index 0000000000,ba8f648c88..1b6cc5dbb1 mode 000000,100644..100644 --- a/qcsrc/server/attic/runematch.qc +++ b/qcsrc/server/attic/runematch.qc @@@ -1,0 -1,604 +1,604 @@@ + 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(self.owner.classname != "player" || time < game_starttime) ++ 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(other.classname != "player" || other.health < 1) ++ 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(rune.owner.classname == "player") ++ 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; + } diff --cc qcsrc/server/bot/bot.qc index ee4933cc46,f6e7f6f1b6..b45f35aa8f --- a/qcsrc/server/bot/bot.qc +++ b/qcsrc/server/bot/bot.qc @@@ -551,7 -551,7 +551,7 @@@ float bot_fixcount( 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; } diff --cc qcsrc/server/cl_client.qc index c8b64a175f,5d29bf7e15..4f741fa443 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@@ -685,7 -627,7 +627,8 @@@ void PutClientInServer (void 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; @@@ -1149,10 -1082,10 +1083,10 @@@ void KillIndicator_Think( { 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; @@@ -1235,30 -1168,30 +1169,30 @@@ void ClientKill_TeamChange (float targe 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); } } @@@ -1266,19 -1199,11 +1200,11 @@@ 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 @@@ -1477,12 -1401,10 +1402,10 @@@ void ClientConnect (void 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? @@@ -1531,8 -1446,14 +1447,14 @@@ 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"); } @@@ -1585,16 -1506,11 +1507,11 @@@ 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); } /* ============= @@@ -2392,8 -2270,9 +2271,9 @@@ float nJoinAllowed(entity ignore) 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); @@@ -2406,45 -2285,45 +2286,45 @@@ * 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); } } } @@@ -2639,11 -2520,10 +2521,11 @@@ void PlayerPreThink (void 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(); diff --cc qcsrc/server/cl_player.qc index 3014b03cb3,95aeced31b..aa6258468b --- a/qcsrc/server/cl_player.qc +++ b/qcsrc/server/cl_player.qc @@@ -617,9 -598,8 +598,8 @@@ void PlayerDamage (entity inflictor, en 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); @@@ -628,13 -608,12 +608,12 @@@ //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 @@@ -957,8 -946,8 +946,8 @@@ float Say(entity source, float teamsay 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); } diff --cc qcsrc/server/cl_weaponsystem.qc index 8d83c975e9,afabe18202..405904565e --- a/qcsrc/server/cl_weaponsystem.qc +++ b/qcsrc/server/cl_weaponsystem.qc @@@ -711,10 -696,9 +696,9 @@@ float client_hasweapon(entity cl, floa 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; diff --cc qcsrc/server/command/cmd.qc index c7fcdeacb8,e22399f4ac..ec9c33b198 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@@ -408,12 -412,12 +412,12 @@@ void ClientCommand_spectate(float reque } } - 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; diff --cc qcsrc/server/command/sv_cmd.qc index dbc09c0ee3,0944f04fbb..4c0445f1d3 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@@ -1109,10 -1105,10 +1105,10 @@@ void GameCommand_nospectators(float req entity plr; FOR_EACH_CLIENT(plr) //give every spectator 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")); diff --cc qcsrc/server/g_world.qc index 91f8caf39c,d8ce88cf3c..e5106bbcd4 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@@ -1347,7 -1339,7 +1339,7 @@@ void IntermissionThink( && ((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; } @@@ -1475,7 -1467,7 +1467,7 @@@ void DumpStats(float final { 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:"); diff --cc qcsrc/server/mutators/gamemode_ctf.qc index 5ca20ec7b5,8f0bc931ef..bc19d88ebb --- a/qcsrc/server/mutators/gamemode_ctf.qc +++ b/qcsrc/server/mutators/gamemode_ctf.qc @@@ -1840,9 -1852,9 +1852,9 @@@ MUTATOR_HOOKFUNCTION(ctf_PlayerUseKey { 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 diff --cc qcsrc/server/mutators/gamemode_freezetag.qc index 4014b14039,980a9b20d9..79ce5e2e14 --- a/qcsrc/server/mutators/gamemode_freezetag.qc +++ b/qcsrc/server/mutators/gamemode_freezetag.qc @@@ -263,34 -323,50 +323,50 @@@ MUTATOR_HOOKFUNCTION(freezetag_RemovePl 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 diff --cc qcsrc/server/mutators/gamemode_onslaught.qc index 21a95d0f76,3801de302d..e4be2d7ab4 --- a/qcsrc/server/mutators/gamemode_onslaught.qc +++ b/qcsrc/server/mutators/gamemode_onslaught.qc @@@ -985,10 -986,10 +986,10 @@@ void onslaught_controlpoint_icon_damage 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) { diff --cc qcsrc/server/scores.qc index 5ccc212bdc,4c75c9850a..114c4f7f85 --- a/qcsrc/server/scores.qc +++ b/qcsrc/server/scores.qc @@@ -527,12 -527,12 +527,12 @@@ void WinningConditionHelper( 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"; diff --cc qcsrc/server/t_items.qc index 407962ae6a,392c05ce14..49a1cb3b5d --- a/qcsrc/server/t_items.qc +++ b/qcsrc/server/t_items.qc @@@ -627,12 -627,12 +627,12 @@@ float Item_GiveTo(entity item, entity p _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) diff --cc qcsrc/server/w_common.qc index 592fa7df35,2e0c1e8f02..a2de5dab04 --- a/qcsrc/server/w_common.qc +++ b/qcsrc/server/w_common.qc @@@ -11,13 -11,9 +11,8 @@@ void W_GiveWeapon (entity e, float wep 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; } diff --cc qcsrc/server/w_minelayer.qc index 12d0a40f9c,40c60e827e..813bcff755 --- a/qcsrc/server/w_minelayer.qc +++ b/qcsrc/server/w_minelayer.qc @@@ -225,9 -226,14 +226,14 @@@ void W_Mine_Touch (void 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