diff --git a/README.md b/README.md index 9b595c09..74419322 100644 --- a/README.md +++ b/README.md @@ -3,17 +3,19 @@ FortressOne Server v0.1.0 New features ------ +* Server option for overriding map class restrictions (except civilian). `serverinfo override_mapclasses 1` or `serverinfo omc 1`. +* Option for maximum grenades for all classes. `localinfo max_gren1_ `, short `localinfo mg1_ `. Works for gren1s and gren2s. Eg `localinfo max_gren1_scout 0` to remove caltrops or `localinfo mg2_9 2` to reduce max EMPs to 2. +* Option to fully restock player's clip and finish reload immediately if in progress. `localinfo stock_reload 1` (`localinfo srd 1`) will trigger only on flag capture (with stock_on_cap enabled). `2` will trigger whenever any tfgoal gives you the appropriate ammo. +* Option for statusbar flaginfo. `setinfo sbflaginfo 1` (default). Setting it to `2` will skip the tf tips on respawn and show flag info all the time. * Admin system created to allow for easy setup of pub/pug/quad/duel games, kick players etc `localinfo adminpwd ` and `cmd adminpwd ; wait; adminmenu` * Loc support added to server, show locations for dropped flag. * Nailgrenades changed to "Shock/Laser Grenades" to lower spam/not stop bunnyhopping on hit (0 original, 1 laser, 2 burst). `localinfo nailgren_type 1` and `nginfo` in game for all configurable settings. -* Option for flaginfo on sbar. `setinfo sbflaginfo on` * Option for hitsounds (1 - enemies only, 2 - enemies and teammates). `setinfo hitsound 2` * Option for medic to be immune from concussion effects. `localinfo medicnocuss on`. * Option to adjust concussion grenade effect time in seconds. `localinfo cussgrentime n`. * Increased nail velocity. Disable with `localinfo old_ng_velocity on`. * Nailgun and Super-nailgun damage configurable with `localinfo ng_damage` and `localinfo sng_damage`. * Keys and flags glow their colour. -* Capping player gets full restock. * Option to adjust conussion grenade effect time in seconds. `localinfo cussgrentime`. * Option to fully restock player on cap. `localinfo stock_on_cap on`. * Option for packs to fully restock health and armour of player. `localinfo stockfull on`. diff --git a/admin.qc b/admin.qc index acfd2afa..1f73725c 100644 --- a/admin.qc +++ b/admin.qc @@ -115,6 +115,13 @@ void () Admin_DoBan = { self.admin_use = world; }; +void () Admin_ForceSpectator = { + bprint4(PRINT_HIGH, self.admin_use.netname, " was made spectator by ", self.netname, ". There's probably a good reason for this.\n"); + stuffcmd(self.admin_use, "observe\n"); + self.admin_mode = 0; + self.admin_use = world; +}; + void () CeaseFire_think = { local entity te; @@ -159,10 +166,13 @@ void () Admin_CeaseFire = { dremove(te); } cease_fire = 0; + bprint(2, "RESUME FIRE\n"); if (cb_prematch) { - StartTimer(); + //Make sure you don't just start the countdown on resume when not everyone's readied up + if (is_countdown || v_ready == TeamFortress_GetNoPlayers () ) { + StartTimer(); + } } - bprint(2, "RESUME FIRE\n"); te = find(world, classname, "player"); while (te) { CenterPrint3(te, "RESUME FIRE\nCalled by: ", self.netname, "\n"); @@ -174,6 +184,42 @@ void () Admin_CeaseFire = { } }; +void () Admin_Pause = { + if (!is_paused) { + setpause(1); + is_paused = 1; + pause_actor = self.netname; + if (cb_prematch && infokey(world, "status") == "Countdown") { + StopTimer(); + bprint2(2, pause_actor, " stops the countdown\n"); + return; + } + bprint2(2, pause_actor, " paused the game\n"); + } + else { + if (cb_prematch) { + //Make sure you don't just start the countdown on resume when not everyone's readied up + if (is_countdown || v_ready == TeamFortress_GetNoPlayers () ) { + StartTimer(); + } + setpause(0); + is_paused = 0; + return; + } + pause_actor = self.netname; + if (!unpause_requested) { + bprint2(2, pause_actor, " has requested to unpause the game in 5 seconds\n"); + unpause_requested = 1; + } + else { + bprint2(2, pause_actor, " cancels unpause request\n"); + unpause_requested = 0; + unpause_countdown = 0; + unpause_lastcountnumber = 0; + } + } +} + void (entity p) CheckAutoKick = { local float rnum; local entity te; @@ -210,6 +256,10 @@ void (entity p) CheckAutoKick = { void (string cl_pwd) Admin_Check = { + if (self.is_admin) { + sprint(self, PRINT_HIGH, "You are already an admin\n"); + return; + } local string st2; st2 = infokey(world, "adminpwd"); @@ -239,4 +289,5 @@ void () Admin_Aliases = TeamFortress_Alias("adminmenu", TF_ADMIN_ADMINMENU, 0); TeamFortress_Alias("startmatch", TF_ADMIN_FORCESTARTMATCH, 0); TeamFortress_Alias("readystatus", TF_ADMIN_READYSTATUS, 0); -}; \ No newline at end of file + stuffcmd(self,"alias ceasefire \"cmd ceasefire\"\n"); +}; diff --git a/buttons.qc b/buttons.qc index 62031067..d66f1222 100644 --- a/buttons.qc +++ b/buttons.qc @@ -3,6 +3,7 @@ #define BUTTON_START_OUT 32 void () button_return; +void (entity pe_player, float dontstopdead) Spy_CheckForFuncTouch; void () button_wait = { self.state = STATE_TOP; @@ -70,6 +71,8 @@ void () button_touch = { if (other.classname != "player") return; + Spy_CheckForFuncTouch(other, 0); + if (self.goal_activation & TFGA_SPANNER) return; diff --git a/clan.qc b/clan.qc index 83a34368..1ef22a4b 100644 --- a/clan.qc +++ b/clan.qc @@ -83,7 +83,7 @@ void () StartMatch = TeamFortress_RemoveTimers(); self.frags = 0; - self.real_frags = 0; + self.real_frags = 0; setspawnparms(self); if (!quadmode) PutClientInServer(); @@ -97,6 +97,18 @@ void () StartMatch = gren.nextthink = (time + 0.1); gren = find(gren, classname, "grenade"); } + te = find(world, classname, "detpack"); + while (te){ + if (te.weaponmode == 1) { + TeamFortress_SetSpeed (te.enemy); + dremove(te.oldenemy); + dremove(te.observer_list); + } + dremove(te.linked_list); + dremove(te); + te = find (te, classname, "detpack"); + } + cb_prematch = 0; cease_fire = 0; @@ -121,7 +133,7 @@ void () StartMatch = if (!quadmode) { te.think = MatchThink; te.nextthink = (time + 1); - } + } } st = infokey(world, "spectalk"); f2 = stof(st); @@ -182,7 +194,7 @@ void () PreMatch_Think = { } if (!quadmode) StartMatch(); - else + else StartQuadRound(); return; } @@ -250,6 +262,7 @@ void () PreMatch_Think = { } strunzone(num); } + self.nextthink = (time + 1); }; @@ -262,7 +275,7 @@ void () ResetBreakAndReady = { v_break = 0; v_ready = 0; te = find (te, classname, "player"); - } + } } void () StartTimer = @@ -304,7 +317,7 @@ void () StartTimer = te.nextthink = 0.01; } - ResetBreakAndReady(); + ResetBreakAndReady(); timer = spawn(); timer.owner = world; timer.classname = "prematch"; @@ -425,13 +438,13 @@ void () DumpClanScores = { if ((no_teams == 2) && (((team1score == team2score) && teamfrags) || ((team1frags == team2frags) && !teamfrags))) { bprint(PRINT_HIGH, " draw "); - } + } else if ((no_teams == 3) && ((((team1score == team2score) == team3score) && teamfrags) || (((team1frags == team2frags) == team3frags) && !teamfrags))) { bprint(PRINT_HIGH, " draw "); - } + } else if ((no_teams == 3) && (((((team1score == team2score) == team3score) == team4score) @@ -440,7 +453,7 @@ void () DumpClanScores = { ((((team1frags == team2frags) == team3frags) == team4frags) && !teamfrags))) { bprint(PRINT_HIGH, " draw "); - } + } else { st = GetTeamName(winners); bprint(PRINT_HIGH, st, " defeated "); @@ -736,6 +749,43 @@ void () TeamFortress_ShowIDs = { sprint(self, PRINT_HIGH, "None\n"); }; +void () CenterPrint_Players_NotReady = { + string players_not_ready; + entity te; + players_not_ready = "Not ready: "; + + local float first = 0; + te = find (world, classname, "player"); + while (te) { + if (te.is_ready == 0) + { + first = first + 1; + if (first == 1) + { + players_not_ready = strcat(players_not_ready, te.netname); + } + else if (first > 1 && first < 5) + { + players_not_ready = strcat(players_not_ready, ", ", te.netname); + } + else if (first >= 5) + { + players_not_ready = strcat(players_not_ready, " and others..."); + break; + } + } + te = find (te, classname, "player"); + } + players_not_ready = strcat(players_not_ready, "\n", "Type \s/ready\s in the console to toggle your ready status\n"); + + te = find(world, classname, "player"); + while (te) + { + CenterPrint(te, players_not_ready); + te = find(te, classname, "player"); + } +} + void () Broadcast_Players_NotReady = { local entity te; if (v_ready != 0) { @@ -747,11 +797,11 @@ void () Broadcast_Players_NotReady = { if (!first) players_not_ready = strcat(players_not_ready, ", "); else - first = 0; + first = 0; players_not_ready = strcat(players_not_ready, te.netname); } te = find (te, classname, "player"); - } + } players_not_ready = strcat(players_not_ready, "\n"); bprint(1, players_not_ready); te = find (world, classname, "player"); @@ -796,7 +846,7 @@ void () PlayerReady = if (self.playerclass == 0) { sprint(self, 2, "You must choose a class first.\n"); return; - } + } if (intermission_running) return; if (self.classname != "player") @@ -810,8 +860,12 @@ void () PlayerReady = bprint2 (3, self.netname, " is ready to start the match\n"); f1 = TeamFortress_GetNoPlayers (); if (v_ready == f1 ) { - bprint (2, "All players ready, starting match\n"); - StartTimer (); + if(cease_fire) { + bprint (2, "All players ready, match will start after ceasefire ends.\n"); + } else { + bprint (2, "All players ready, starting match\n"); + StartTimer (); + } return; } Broadcast_Players_NotReady(); @@ -831,17 +885,22 @@ void () RemoveVotes = { }; void () PreMatch_Message = { - local entity p = find (world, classname, "player"); - while (p != world) { - if (p.netname != "") { - sprint(p, PRINT_HIGH, "Currently in \sprematch\s time\n"); - if (p.is_ready) - sprint(p, PRINT_HIGH, "You are \sready\s to start the match.\n Type \s/notready\s in the console if you are not ready\n"); - else - sprint(p, PRINT_HIGH, "Type \s/ready\s in the console if you are ready to start the match\n"); - stuffcmd(p, "play buttons/switch04.wav\n"); + self.cnt2 = self.cnt2 + 1; + if (self.cnt2 % 30 == 0) + { + local entity p = find (world, classname, "player"); + while (p != world) { + if (p.netname != "") { + sprint(p, PRINT_HIGH, "Currently in \sprematch\s time\n"); + if (p.is_ready) + sprint(p, PRINT_HIGH, "You are \sready\s to start the match.\n Type \s/notready\s in the console if you are not ready\n"); + else + sprint(p, PRINT_HIGH, "Type \s/ready\s in the console if you are ready to start the match\n"); + stuffcmd(p, "play buttons/switch04.wav\n"); + } + p = find(p, classname, "player"); } - p = find(p, classname, "player"); } - self.nextthink = time + 30; -} \ No newline at end of file + CenterPrint_Players_NotReady(); + self.nextthink = time + 1; +} diff --git a/client.qc b/client.qc index 8e9fdc9c..9c79061f 100644 --- a/client.qc +++ b/client.qc @@ -142,12 +142,13 @@ void () autokick_think = { dremove(self); }; -float (string ps_short, string ps_setting, string ps_default) CF_GetSetting = { +//if ent is world, return serverinfo, if ent is a player, return that client's setinfo key +float (entity ent, string ps_short, string ps_setting, string ps_default) FO_GetUserSetting = { local string st; - st = infokey(world, ps_short); + st = infokey(ent, ps_short); if (st == string_null) { - st = infokey(world, ps_setting); + st = infokey(ent, ps_setting); if (st == string_null) { st = ps_default; } @@ -164,6 +165,10 @@ float (string ps_short, string ps_setting, string ps_default) CF_GetSetting = { } }; +float (string ps_short, string ps_setting, string ps_default) CF_GetSetting = { + return FO_GetUserSetting(world, ps_short, ps_setting, ps_default); +}; + void () DecodeLevelParms = { local float fl; local string st; @@ -327,6 +332,33 @@ void () DecodeLevelParms = { toggleflags = toggleflags - (toggleflags & TFLAG_FULLTEAMSCORE); } + // nailgren types 0 = NGR_TYPE_DEFAULT, 1 = NGR_TYPE_LASER, 2 = NGR_TYPE_BURST + nailgren_type = CF_GetSetting("ngt", "nailgren_type", ftos(NGR_TYPE_LASER)); + + // how many rotations the nailgren does [2] + lasergren_rotationcount = CF_GetSetting("lgrc", "lasergren_rotationcount", ftos(NGR_LASER_DEFAULT_ROTATIONCOUNT)); + + // time each rotation takes [1] + lasergren_rotationtime = CF_GetSetting("lgrt", "lasergren_rotationtime", ftos(NGR_LASER_DEFAULT_ROTATIONTIME)); + + // damage [20] + lasergren_damage = CF_GetSetting("lgd", "lasergren_damage", ftos(NGR_LASER_DEFAULT_DAMAGE)); + + // think time for lightning, lower is smoother [0.1] + lasergren_thinktime = CF_GetSetting("lgtt", "lasergren_thinktime", "0.01"); //ftos cuts off after 1 dec place, using ftos here would result in 0 and crash? + + // range of shaft [150] + lasergren_range = CF_GetSetting("lgr", "lasergren_range", ftos(NGR_LASER_DEFAULT_RANGE)); + + // how many bursts of nails [2] + burstgren_count = CF_GetSetting("bgc", "burstgren_count", ftos(NGR_BURST_DEFAULT_COUNT)); + + // time between each burst [0.7] + burstgren_interval = CF_GetSetting("bgi", "burstgren_interval", ftos(NGR_BURST_DEFAULT_INTERVAL)); + + // time before nail projectile destroys itself [0.3] + burstgren_range = CF_GetSetting("bgr", "burstgren_range", ftos(NGR_BURST_DEFAULT_RANGE)); + // use old concussion, gas and flash grenades [off] old_grens = CF_GetSetting("og", "old_grens", "off"); @@ -450,6 +482,9 @@ void () DecodeLevelParms = { // stock on cap [on] stock_on_cap = CF_GetSetting("soc", "stock_on_cap", "on"); + // stock clip to full for reloading guns [on] + stock_reload = CF_GetSetting("srd", "stock_reload", "on"); + // display class tips [on] classtips = CF_GetSetting("ct", "classtips", "on"); @@ -503,6 +538,39 @@ void () DecodeLevelParms = { // pyro class type - 0:default; 1:OzTF like; 2:plasmaclass pyro_type = CF_GetSetting("pyrotype", "pyro_type", "1"); + // ceasefire type - 0: default; 1: pause + ceasefire_type = CF_GetSetting("ceasefiretype", "cft", "1"); + + // wait until attack_finished is over before changing weapons + chweap_wait_attfinished = CF_GetSetting("cwaf", "chweap_wait_atk", "on"); + + // enable flag model following the player who has it + flag_follow = CF_GetSetting("flagfollow", "flag_follow", "on"); + + // override map-set class restrictions [off] + override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); + // Maximum number of primary grenades per class + max_gren1_scout = CF_GetSetting("mg1_1", "max_gren1_scout", ftos(PC_SCOUT_GRENADE_MAX_1)); + max_gren1_sniper = CF_GetSetting("mg1_2", "max_gren1_sniper", ftos(PC_SNIPER_GRENADE_MAX_1)); + max_gren1_soldier = CF_GetSetting("mg1_3", "max_gren1_soldier", ftos(PC_SOLDIER_GRENADE_MAX_1)); + max_gren1_demoman = CF_GetSetting("mg1_4", "max_gren1_demoman", ftos(PC_DEMOMAN_GRENADE_MAX_1)); + max_gren1_medic = CF_GetSetting("mg1_5", "max_gren1_medic", ftos(PC_MEDIC_GRENADE_MAX_1)); + max_gren1_hwguy = CF_GetSetting("mg1_6", "max_gren1_hwguy", ftos(PC_HVYWEAP_GRENADE_MAX_1)); + max_gren1_pyro = CF_GetSetting("mg1_7", "max_gren1_pyro", ftos(PC_PYRO_GRENADE_MAX_1)); + max_gren1_spy = CF_GetSetting("mg1_8", "max_gren1_spy", ftos(PC_SPY_GRENADE_MAX_1)); + max_gren1_engineer = CF_GetSetting("mg2_9", "max_gren1_engineer", ftos(PC_ENGINEER_GRENADE_MAX_1)); + + // Maximum number of secondary grenades per class + max_gren2_scout = CF_GetSetting("mg2_1", "max_gren2_scout", ftos(PC_SCOUT_GRENADE_MAX_2)); + max_gren2_sniper = CF_GetSetting("mg2_2", "max_gren2_sniper", ftos(PC_SNIPER_GRENADE_MAX_2)); + max_gren2_soldier = CF_GetSetting("mg2_3", "max_gren2_soldier", ftos(PC_SOLDIER_GRENADE_MAX_2)); + max_gren2_demoman = CF_GetSetting("mg2_4", "max_gren2_demoman", ftos(PC_DEMOMAN_GRENADE_MAX_2)); + max_gren2_medic = CF_GetSetting("mg2_5", "max_gren2_medic", ftos(PC_MEDIC_GRENADE_MAX_2)); + max_gren2_hwguy = CF_GetSetting("mg2_6", "max_gren2_hwguy", ftos(PC_HVYWEAP_GRENADE_MAX_2)); + max_gren2_pyro = CF_GetSetting("mg2_7", "max_gren2_pyro", ftos(PC_PYRO_GRENADE_MAX_2)); + max_gren2_spy = CF_GetSetting("mg2_8", "max_gren2_spy", ftos(PC_SPY_GRENADE_MAX_2)); + max_gren2_engineer = CF_GetSetting("mg2_9", "max_gren2_engineer", ftos(PC_ENGINEER_GRENADE_MAX_2)); + st = infokey(world, "default"); if (st == "on") { impulse_queue = FALSE; @@ -545,6 +613,7 @@ void () DecodeLevelParms = { spawnfull = TRUE; stockfull = TRUE; stock_on_cap = TRUE; + stock_reload = TRUE; classtips = TRUE; sniperpower = TRUE; sniperreloadpercent = TRUE; @@ -553,6 +622,24 @@ void () DecodeLevelParms = { ng_velocity = 1500; old_ng_rof = FALSE; pyro_type = 1; + max_gren1_scout = PC_SCOUT_GRENADE_MAX_1; + max_gren1_sniper = PC_SNIPER_GRENADE_MAX_1; + max_gren1_soldier = PC_SOLDIER_GRENADE_MAX_1; + max_gren1_demoman = PC_DEMOMAN_GRENADE_MAX_1; + max_gren1_medic = PC_MEDIC_GRENADE_MAX_1; + max_gren1_hwguy = PC_HVYWEAP_GRENADE_MAX_1; + max_gren1_pyro = PC_PYRO_GRENADE_MAX_1; + max_gren1_spy = PC_SPY_GRENADE_MAX_1; + max_gren1_engineer = PC_ENGINEER_GRENADE_MAX_1; + max_gren2_scout = PC_SCOUT_GRENADE_MAX_2; + max_gren2_sniper = PC_SNIPER_GRENADE_MAX_2; + max_gren2_soldier = PC_SOLDIER_GRENADE_MAX_2; + max_gren2_demoman = PC_DEMOMAN_GRENADE_MAX_2; + max_gren2_medic = PC_MEDIC_GRENADE_MAX_2; + max_gren2_hwguy = PC_HVYWEAP_GRENADE_MAX_2; + max_gren2_pyro = PC_PYRO_GRENADE_MAX_2; + max_gren2_spy = PC_SPY_GRENADE_MAX_2; + max_gren2_engineer = PC_ENGINEER_GRENADE_MAX_2; } st = infokey(world, "faithful"); @@ -596,6 +683,7 @@ void () DecodeLevelParms = { spawnfull = FALSE; stockfull = FALSE; stock_on_cap = FALSE; + stock_reload = FALSE; classtips = FALSE; sniperpower = FALSE; sniperreloadpercent = FALSE; @@ -604,6 +692,24 @@ void () DecodeLevelParms = { ng_velocity = 1000; old_ng_rof = TRUE; pyro_type = 0; + max_gren1_scout = 4; + max_gren1_sniper = 4; + max_gren1_soldier = 4; + max_gren1_demoman = 4; + max_gren1_medic = 4; + max_gren1_hwguy = 4; + max_gren1_pyro = 4; + max_gren1_spy = 4; + max_gren1_engineer = 4; + max_gren2_scout = 3; + max_gren2_sniper = 4; + max_gren2_soldier = 3; + max_gren2_demoman = 4; + max_gren2_medic = 3; + max_gren2_hwguy = 4; + max_gren2_pyro = 4; + max_gren2_spy = 4; + max_gren2_engineer = 4; } } @@ -1209,7 +1315,7 @@ void () PutClientInServer = { if (self.tfstate & TFSTATE_RANDOMPC) { oldclass = self.playerclass; self.playerclass = 1 + floor(random() * (10 - 1)); - while (!IsLegalClass(self.playerclass) || + while ((!IsLegalClass(self.playerclass) && !override_mapclasses) || (self.playerclass == oldclass) || CF_ClassIsRestricted(self.team_no, self.playerclass)) { self.playerclass = 1 + floor(random() * (10 - 1)); @@ -1922,8 +2028,6 @@ void () CheckPowerups = { }; void () PlayerPostThink = { - local float fdmg; - if (self.view_ofs == '0 0 0') { return; } @@ -1933,6 +2037,8 @@ void () PlayerPostThink = { return; } + local float fdmg; + if (((self.jump_flag < -300) && (self.flags & 512)) && (self.health > 0)) { if (self.watertype == -3) { @@ -2166,9 +2272,11 @@ string (entity pe_target, entity pe_attacker, float pf_deathmsg) GetDeathMessage return strcat(pe_target.netname, s_deathstring); } else if (pf_deathmsg == DMSG_GREN_NAIL) { - - return strcat(pe_target.netname, " hammers himself\n"); - + if (nailgren_type == NGR_TYPE_LASER) { + return strcat(pe_target.netname, " electrocutes himself\n"); + } else { + return strcat(pe_target.netname, " hammers himself\n"); + } } else if (pf_deathmsg == DMSG_GREN_MIRV) { if (pe_target.playerclass == PC_DEMOMAN) @@ -2276,8 +2384,13 @@ string (entity pe_target, entity pe_attacker, float pf_deathmsg) GetDeathMessage } } else if (pf_deathmsg == DMSG_GREN_NAIL) { - s_deathstring = " gets flayed by "; - s_deathstring2 = "'s nail grenade\n"; + if (nailgren_type == NGR_TYPE_LASER) { + s_deathstring = " gets melted by "; + s_deathstring2 = "'s shock grenade\n"; + } else { + s_deathstring = " gets flayed by "; + s_deathstring2 = "'s nail grenade\n"; + } } else if (pf_deathmsg == DMSG_GREN_MIRV) { if (pe_attacker.playerclass == PC_DEMOMAN) { s_deathstring = " does a dance on "; @@ -2704,3 +2817,39 @@ float () GetLastWeaponImpulse = { else return 4; } + +// this is to fix hack used to avoid fall damage, it currently breaks pm_airstep +/* +void() SV_RunClientCommand = { + + local float fdmg; + + runstandardplayerphysics(self); + + if (((self.jump_flag < -300) && (self.flags & 512)) && + (self.health > 0)) { + if (self.watertype == -3) { + sound(self, 4, "player/h2ojump.wav", 1, ATTN_NORM); + } else { + if (self.jump_flag < -650) { + fdmg = 5; + fdmg = (fdmg * (self.jump_flag / 300)) * -1; + if (self.playerclass == 1) { + fdmg = fdmg / 2; + } else { + if (self.playerclass == 6) { + fdmg = fdmg * 1.5; + } + } + fdmg = rint(fdmg); + TF_T_Damage(self, world, world, fdmg, 1, 0); + sound(self, 2, "player/land2.wav", 1, ATTN_NORM); + self.deathtype = "falling"; + } else { + sound(self, 2, "player/land.wav", 1, ATTN_NORM); + } + } + } + self.jump_flag = self.velocity_z; +} +*/ diff --git a/combat.qc b/combat.qc index cf00e88f..eca3f3c0 100644 --- a/combat.qc +++ b/combat.qc @@ -62,7 +62,9 @@ void (entity targ, entity attacker) Killed = { self.health = -99; if ((self.movetype == MOVETYPE_PUSH) || - (self.movetype == MOVETYPE_NONE)) { + //make sure unmovable players like those feigning/building are still given an obituary + //(self.movetype == MOVETYPE_NONE && !self.is_building && !self.is_detpacking && !self.is_feigning)) { + (self.movetype == MOVETYPE_NONE && self.classname != "player")) { self.th_die(); self = oself; diff --git a/commands.qc b/commands.qc index d88b2e45..7b9b1d02 100644 --- a/commands.qc +++ b/commands.qc @@ -1,3 +1,227 @@ +float (string arg1, string arg2) ParseCmds = { + local float arg_num, processedCmd; + local string tmp; + processedCmd = FALSE; + + if (arg1) + arg_num = 1; + if (arg2) + arg_num = 2; + + if (arg1 == "adminpwd") + { + processedCmd = TRUE; + if (arg_num == 2) { + Admin_Check(arg2); + if (self.is_admin) { + Admin_Aliases(); + } + } + if (arg_num == 1) { + sprint(self, PRINT_HIGH, "usage: cmd adminpwd password, where password is the admin password\n"); + sprint(self, PRINT_HIGH, "\n"); + } + return processedCmd; + } + + if (self.is_admin) + { + switch (arg1) + { + case "timelimit": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("timelimit "); + localcmd(arg2); + localcmd("\n"); + } + if (arg_num == 1) { + tmp = infokey(world, arg1); + sprint(self, PRINT_HIGH, "timelimit is "); + sprint(self, PRINT_HIGH, "\""); + sprint(self, PRINT_HIGH, tmp); + sprint(self, PRINT_HIGH, "\"\n"); + } + break; + case "prematch": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("prematch "); + localcmd(arg2); + localcmd("\n"); + } + if (arg_num == 1) { + tmp = infokey(world, arg1); + sprint(self, PRINT_HIGH, "prematch is "); + sprint(self, PRINT_HIGH, "\""); + sprint(self, PRINT_HIGH, tmp); + sprint(self, PRINT_HIGH, "\"\n"); + } + break; + case "fraglimit": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("fraglimit "); + localcmd(arg2); + localcmd("\n"); + } + if (arg_num == 1) { + tmp = infokey(world, arg1); + sprint(self, PRINT_HIGH, "fraglimit is "); + sprint(self, PRINT_HIGH, "\""); + sprint(self, PRINT_HIGH, tmp); + sprint(self, PRINT_HIGH, "\"\n"); + } + break; + case "teamplay": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("teamplay "); + localcmd(arg2); + localcmd("\n"); + } + if (arg_num == 1) { + tmp = infokey(world, arg1); + sprint(self, PRINT_HIGH, "teamplay is "); + sprint(self, PRINT_HIGH, "\""); + sprint(self, PRINT_HIGH, tmp); + sprint(self, PRINT_HIGH, "\"\n"); + } + break; + case "password": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("password "); + if (arg2 == "none") { + bprint(PRINT_HIGH, Q"\n\sServer Password removed!\s\n\n"); + localcmd("\"\""); + } + else { + bprint(PRINT_HIGH, Q"\n\sServer Password changed to \"", arg2, "\"\s\n\n"); + localcmd(arg2); + } + localcmd("\n"); + } + if (arg_num == 1) { + sprint(self, PRINT_HIGH, "usage: cmd password pwd\n"); + sprint(self, PRINT_HIGH, "\n"); + } + break; + case "record": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("record "); + localcmd(arg2); + localcmd("\n"); + } + if (arg_num == 1) { + sprint(self, PRINT_HIGH, "usage: cmd record demo, where demo is the demo name\n"); + sprint(self, PRINT_HIGH, "\n"); + } + break; + case "easyrecord": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("easyrecord "); + localcmd(arg2); + localcmd("\n"); + } + if (arg_num == 1) { + localcmd("easyrecord\n"); + } + break; + case "autorecord": + processedCmd = TRUE; + if (arg_num == 2) { + localcmd("localinfo demo_auto_left "); + localcmd(arg2); + localcmd("\n"); + } + if (arg_num == 1) { + tmp = infokey(world, "demo_auto_left"); + if (stof(tmp) > 0) { + sprint (self, PRINT_HIGH, "Auto-Recording off\n"); + localcmd ("localinfo demo_auto_left 0\n"); + } + else { + sprint(self, PRINT_HIGH, "Auto-Recording the next match\n"); + localcmd("localinfo demo_auto_left 1\n"); + } + } + break; + case "cancel": + localcmd ("cancel\n"); + processedCmd = TRUE; + break; + case "stop": + localcmd ("stop\n"); + processedCmd = TRUE; + break; + case "kick": + Admin_CycleDeal(); + processedCmd = TRUE; + break; + case "ceasefire": + if (ceasefire_type) + Admin_Pause(); + else + Admin_CeaseFire(); + processedCmd = TRUE; + break; + case "map": + processedCmd = TRUE; + if (arg_num == 2) { + bprint(PRINT_HIGH, self.netname); + bprint(PRINT_HIGH, " has changed the map to "); + bprint(PRINT_HIGH, arg2); + bprint(PRINT_HIGH, "\n"); + localcmd("map "); + localcmd(arg2); + localcmd("\n"); + } + else if (arg_num == 1) { + sprint (self, PRINT_HIGH, "usage: cmd map mapname, where mapname is the map name you wish to change to\n"); + sprint (self, PRINT_HIGH, "\n"); + } + break; + case "help": + case "list": + processedCmd = TRUE; + sprint(self, PRINT_HIGH, "Commands list:\n"); + sprint(self, PRINT_HIGH, "cmd adminpwd\n"); + sprint(self, PRINT_HIGH, "cmd timelimit\n"); + sprint(self, PRINT_HIGH, "cmd prematch\n"); + sprint(self, PRINT_HIGH, "cmd fraglimit\n"); + sprint(self, PRINT_HIGH, "cmd teamplay\n"); + sprint(self, PRINT_HIGH, "cmd password\n"); + sprint(self, PRINT_HIGH, "cmd map\n"); + sprint(self, PRINT_HIGH, "cmd record\n"); + sprint(self, PRINT_HIGH, "cmd easyrecord\n"); + sprint(self, PRINT_HIGH, "cmd autorecord\n"); + sprint(self, PRINT_HIGH, "cmd cancel\n"); + sprint(self, PRINT_HIGH, "cmd stop\n"); + sprint(self, PRINT_HIGH, "cmd kick\n"); + sprint(self, PRINT_HIGH, "cmd help || list (this command)\n"); + sprint(self, PRINT_HIGH, "\n"); + break; + } + } + + return processedCmd; +} + +void (string cmd) SV_ParseClientCommand = { + float isProcessed; + tokenize(cmd); + + isProcessed = ParseCmds(argv(0), argv(1)); + + if (!isProcessed) + { + clientcommand(self, cmd); + } +} + void () QuadMode = { localcmd ("localinfo clan on\n"); @@ -8,19 +232,18 @@ void () QuadMode = localcmd ("localinfo round_delay_time 30\n"); localcmd ("localinfo teamfrags on\n"); localcmd ("localinfo fullteamscore off\n"); - localcmd ("password pineapple\n"); localcmd ("fraglimit 0\n"); - localcmd ("exec of_quadmode.cfg\n"); - bprint (2, "Quad Mode set to on\n"); - bprint (2, "Map Restart needed to take effect!\n"); + localcmd ("exec fo_quadmode.cfg\n"); + bprint (PRINT_HIGH, "Quad Mode set to on\n"); + bprint (PRINT_HIGH, "Map Restart needed to take effect!\n"); }; void () ClanMode = { localcmd("localinfo clan on\n"); - localcmd ("exec of_clanmode.cfg\n"); - bprint(2, "Clan Mode set to on\n"); - bprint(2, "Map Restart needed to take effect!\n"); + localcmd ("exec fo_clanmode.cfg\n"); + bprint(PRINT_HIGH, "Clan Mode set to on\n"); + bprint(PRINT_HIGH, "Map Restart needed to take effect!\n"); }; void () PubMode = @@ -34,9 +257,9 @@ void () PubMode = localcmd("timelimit 20\n"); localcmd ("fraglimit 0\n"); localcmd("localinfo round_time 0\n"); - localcmd ("exec of_pubmode.cfg\n"); - bprint(2, "Pub Mode set to on\n"); - bprint(2, "Map Restart needed to take effect!\n"); + localcmd ("exec fo_pubmode.cfg\n"); + bprint(PRINT_HIGH, "Pub Mode set to on\n"); + bprint(PRINT_HIGH, "Map Restart needed to take effect!\n"); } void () DuelMode = @@ -48,7 +271,7 @@ void () DuelMode = localcmd ("password none\n"); localcmd("timelimit 0\n"); localcmd ("fraglimit 30\n"); - localcmd ("exec of_duelmode.cfg\n"); - bprint(2, "Duel Mode set to on\n"); - bprint(2, "Map Restart needed to take effect!\n"); + localcmd ("exec fo_duelmode.cfg\n"); + bprint(PRINT_HIGH, "Duel Mode set to on\n"); + bprint(PRINT_HIGH, "Map Restart needed to take effect!\n"); } \ No newline at end of file diff --git a/defs.h b/defs.h index df00d68a..cb0fc5af 100644 --- a/defs.h +++ b/defs.h @@ -330,6 +330,8 @@ #define ADMIN_MENU_TYPE_QUADMODE 6 #define ADMIN_MENU_TYPE_QUAD_ROUNDNUM 7 #define ADMIN_MENU_TYPE_QUAD_ROUNDTL 8 +#define ADMIN_MENU_TYPE_CLASSES 9 +#define ADMIN_MENU_TYPE_FORCESPEC 10 /*======================================================*/ @@ -474,7 +476,7 @@ #define TF_ADMIN_FORCESTARTMATCH 137 #define TF_ADMIN_READYSTATUS 138 // unused 139 -// unused 140 +#define TF_NAILGREN_INFO 140 // unused 141 // unused 142 // unused 143 @@ -734,6 +736,21 @@ #define GR_TYPE_FLASH 9 #define GR_TYPE_CALTROP 10 +// Defines for NailGren Types +#define NGR_TYPE_DEFAULT 0 +#define NGR_TYPE_LASER 1 +#define NGR_TYPE_BURST 2 + +// NailGren Default Settings +#define NGR_LASER_DEFAULT_ROTATIONCOUNT 2 +#define NGR_LASER_DEFAULT_ROTATIONTIME 1 +#define NGR_LASER_DEFAULT_DAMAGE 20 +#define NGR_LASER_DEFAULT_RANGE 150 + +#define NGR_BURST_DEFAULT_COUNT 2 +#define NGR_BURST_DEFAULT_INTERVAL 0.7 +#define NGR_BURST_DEFAULT_RANGE 0.3 + // Defines for WeaponMode #define GL_NORMAL 0 #define GL_PIPEBOMB 1 diff --git a/defs.qc b/defs.qc index cd19bccf..614b96a9 100644 --- a/defs.qc +++ b/defs.qc @@ -441,7 +441,6 @@ float tod_sec, tod_min, tod_hour, tod_day, tod_mon, tod_year; void(float s, float mi, float h, float d, float mo, float y, string tmp_timeofday) timeofday = { tod_sec = s; tod_min = mi; tod_hour = h; tod_day = d; tod_mon = (mo + 1); tod_year = y; }; -void() setpause = #531; //============================================================================ // diff --git a/doors.qc b/doors.qc index a35b9db5..ad26ffe9 100644 --- a/doors.qc +++ b/doors.qc @@ -1,6 +1,7 @@ void () door_go_down; void () door_go_up; +void (entity pe_player, float dontstopdead) Spy_CheckForFuncTouch; void () door_blocked = { if (other.classname == "detpack") { @@ -41,14 +42,18 @@ void () door_hit_bottom = { self.state = 1; }; -void () door_go_down = { - sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM); +void () door_go_down_silent = { if (self.max_health) { self.takedamage = 1; self.health = self.max_health; } self.state = STATE_DOWN; SUB_CalcMove(self.pos1, self.speed, door_hit_bottom); +} + +void () door_go_down = { + sound(self, CHAN_VOICE, self.noise2, 1, ATTN_NORM); + door_go_down_silent(); }; void () door_go_up = { @@ -151,6 +156,9 @@ void () door_touch = { if (other.classname != "player") return; + + Spy_CheckForFuncTouch(other, 0); + if (self.owner.attack_finished > time) return; @@ -541,6 +549,8 @@ void () secret_touch = { if (other.classname != "player") return; + Spy_CheckForFuncTouch(other, 0); + if (self.attack_finished > time) return; diff --git a/help.qc b/help.qc index c6b27f6b..43b535a6 100644 --- a/help.qc +++ b/help.qc @@ -82,7 +82,7 @@ void () Help_ShowSoldier = { sprint(self, PRINT_HIGH, Q"\s2\s - Equip Super Shotgun\n"); sprint(self, PRINT_HIGH, Q"\s2\s - Equip Shotgun\n"); sprint(self, PRINT_HIGH, Q"\s4\s - Equip Axe\n"); - sprint(self, PRINT_HIGH, Q"\sf\s - Prime/throw Nail Grenade\n"); + sprint(self, PRINT_HIGH, Q"\sf\s - Prime/throw Nail/Shock Grenade\n"); sprint(self, PRINT_HIGH, Q"\smouse2\s - Prime/throw Hand Grenade\n"); }; diff --git a/items.qc b/items.qc index ae1790bd..c0a2b98f 100644 --- a/items.qc +++ b/items.qc @@ -1422,6 +1422,7 @@ void () DropBackpack = { setmodel(newmis, "progs/backpack.mdl"); setsize(newmis, '-16 -16 0', '16 16 56'); newmis.touch = BackpackTouch; + newmis.classname = "backpack"; newmis.nextthink = time + 120; newmis.think = SUB_Remove; diff --git a/locfiles.qc b/locfiles.qc new file mode 100644 index 00000000..0c0ffcfe --- /dev/null +++ b/locfiles.qc @@ -0,0 +1,73 @@ +#pragma target fte + +void loadloc() { + local float i; + local string ln; + local string out; + local float locfilehandle; + + local string path = strcat("locs/", mapname); + path = strcat(path, ".loc"); + locfilehandle = fopen(path, FILE_READ); + if (locfilehandle >= 0) { + ln = fgets(locfilehandle); + while (ln != string_null) { + numlocs++; + ln = fgets(locfilehandle); + } + fclose(locfilehandle); + + locs = memalloc(sizeof(*locs)*numlocs); + + locfilehandle = fopen(path, FILE_READ); + ln = fgets(locfilehandle); + i = 0; + while (ln != string_null && i < numlocs) { + float s1 = strstrofs(ln, " ", 0); + float s2 = strstrofs(ln, " ", s1+1); + float s3 = strstrofs(ln, " ", s2+1); + local string px = substring(ln, 0, s1); + local string py = substring(ln, s1+1, (s2-(s1+1))); + local string pz = substring(ln, s2+1, (s3-(s2+1))); + + locs[i].pos.x = stof(px); + locs[i].pos.y = stof(py); + locs[i].pos.z = stof(pz); + locs[i].desc = substring(ln, s3+1, strlen(ln)-s3+2); + i++; + ln = fgets(locfilehandle); + } + fclose(locfilehandle); + out = strcat("Loaded ", mapname); + out = strcat(out, ".loc with "); + out = strcat(out, ftos(numlocs)); + out = strcat(out, " locations\n"); + } + else { + out = strcat("Couldn't find ", mapname); + out = strcat(out, ".loc\n"); + } + dprint(out); +} + +string getLocationName(vector location) { + local float bestdist; + local string desc; + local float i; + + desc = "someplace"; + location = location * 8; + bestdist = 0; + for (i = 0; i < numlocs; i++) { + float dist = vlen(location - locs[i].pos); + if (bestdist == 0) { + bestdist = dist; + desc = locs[i].desc; + } + else if (dist < bestdist) { + bestdist = dist; + desc = locs[i].desc; + } + } + return desc; +} \ No newline at end of file diff --git a/menu.qc b/menu.qc index 4b23060a..16c13eeb 100644 --- a/menu.qc +++ b/menu.qc @@ -93,6 +93,14 @@ void (float inp) Menu_Dispenser_Input; void () Menu_Admin; void (float inp) Menu_Admin_Input; void () Admin_DoKick; +void () Admin_ForceSpectator; + +void () Admin_Pause; +void () Admin_CeaseFire; +void () Broadcast_Players_NotReady; +void () StartTimer; + +float (string ps_short, string ps_setting, string ps_default) CF_GetSetting; void (entity pl) Menu_Close = { @@ -119,7 +127,8 @@ void (float inp) Menu_Input = var f_void_float tmp; tmp = self.menu_input; self.menu_input = nil; self.impulse = 0; - tmp(inp); + if(tmp) + tmp(inp); Status_Print(self, ""); }; @@ -234,13 +243,13 @@ void (float update) Menu_Team = { void (float inp) Menu_Class_Input = { if (!inp) return; - + override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); // keep showing menu if class is invalid - if (inp > 10 || !IsLegalClass(inp) || CF_ClassIsRestricted(self.team_no, inp)) + if (inp > 10 || (!IsLegalClass(inp) && !override_mapclasses) || CF_ClassIsRestricted(self.team_no, inp)) Menu_Class(0); // don't try to change class if class is forbidden - if (!IsLegalClass(inp) || CF_GetClassRestriction(self.team_no, inp) == -1) + if ((!IsLegalClass(inp) && !override_mapclasses) || CF_GetClassRestriction(self.team_no, inp) == -1) return; // close menu if selected class is current class @@ -267,7 +276,8 @@ string (float pf_class, string ps_class) Menu_Class_ClassString = { local float f_max = CF_GetClassRestriction(self.team_no, pf_class); local float f_players = CF_GetClassPlayers(self.team_no, pf_class); - if (IsLegalClass(pf_class) && f_max >= 0) { + override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); + if ((IsLegalClass(pf_class) || override_mapclasses) && f_max >= 0) { if (f_players < 10) s_string = strpadl(ftos(f_players), (1 + f_gap)); else @@ -1022,6 +1032,7 @@ void () Menu_Admin = { local string s_menu1; local string s_menu2; + local string override; /* More menu lines, commented for the sake of unecessary warnings * local string s_menu3; @@ -1048,7 +1059,7 @@ void () Menu_Admin = case ADMIN_MENU_TYPE_MAIN: s_menu1 = "FortressOne Admin Menu: \n\n"; if (self.current_menu_page == 1) { - s_menu1 = strcat(s_menu1, Q"\s[1]\s Not Used \n"); + s_menu1 = strcat(s_menu1, Q"\s[1]\s Ceasefire \n"); s_menu1 = strcat(s_menu1, Q"\s[2]\s Timelimit \n"); s_menu1 = strcat(s_menu1, Q"\s[3]\s Kick \n"); s_menu1 = strcat(s_menu1, Q"\s[4]\s Ban \n"); @@ -1060,9 +1071,11 @@ void () Menu_Admin = s_menu1 = strcat(s_menu1, Q"\s[2]\s Quad Mode \n"); s_menu1 = strcat(s_menu1, Q"\s[3]\s Pub Mode \n"); s_menu1 = strcat(s_menu1, Q"\s[4]\s Duel Mode (Not implemented) \n"); - s_menu1 = strcat(s_menu1, Q"\s[5]\s \n"); - s_menu1 = strcat(s_menu1, Q"\s[6]\s \n"); - s_menu1 = strcat(s_menu1, Q"\s[7]\s \n"); + s_menu1 = strcat(s_menu1, Q"\s[5]\s Force Spectate \n"); + s_menu1 = strcat(s_menu1, Q"\s[6]\s Ready Status \n"); + s_menu1 = strcat(s_menu1, Q"\s[7]\s Force Match Start (Be Nice) \n"); + } else if (self.current_menu_page == 3) { + s_menu1 = strcat(s_menu1, Q"\s[1]\s Class Settings \n"); } s_menu1 = strcat(s_menu1, "\n\n"); s_menu1 = strcat(s_menu1, Q"\s[8]\s Previous Page \n"); @@ -1111,13 +1124,46 @@ void () Menu_Admin = s_menu1 = strcat(Q"\[\sCaptain\s\] Team ", ftos(self.team_no)); s_menu1 = strcat(s_menu1, " : \n\n"); break; + case ADMIN_MENU_TYPE_CLASSES: + s_menu1 = "Class Management Menu: \n\n"; + //override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); + if(override_mapclasses) { + override = "\x10 on\x11"; + } else { + override = "\x10off\x11"; + } + if (self.current_menu_page == 1) { + s_menu1 = strcat(s_menu1, Q"\s[1]\s Override Map Settings ", override, "\n"); + //s_menu1 = strcat(s_menu1, Q"\s[1]\s Override Map Settings \n"); + //s_menu1 = strcat(s_menu1, Q"\s[2]\s Scout \n"); + //s_menu1 = strcat(s_menu1, Q"\s[3]\s Sniper \n"); + //s_menu1 = strcat(s_menu1, Q"\s[4]\s Soldier \n"); + //s_menu1 = strcat(s_menu1, Q"\s[5]\s Demoman \n"); + //s_menu1 = strcat(s_menu1, Q"\s[6]\s Medic \n"); + //s_menu1 = strcat(s_menu1, Q"\s[7]\s Heavy \n"); + } else if (self.current_menu_page == 2) { + //s_menu1 = strcat(s_menu1, Q"\s[1]\s Pyro \n"); + //s_menu1 = strcat(s_menu1, Q"\s[2]\s Spy \n"); + //s_menu1 = strcat(s_menu1, Q"\s[3]\s Engineer \n"); + //s_menu1 = strcat(s_menu1, Q"\s[4]\s RandomPC \n"); + //s_menu1 = strcat(s_menu1, Q"\s[5]\s \n"); + //s_menu1 = strcat(s_menu1, Q"\s[6]\s \n"); + //s_menu1 = strcat(s_menu1, Q"\s[7]\s \n"); + } + s_menu1 = strcat(s_menu1, "\n\n"); + s_menu1 = strcat(s_menu1, Q"\s[8]\s Previous Page \n"); + s_menu1 = strcat(s_menu1, Q"\s[9]\s Next Page \n"); + s_menu1 = strcat(s_menu1, Q"\s[0]\s Exit Menu \n"); + + Status_Menu(self, Menu_Admin_Input, s_menu1); + break; } // jesus christ what is this, this should be separated out for the good of the people // or maybe made understandable if (self.current_menu_type == ADMIN_MENU_TYPE_KICK || self.current_menu_type == ADMIN_MENU_TYPE_BAN || self.current_menu_type == ADMIN_MENU_TYPE_CAPTAINTEAMONE || self.current_menu_type == ADMIN_MENU_TYPE_CAPTAINTEAMTWO - || self.current_menu_type == ADMIN_MENU_TYPE_CAPTAINSELECT) + || self.current_menu_type == ADMIN_MENU_TYPE_CAPTAINSELECT || self.current_menu_type == ADMIN_MENU_TYPE_FORCESPEC) { f_tmp = 0; f_tmp2 = 0; @@ -1151,7 +1197,7 @@ void () Menu_Admin = te = find (te, classname, "player"); } - if (self.current_menu_type != ADMIN_MENU_TYPE_CAPTAINTEAMONE && self.current_menu_type != ADMIN_MENU_TYPE_CAPTAINTEAMTWO && self.current_menu_type != ADMIN_MENU_TYPE_CAPTAINSELECT ) { + if (self.current_menu_type != ADMIN_MENU_TYPE_CAPTAINTEAMONE && self.current_menu_type != ADMIN_MENU_TYPE_CAPTAINTEAMTWO && self.current_menu_type != ADMIN_MENU_TYPE_CAPTAINSELECT && self.current_menu_type != ADMIN_MENU_TYPE_FORCESPEC ) { te = find (world, classname, "observer"); while (te != world) { if ( (f_tmp <= (self.current_menu_page * 7) ) && (f_tmp > (self.current_menu_page - 1) * 7) && te.netname != "") { @@ -1226,7 +1272,11 @@ void (float inp) Menu_Admin_Input = { switch (inp) { - case 1: // Unused + case 1: // Ceasefire + if (ceasefire_type) + Admin_Pause(); + else + Admin_CeaseFire(); return; case 2: // Change Timelimit if (stof(infokey (world, "timelimit")) > 35) { @@ -1332,12 +1382,41 @@ void (float inp) Menu_Admin_Input = self.current_menu_type = ADMIN_MENU_TYPE_MAIN; self.current_menu_page = 1; break; + case 5: // force spectator + self.current_menu_type = ADMIN_MENU_TYPE_FORCESPEC; + self.current_menu_page = 1; + Menu_Admin(); + break; + case 6: // ready status + Broadcast_Players_NotReady(); + Menu_Close(self); + return; + case 7: // force match start + if (clanbattle == 1 && cb_prematch == 1) { + bprint(PRINT_HIGH, self.netname); + bprint(PRINT_HIGH, " has forced the match start.\n"); + StartTimer(); + } + Menu_Close(self); + return; + } + } + else if (self.current_menu_page == 3) + { + switch (inp) + { + case 1: + self.current_menu_type = ADMIN_MENU_TYPE_CLASSES; + self.current_menu_page = 1; + Menu_Admin(); + return; } } } - else if ((self.current_menu_type == ADMIN_MENU_TYPE_KICK || self.current_menu_type == ADMIN_MENU_TYPE_BAN ) + else if ((self.current_menu_type == ADMIN_MENU_TYPE_KICK || self.current_menu_type == ADMIN_MENU_TYPE_BAN || self.current_menu_type == ADMIN_MENU_TYPE_FORCESPEC) && inp >= 1 && inp <= 7) { // Kick / Ban Actions + bprint(PRINT_HIGH, "Getting player ", ftos(inp), "\n"); f_tmp = 1; self.admin_use = find (world, classname, "player"); while (self.admin_use != world) { @@ -1360,14 +1439,20 @@ void (float inp) Menu_Admin_Input = } } if (self.admin_use) { + bprint(PRINT_HIGH, "Player found: ", ftos(f_tmp), ", ", ftos(((self.current_menu_page - 1) * 7) + inp),", ", self.admin_use.classname , "\n"); if (f_tmp == ((self.current_menu_page - 1) * 7) + inp) { - self.admin_use.ip = infokey (self.admin_use, "ip"); - if (self.current_menu_type == ADMIN_MENU_TYPE_BAN) { - localcmd("addip "); - localcmd(self.admin_use.ip); - localcmd("\n"); + if(self.current_menu_type == ADMIN_MENU_TYPE_FORCESPEC) { + Admin_ForceSpectator(); + Menu_Close(self); + } else { + self.admin_use.ip = infokey (self.admin_use, "ip"); + if (self.current_menu_type == ADMIN_MENU_TYPE_BAN) { + localcmd("addip "); + localcmd(self.admin_use.ip); + localcmd("\n"); + } + Admin_DoKick(); } - Admin_DoKick(); } } } @@ -1497,6 +1582,24 @@ void (float inp) Menu_Admin_Input = self.current_menu_page = 1; Menu_Admin(); } + else if (self.current_menu_type == ADMIN_MENU_TYPE_CLASSES) + { + if (self.current_menu_page == 1) + { + override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); + switch (inp) + { + case 1: + override_mapclasses = !override_mapclasses; + localcmd("serverinfo omc "); + localcmd(ftos(override_mapclasses)); + localcmd("\n"); + bprint(PRINT_HIGH, self.netname, " has set server class overrides to ", ftos(override_mapclasses), "\n"); + Menu_Admin(); + return; + } + } + } //Previous page if (inp == 8) { @@ -1544,4 +1647,4 @@ void (float inp) Menu_Admin_Input = } } self.impulse = 0; -}; \ No newline at end of file +}; diff --git a/misc.qc b/misc.qc index 1d370301..8e78724b 100644 --- a/misc.qc +++ b/misc.qc @@ -609,3 +609,203 @@ void () misc_noisemaker = { self.nextthink = time + 0.1 + random(); self.think = noise_think; }; + +void() blocker_use = +{ + if (!(self.state)) + { + self.state = 1; + setorigin(self, self.origin - '8000 8000 8000'); + sound(self, 2, self.noise1, 1, 1); + } + else + { + self.state = 0; + setorigin(self, self.origin + '8000 8000 8000'); + sound(self, 2, self.noise, 1, 1); + } +}; + +void(entity attacker, float damage) glass_pain = +{ + if (self.spawnflags & 8) + { + self.health = self.max_health; + } +}; + +void() glass_die = +{ + local entity new; + local vector tmpvec; + while (self.cnt2 > 0) + { + new = spawn(); + new.origin = self.origin; + if (random() < 0.5) + { + setmodel(new, "progs/glass2.mdl"); + } + else + { + setmodel(new, "progs/glass1.mdl"); + } + setsize(new, '0 0 0', '0 0 0'); + if (self.height != 100) + { + new.velocity_x = 70 * crandom(); + new.velocity_y = 70 * crandom(); + new.velocity_z = 140 + 70 * random(); + } + else + { + new.velocity_x = 400 * crandom(); + new.velocity_y = 400 * crandom(); + new.velocity_z = 140 + 70 * random(); + } + new.movetype = 10; + new.solid = 2; + new.avelocity_x = random() * 600; + new.avelocity_y = random() * 600; + new.avelocity_z = random() * 600; + new.nextthink = time + 2 + random() * 3; + new.think = SUB_Remove; + self.absmin = self.origin + self.mins; + self.absmax = self.origin + self.maxs; + tmpvec_x = self.absmin_x + random() * (self.absmax_x - self.absmin_x); + tmpvec_y = self.absmin_y + random() * (self.absmax_y - self.absmin_y); + tmpvec_z = self.absmin_z + random() * (self.absmax_z - self.absmin_z); + setorigin(new, tmpvec); + self.cnt2 = self.cnt2 - 1; + } + if (self.noise2) + { + if (pointcontents(self.origin) == -3) + { + sound(self, 2, "effects/rcksplsh.wav", 1, 1); + } + else + { + sound(self, 2, self.noise2, 1, 1); + } + } + remove(self); +}; + +void() func_glass = +{ + local vector tmpvec; + self.movetype = 7; + self.solid = 4; + self.mdl = self.model; + setmodel(self, self.model); + setsize(self, self.mins, self.maxs); + setorigin(self, self.origin); + self.model = string_null; + precache_sound("misc/null.wav"); + precache_sound("effects/rcksplsh.wav"); + precache_sound("effects/shatter.wav"); + precache_model("progs/glass2.mdl"); + precache_model("progs/glass1.mdl"); + + if (self.health > 0) + { + if (!(self.cnt2)) + { + tmpvec = self.maxs - self.mins; + tmpvec = tmpvec * 0.031; + if (tmpvec_x < 1) + { + tmpvec_x = 1; + } + if (tmpvec_y < 1) + { + tmpvec_y = 1; + } + if (tmpvec_z < 1) + { + tmpvec_z = 1; + } + self.cnt2 = tmpvec_x * tmpvec_y * tmpvec_z; + } + else + { + if (self.cnt2 == -1) + { + self.cnt2 = 0; + } + } + if (self.cnt2 > 16) + { + self.cnt2 = 16; + } + self.takedamage = 1; + self.max_health = self.health; + self.th_die = glass_die; + self.th_pain = glass_pain; + precache_model("progs/glass1.mdl"); + precache_model("progs/glass2.mdl"); + } + if (self.target) + { + if (!(self.speed)) + { + self.speed = 100; + } + if (!(self.dmg)) + { + self.dmg = 2; + } + if (self.sounds == 1) + { + if (!(self.noise)) + { + self.noise = "plats/train2.wav"; + } + if (!(self.noise1)) + { + self.noise1 = "plats/train1.wav"; + } + precache_sound(self.noise); + precache_sound(self.noise1); + } + self.cnt = 1; + self.blocked = train_blocked; + self.use = train_use; + self.classname = "train"; + self.think = func_train_find; + self.nextthink = self.ltime + 0.6; + } + else + { + self.use = blocker_use; + if (self.spawnflags & 4) + { + self.state = 0; + setorigin(self, self.origin + '8000 8000 8000'); + } + else + { + self.state = 1; + if (self.noise1) + { + sound(self, 2, self.noise1, 1, 1); + } + } + } + if (!(self.noise)) + { + self.noise = "misc/null.wav"; + } + if (!(self.noise1)) + { + self.noise1 = "misc/null.wav"; + } + if (!(self.noise2)) + { + self.noise2 = "effects/shatter.wav"; + } + precache_sound(self.noise); + precache_sound(self.noise1); + precache_sound(self.noise2); +}; diff --git a/mvdsv.qc b/mvdsv.qc index ef7f62ca..b78593ef 100644 --- a/mvdsv.qc +++ b/mvdsv.qc @@ -1,226 +1,12 @@ float () UserCmd = { - local float arg_num; - local string tmp; + float isProcessed; + string arg1, arg2; + arg1 = argv_mvdsv(0); + arg2 = argv_mvdsv(1); - arg_num = argc(); - if (arg_num == 0) { - return (0); - } - if (argv_mvdsv(0) == "adminpwd") { - if (arg_num == 2) { - if (self.is_admin) { - sprint(self, 2, "You are already an admin\n"); - return (1); - } - Admin_Check(argv_mvdsv(1)); - if (self.is_admin) { - Admin_Aliases(); - } - return (1); - } - if (arg_num == 1) { - sprint(self, 2, "usage: cmd adminpwd password, where password is the admin password\n"); - sprint(self, 2, "\n"); - return (1); - } - } - if (self.is_admin) { - //Adminpwd commands - if (argv_mvdsv(0) == "timelimit") { - if (arg_num == 2) { - localcmd("timelimit "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - tmp = infokey(world, argv_mvdsv(0)); - sprint(self, 2, "timelimit is "); - sprint(self, 2, "\""); - sprint(self, 2, tmp); - sprint(self, 2, "\"\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "prematch") { - if (arg_num == 2) { - localcmd("prematch "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - tmp = infokey(world, argv_mvdsv(0)); - sprint(self, 2, "prematch is "); - sprint(self, 2, "\""); - sprint(self, 2, tmp); - sprint(self, 2, "\"\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "fraglimit") { - if (arg_num == 2) { - localcmd("fraglimit "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - tmp = infokey(world, argv_mvdsv(0)); - sprint(self, 2, "fraglimit is "); - sprint(self, 2, "\""); - sprint(self, 2, tmp); - sprint(self, 2, "\"\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "teamplay") { - if (arg_num == 2) { - localcmd("teamplay "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - tmp = infokey(world, argv_mvdsv(0)); - sprint(self, 2, "teamplay is "); - sprint(self, 2, "\""); - sprint(self, 2, tmp); - sprint(self, 2, "\"\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "password") { - if (arg_num == 2) { - localcmd("password "); - if (argv_mvdsv(1) == "none") { - localcmd("\"\""); - } - else { - localcmd(argv_mvdsv(1)); - } - localcmd("\n"); - bprint("\n"); - argv_mvdsv(1); - if (argv_mvdsv(1) == "none") { - bprint(2, Q"\sServer Password removed!\s\n"); - } - else { - bprint3(2, Q"\sServer Password changed to \"", argv_mvdsv(1), "\"\s\n"); - } - bprint("\n"); - return (1); - } - if (arg_num == 1) { - sprint(self, 2, "usage: cmd password pwd\n"); - sprint(self, 2, "\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "record") { - if (arg_num == 2) { - localcmd("record "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - sprint(self, 2, "usage: cmd record demo, where demo is the demo name\n"); - sprint(self, 2, "\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "easyrecord") { - if (arg_num == 2) { - localcmd("easyrecord "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - localcmd("easyrecord\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "autorecord") { - if (arg_num == 2) { - localcmd("localinfo demo_auto_left "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - tmp = infokey(world, "demo_auto_left"); - if (stof(tmp) > 0) { - dprint ("Auto-Recording off\n"); - localcmd ("localinfo demo_auto_left 0\n"); - return (1); - } - else { - dprint("Auto-Recording the next match\n"); - localcmd("localinfo demo_auto_left 1\n"); - return (1); - } - } - } - else if (argv_mvdsv(0) == "cancel") { - localcmd ("cancel\n"); - return (1); - } - else if (argv_mvdsv(0) == "stop") { - localcmd ("stop\n"); - return (1); - } - else if (argv_mvdsv(0) == "kick") { - Admin_CycleDeal(); - return (1); - } - else if (argv_mvdsv(0) == "map") { - if (self.is_admin) { - if (clanbattle == 1 && !(cb_prematch)) { - sprint(self, 2, "Clan Battle in progress....\n"); - self.impulse = 0; - return (1); - } - } - if (arg_num == 2) { - bprint(2, self.netname); - bprint(2, " Has changed the map to "); - bprint(2, argv_mvdsv(1)); - bprint(2, "\n"); - localcmd("map "); - localcmd(argv_mvdsv(1)); - localcmd("\n"); - return (1); - } - if (arg_num == 1) { - sprint (self, 2, "usage: cmd map mapname, where mapname is the map name you wish to change to\n"); - sprint (self, 2, "\n"); - return (1); - } - } - else if (argv_mvdsv(0) == "help" || argv_mvdsv(0) == "list") { - sprint(self, 2, "Commands list:\n"); - sprint(self, 2, "cmd adminpwd\n"); - sprint(self, 2, "cmd timelimit\n"); - sprint(self, 2, "cmd prematch\n"); - sprint(self, 2, "cmd fraglimit\n"); - sprint(self, 2, "cmd teamplay\n"); - sprint(self, 2, "cmd password\n"); - sprint(self, 2, "cmd map\n"); - sprint(self, 2, "cmd record\n"); - sprint(self, 2, "cmd easyrecord\n"); - sprint(self, 2, "cmd autorecord\n"); - sprint(self, 2, "cmd cancel\n"); - sprint(self, 2, "cmd stop\n"); - sprint(self, 2, "cmd kick\n"); - sprint(self, 2, "cmd help || list (this command)\n"); - sprint(self, 2, "\n"); - return (1); - } - } - return 0; + isProcessed = ParseCmds(arg1, arg2); + return (isProcessed); }; float () ConsoleCmd { @@ -280,4 +66,71 @@ float () ConsoleCmd { return (1); } return 0; +} + +void (float duration) GE_PausedTic = { + local entity p; + if (unpause_requested && (unpause_countdown == 0)) { + unpause_countdown = duration + 5; + } + if (unpause_requested) { + if ((duration >= unpause_countdown)) { + is_paused = 0; + unpause_countdown = 0; + unpause_requested = 0; + unpause_lastcountnumber = 0; + setpause(0); + } + else { + if (duration >= (unpause_countdown - 4) && (unpause_lastcountnumber == 0)) { + unpause_lastcountnumber = 4; + p = find (world, classname, "player"); + while (p) { + if (p.netname != "") { + stuffcmd(p, "play buttons/switch04.wav\n"); + } + p = find(p, classname, "player"); + } + bprint(PRINT_HIGH, "Unpausing in 4 seconds\n" ); + + } + else if (duration >= (unpause_countdown - 3) && (unpause_lastcountnumber == 4)) { + unpause_lastcountnumber = 3; + p = find (world, classname, "player"); + while (p) { + if (p.netname != "") { + stuffcmd(p, "play buttons/switch04.wav\n"); + } + p = find(p, classname, "player"); + } + bprint(PRINT_HIGH, "Unpausing in 3 seconds\n" ); + } + else if (duration >= (unpause_countdown - 2) && (unpause_lastcountnumber == 3)) { + unpause_lastcountnumber = 2; + p = find (world, classname, "player"); + while (p) { + if (p.netname != "") { + stuffcmd(p, "play buttons/switch04.wav\n"); + } + p = find(p, classname, "player"); + } + bprint(PRINT_HIGH, "Unpausing in 2 seconds\n" ); + } + else if (duration >= (unpause_countdown - 1) && (unpause_lastcountnumber == 2)) { + unpause_lastcountnumber = 1; + p = find (world, classname, "player"); + while (p) { + if (p.netname != "") { + stuffcmd(p, "play buttons/switch04.wav\n"); + } + p = find(p, classname, "player"); + } + bprint(PRINT_HIGH, "Unpausing in 1 second\n" ); + } + } + } +} + +void(float pauseduration) SV_PausedTic = { + GE_PausedTic(pauseduration); } \ No newline at end of file diff --git a/plats.qc b/plats.qc index db586023..83636b46 100644 --- a/plats.qc +++ b/plats.qc @@ -5,6 +5,7 @@ void () plat_trigger_use; void () plat_go_up; void () plat_go_down; void () plat_crush; +void (entity pe_player, float dontstopdead) Spy_CheckForFuncTouch; void () plat_spawn_inside_trigger = { local entity trigger; @@ -83,6 +84,8 @@ void () plat_center_touch = { if (other.playerclass == 0) return; + Spy_CheckForFuncTouch(other, 1); + if (!Activated(self, other)) { if (self.else_goal != 0) { te = Findgoal(self.else_goal); @@ -108,6 +111,8 @@ void () plat_outside_touch = { if (other.classname != "player") return; + Spy_CheckForFuncTouch(other, 0); + if (!Activated(self, other)) { if (self.else_goal != 0) { te = Findgoal(self.else_goal); diff --git a/progs.src b/progs.src index b9f9f7b0..d6933ca5 100644 --- a/progs.src +++ b/progs.src @@ -12,6 +12,7 @@ help.qc subs.qc combat.qc items.qc +locfiles.qc weapons.qc world.qc client.qc diff --git a/quadmode.qc b/quadmode.qc index 4f48ecf7..4a4d7256 100644 --- a/quadmode.qc +++ b/quadmode.qc @@ -8,7 +8,7 @@ float () CheckWinningTeam = { win_score = team1score; winning_team = 1; } - + if (team2score > win_score) { win_score = team2score; winning_team = 2; @@ -57,7 +57,7 @@ void () QuadRoundThink = { } if (self.cnt == -1) - return; + return; if ( self.cnt == stof(infokey(world, "round_time")) - 1 && self.cnt2 == 59 ) { localcmd("serverinfo status \""); @@ -75,17 +75,17 @@ void () QuadRoundThink = { if (self.cnt2 == -1) { self.cnt2 = 59; - self.cnt = (self.cnt - 1); + self.cnt = (self.cnt - 1); } if (!cease_fire) self.cnt2 = (self.cnt2 - 1); - + if (!self.cnt2) { if ((self.cnt == 1) || (self.cnt == 5)) { tmp = ftos (self.cnt); bprint3(2, "\s[\s", tmp, "\s]\s minute"); - if (self.cnt != 1) + if (self.cnt != 1) bprint(2, "s"); bprint(2, " remaining\n"); } @@ -96,7 +96,7 @@ void () QuadRoundThink = { st = infokey(world, "round_delay_time"); bprint(2, "ROUND TIME OVER\nNext round begins in ", st, " seconds\n"); } - + // lightstyle (0, "e"); @@ -111,7 +111,7 @@ void () QuadRoundThink = { tmp = ftos(self.cnt2); bprint3(2, "\s[\s", tmp, "\s]\s second"); if ((self.cnt2 != 1)) - bprint(2, "s"); + bprint(2, "s"); bprint(2, " remaining\n"); } } @@ -152,12 +152,12 @@ void () QuadRoundBegin = { round_active = 1; round_over = 0; if (!self.cnt) { - self.cnt = stof(infokey (world, "round_time")) - 1; + self.cnt = stof(infokey (world, "round_time")) - 1; self.cnt2 = 60; } else { counter = floor(self.cnt); - if (counter < self.cnt) + if (counter < self.cnt) self.cnt2 = ((self.cnt - counter) * 60); else self.cnt2 = 60; @@ -190,6 +190,7 @@ void () QuadRoundInit = { round_over = 2; else { if (!self.cnt2) { + localcmd("serverinfo status \"0 min left\"\n"); self.nextthink = (time + 0.1); self.think = QuadRoundBegin; p = find(world, classname, "player"); @@ -210,7 +211,7 @@ void () QuadRoundInit = { while (p) { if (p.netname != "") { CenterPrint3(p, "Round begins in: ", num, " second(s).\nEnsure correct class is chosen!\n"); - + if (self.cnt2 <= 5) { cease_fire = 0; @@ -286,7 +287,8 @@ void () StartQuadRound = while (te != world) { te2 = self; self = te; - door_go_down(); + //door_go_down(); + door_go_down_silent(); self.think = LinkDoors; self = te2; te = find(te, classname, "door"); @@ -346,6 +348,18 @@ void () StartQuadRound = dremove(te); te = find (te, classname, "detpack"); } + te = find(world, classname, "backpack"); + while (te) { + te.think = SUB_Remove; + te.nextthink = (time + 0.1); + te = find(te, classname, "backpack"); + } + te = find(world, classname, "ammobox"); + while (te) { + te.think = SUB_Remove; + te.nextthink = (time + 0.1); + te = find(te, classname, "ammobox"); + } te = find(world, classname, "round"); st = infokey(world, "count"); @@ -368,7 +382,7 @@ void () StartQuadRound = } else { te.think = QuadRoundInit; - te.nextthink = (time + 1); + te.nextthink = (time + 1); } }; @@ -388,4 +402,4 @@ void () EndQuadRound = { } } } -}; \ No newline at end of file +}; diff --git a/qw.qc b/qw.qc index 4d09e3ac..0b6d06e4 100644 --- a/qw.qc +++ b/qw.qc @@ -332,6 +332,7 @@ float item_list_bit; // Global, used to determine what the bit of .float delay_time; // For delayed goal results .float dont_do_triggerwork; +.float track_goal; // Track this info_goal in the statusbar // Abbreviations for the above .float g_a; // goal_activation @@ -446,6 +447,19 @@ float is_countdown; float exec_map_cfgs; float spy_off; + +float nailgren_type; +float lasergren_rotationcount; +float lasergren_rotationtime; +float lasergren_thinktime; +float lasergren_range; +float lasergren_damage; +float lasergren_reqthinks; +float lasergren_angleperthink; +float burstgren_count; +float burstgren_interval; +float burstgren_range; + float old_grens; float invis_only; float flagem_checked; @@ -454,6 +468,24 @@ float drop_grenades; float drop_grenpack; float drop_gren1; float drop_gren2; +float max_gren1_scout; +float max_gren1_sniper; +float max_gren1_soldier; +float max_gren1_demoman; +float max_gren1_medic; +float max_gren1_hwguy; +float max_gren1_pyro; +float max_gren1_spy; +float max_gren1_engineer; +float max_gren2_scout; +float max_gren2_sniper; +float max_gren2_soldier; +float max_gren2_demoman; +float max_gren2_medic; +float max_gren2_hwguy; +float max_gren2_pyro; +float max_gren2_spy; +float max_gren2_engineer; float grentimers; float id_extended; float remember_weapon; @@ -484,6 +516,7 @@ float sniperreload; float spawnfull; float stockfull; float stock_on_cap; +float stock_reload; float classtips; float cussgrentime; float medicnocuss; @@ -504,6 +537,19 @@ float sng_damage; float old_ng_rof; float impulse_queue; float pyro_type; +float flag_follow; +float ceasefire_type; +float is_paused; +string pause_actor; +float unpause_requested; +float unpause_countdown; +float unpause_lastcountnumber; +float chweap_wait_attfinished; +float override_mapclasses; + +float numlocs; +typedef struct {vector pos; string desc;} loc_t; +loc_t *locs; .float teamkills; @@ -578,4 +624,4 @@ string (string s, float width) strpadr = }; float captainmode; -.float captain; \ No newline at end of file +.float captain; diff --git a/scout.qc b/scout.qc index ff743084..bc13245d 100644 --- a/scout.qc +++ b/scout.qc @@ -24,17 +24,11 @@ void () CF_Scout_Dash = { if (!scoutdash || time < self.dash_cooldown) return; - // don't dash if scout is concussed or have damaged legs - if (self.leg_damage || self.is_concussed) - return; - - // only dash if walking or slower - if (vlen(self.velocity) <= 450 && (self.flags & FL_ONGROUND)) { + self.dash_cooldown = time + 1; makevectors(self.angles); self.velocity = v_forward * 540; self.velocity_z = 181; sound(self, CHAN_BODY, "dash.wav", 1, ATTN_NORM); - } } void () CanisterTouch = diff --git a/spect.qc b/spect.qc index 40eac69d..8e2b9539 100644 --- a/spect.qc +++ b/spect.qc @@ -96,7 +96,23 @@ void () SpectatorImpulseCommand = { Admin_CycleDeal(); else if (self.impulse == TF_ADMIN_LISTIPS) Admin_ListIPs(); - + else if (self.impulse == TF_ADMIN_CLANMODE) + ClanMode(); + else if (self.impulse == TF_ADMIN_QUADMODE) + QuadMode(); + else if (self.impulse == TF_ADMIN_ADMINMENU) { + self.current_menu_page = 1; + Menu_Admin(); + } + else if (self.impulse == TF_ADMIN_FORCESTARTMATCH) + StartTimer(); + else if (self.impulse == TF_ADMIN_READYSTATUS) + Broadcast_Players_NotReady(); + + else if (self.impulse > 0 && self.impulse <= 10) { + Menu_Input(self.impulse); + } + self.impulse = 0; }; diff --git a/spy.qc b/spy.qc index 491b9cbe..35758771 100644 --- a/spy.qc +++ b/spy.qc @@ -372,29 +372,58 @@ float (entity pe_player) Spy_CheckArea = { return 0; }; +void (entity pe_player, float dontstopdead) Spy_CheckForFuncTouch = { + if (pe_player.classname == "player" && pe_player.playerclass == PC_SPY) { + if(pe_player.is_feigning) { + pe_player.velocity_x = 0; + pe_player.velocity_y = 0; + pe_player.movetype = MOVETYPE_TOSS; + //This is needed for plats that have a virtual presence and this causes you to fall slowly when inside it + if(!dontstopdead) { + pe_player.tfstate = pe_player.tfstate | TFSTATE_CANT_MOVE; + TeamFortress_SetSpeed(pe_player); + } + } + } +}; + void () CF_Spy_AirThink = { local float area_check = 0; - if ((self.owner.deadflag >= 2) || (self.owner.playerclass != PC_SPY) || (!self.owner.is_feigning)) { + if(self.owner.deadflag >= 2) { + // reset the movetype just in case you die while in the TOSS or the WALK states (eg mbasesr lift squish) + self.owner.movetype = MOVETYPE_NONE; + self.owner.tfstate = self.owner.tfstate | TFSTATE_CANT_MOVE; + dremove(self); + return; + } + if ((self.owner.playerclass != PC_SPY) || (!self.owner.is_feigning)) { dremove(self); return; } // only do stuff when spy is no longer moving if (!self.owner.velocity) { - // if spy is on ground and an entity is not nearby, set movetype to none (so he can't move) if (self.owner.flags & FL_ONGROUND) { area_check = Spy_CheckArea(self.owner); if (area_check == 0) { - self.owner.movetype = MOVETYPE_NONE; + //This checks if something is trying to squish you, fixing some situations where the door or whatever would just go through you. + traceline(self.owner.origin, self.owner.origin, 0, self.owner); + if(trace_ent) { + if(trace_ent.classname == "door" || trace_ent.classname == "plat" || trace_ent.classname == "train") { + self.owner.movetype = MOVETYPE_TOSS; + } + } else { + self.owner.movetype = MOVETYPE_NONE; + } self.owner.tfstate = self.owner.tfstate | TFSTATE_CANT_MOVE; } } - // if spy is in the air, set movetype to walk (so he falls to ground) + // if spy is in the air, set movetype to walk^H^H^H^H toss (so he falls to ground) else { - self.owner.movetype = MOVETYPE_WALK; + self.owner.movetype = MOVETYPE_TOSS; } TeamFortress_SetSpeed(self.owner); @@ -679,17 +708,17 @@ void (entity own) Spy_SetClientSkins = { entity te; string color, dcolor, skin, dskin, sendcolor, sendskin; float dteam, dpc; - + dteam = own.undercover_team == 0 ? own.team_no : own.undercover_team; dpc = own.undercover_skin == 0 ? own.playerclass : own.undercover_skin; color = ftos(TeamFortress_TeamGetColor(own.team_no) - 1); dcolor = ftos(TeamFortress_TeamGetColor(dteam) - 1); - + skin = TeamFortress_GetSkin(own.team_no, own.playerclass); dskin = TeamFortress_GetSkin(dteam, dpc); te = find(world, classname, "player"); - while (te) + while (te) { if (te.team_no) { @@ -702,9 +731,9 @@ void (entity own) Spy_SetClientSkins = { else // not on same team, send them disguise { sendcolor = dcolor; - sendskin = dskin; + sendskin = dskin; } - + msg_entity = te; // set skin @@ -718,14 +747,14 @@ void (entity own) Spy_SetClientSkins = { WriteByte(MSG_ONE, own.colormap-1); WriteString(MSG_ONE, "topcolor"); WriteString(MSG_ONE, sendcolor); - + // set bottom colour / color WriteByte(MSG_ONE, SVC_SETINFO); WriteByte(MSG_ONE, own.colormap-1); WriteString(MSG_ONE, "bottomcolor"); WriteString(MSG_ONE, sendcolor); } - + te = find(te, classname, "player"); } } @@ -767,7 +796,7 @@ void () CF_Spy_UndercoverThink = { self.owner.queue_skin = 0; self.owner.is_undercover = 1; TeamFortress_SetSkin(self.owner); - + if (self.owner.queue_team) { CF_Spy_ChangeColor(self.owner, self.owner.queue_team); } else { @@ -781,7 +810,7 @@ void () CF_Spy_UndercoverThink = { s_class = "Spy"; sprint(self.owner, PRINT_HIGH, "Disguised as ", s_team, " ", s_class, "\n"); } - + } else if (self.team) { self.owner.undercover_team = self.team; self.owner.last_team = self.team; @@ -800,7 +829,7 @@ void () CF_Spy_UndercoverThink = { sprint(self.owner, PRINT_HIGH, "Disguised as ", s_team, " ", s_class, "\n"); } } - + TeamFortress_SpyCalcName(self.owner); } @@ -808,7 +837,7 @@ void () CF_Spy_UndercoverThink = { Status_Refresh(self.owner); if (self.owner.menu_input == Menu_Spy_Input) Menu_Spy(self.owner); - + dremove(self); }; @@ -1408,7 +1437,8 @@ void () Spy_DropBackpack = { setmodel(newmis, "progs/backpack.mdl"); setsize(newmis, '-16 -16 0', '16 16 56'); newmis.touch = BackpackTouch; + newmis.classname = "backpack"; newmis.nextthink = time + 120; newmis.think = SUB_Remove; -}; \ No newline at end of file +}; diff --git a/status.qc b/status.qc index f302702a..b2cd87d6 100644 --- a/status.qc +++ b/status.qc @@ -19,6 +19,11 @@ string(entity pl) DisguiseToString; string(entity pl) SentryDetailsToString; string(entity pl) BuildingToString; string(float pc) TeamFortress_GetClassName; +entity(float ino) Finditem; +void () tfgoalitem_droptouch; +void () tfgoalitem_dropthink; +void () tfgoalitem_remove; +float (entity ent, string ps_short, string ps_setting, string ps_default) FO_GetUserSetting; string (float class) CF_GetRandomClassTip { local string tiptype = ""; @@ -232,7 +237,11 @@ string (float class) CF_GetRandomClassTip { line1 = "Use the super shotgun (2) at very close"; line2 = "range to avoid splash damage."; } else if (self.display_tip == 7) { - line1 = "Use a nail grenade (f) to clear a small"; + if (nailgren_type == NGR_TYPE_LASER) { + line1 = "Use a shock grenade (f) to clear a small"; + } else { + line1 = "Use a nail grenade (f) to clear a small"; + } line2 = "room or block a bottle neck."; } } @@ -561,6 +570,63 @@ void (entity pl, string s1, string s2, string s3) CenterPrint3 = { Status_Print(pl, s1, s2, s3); }; +void (entity pl, string s1, string s2, string s3, string s4) CenterPrint4 = { + Status_Print(pl, s1, s2, s3, s4); +}; + +void (entity pl, string s1, string s2, string s3, string s4, string s5) CenterPrint5 = { + Status_Print(pl, s1, s2, s3, s4, s5); +}; + +string getLocationName(vector location); + +string (entity Player, entity Item, float teamno) GetItemStatus = { + local string st; + switch (teamno) + { + case 1: + st = "Blue Flag"; + break; + case 2: + st = "Red Flag"; + break; + case 3: + st = "Yellow Flag"; + break; + case 4: + st = "Green Flag"; + break; + } + if (Player.team_no == Item.owned_by) { + st = strcat(Q"\x10", st ,Q"\x11"); + //st = strcat("[", st ,"]"); + } + if (Item.goal_state == 1 && Item.owner != world) { + if (Player == Item.owner) { + st = strcat(st, Q"\s: Carried by \sYOU"); + } else { + st = strcat(st, Q"\s: Carried by \s", Item.owner.netname); + } + + } else { + if (Item.origin != Item.oldorigin) { + //When the item is thrown, there is a touch think with a pad of 4.25s before the normal timer kicks in + if((Item.nextthink - time) >= 0) { + if(Item.think != tfgoalitem_droptouch) { + st = strcat(st, Q"\s: Return: \s", ftos(rint(Item.bubble_count - time))); + } else { + st = strcat(st, Q"\s: Dropped\s"); + } + } else { + st = strcat(st, Q"\s: Returning\s NOW!"); + } + } else { + st = strcat(st, Q"\s: Safe\s"); + } + } + return st; +} + void (entity pl) RefreshStatusBar = { local string pad; local string s1; // will be used for grenade timers @@ -571,6 +637,11 @@ void (entity pl) RefreshStatusBar = { local string ident; local float height; local float i; + local entity tfdet; //info_tfdetect entity + local entity te, tg; + local string bi; //button info + //By default, show after tips; 0/off = off; 2 = always + local float sbflaginfostate = FO_GetUserSetting(pl, "sbflaginfo", "sbflaginfo", "on"); /* local float win, sec; */ pad = ""; @@ -599,11 +670,79 @@ void (entity pl) RefreshStatusBar = { pad = strzone(pad); // class tip - if (((time - 6) < pl.spawn_time) || ((time - 6) < pl.tip_time)) { + if ((((time - 6) < pl.spawn_time) || ((time - 6) < pl.tip_time)) && sbflaginfostate < 2) { ct = CF_GetRandomClassTip(pl.playerclass); } else { pl.display_tip = 0; - ct = strzone("\n\n\n\n\n\n"); + tfdet = find(world, classname, "info_tfdetect"); + if (!tfdet || !sbflaginfostate) { + ct = strzone("\n\n\n\n\n\n"); + } else { + ct = ""; + i = number_of_teams; // Extra newlines + for (float t = 1; t <= number_of_teams; t++) { + switch (t) + { + case 1: + te = Finditem(tfdet.display_item_status1); + break; + case 2: + te = Finditem(tfdet.display_item_status2); + break; + case 3: + te = Finditem(tfdet.display_item_status3); + break; + case 4: + te = Finditem(tfdet.display_item_status4); + break; + } + + if (te) + { + if(number_of_teams < 4) { + ct = strcat(ct, strpadr(GetItemStatus(pl, te, t),40),"\n"); + if((te.think == tfgoalitem_dropthink || te.think == tfgoalitem_remove) && !te.owner && (te.origin != te.oldorigin)) { + ct = strcat(ct, strpadr(strcat("\s Location: \s", getLocationName(te.origin)),40)); + } + i += 1; + } else { + if((te.think == tfgoalitem_dropthink || te.think == tfgoalitem_remove) && !te.owner && (te.origin != te.oldorigin)) { + ct = strcat(ct, strpadr(strcat(GetItemStatus(pl, te, t),"\s: \s", getLocationName(te.origin)),40)); + } else { + ct = strcat(ct, strpadr(GetItemStatus(pl, te, t),40)); + } + } + } + ct = strcat(ct, "\n"); + } + tg = find(world, classname, "info_tfgoal"); + while (tg) { + if (tg.track_goal && tg.goal_state == TFGS_DELAYED && i < 6) { + bi = ""; + //only do this for named goals, otherwise there's no way to distinguish them (they don't ususally have owned_by or anything) + if(tg.netname) { + bi = tg.netname; + if(tg.team_str_moved) { + bi = strcat(bi,": ", tg.team_str_moved); + } else { + bi = strcat(bi,": \sOffline\s"); + } + bi = strcat(bi, " ", ftos(rint(tg.bubble_count - time))); + ct = strcat(ct, strpadr(bi,40),"\n"); + i += 1; + } + } + tg = find(tg, classname, "info_tfgoal"); + } + + + for (float t = 0; t < (6 - i); t++) + ct = strcat(ct, "\n"); + + //ct = strcat(ct, "\n\n\n"); + + ct = strzone(ct); + } } // status line 1 column 1 - grenade timer @@ -664,34 +803,6 @@ void (entity pl) RefreshStatusBar = { s2 = strcat(s2, "\n"); s2 = strzone(s2); - // status line 3 column 1 - team 1 score - /* win = TeamFortress_TeamGetWinner(); */ - /* sec = TeamFortress_TeamGetSecond(); */ - /* if (win == 0) */ - /* st1 = BlueScoreToString(team1score); */ - /* else if (win == 1) */ - /* st1 = BlueScoreToString(team1score); */ - /* else if (win == 2) */ - /* st1 = RedScoreToString(team2score); */ - /* else if (win == 3) */ - /* st1 = YellowScoreToString(team3score); */ - /* else */ - /* st1 = GreenScoreToString(team4score); */ - /* // status line 3 column 2 - team 2 score */ - /* if (sec == 0) { */ - /* if (win < 2) */ - /* st2 = RedScoreToString(team2score); */ - /* else */ - /* st2 = BlueScoreToString(team1score); */ - /* } */ - /* else if (sec == 1) */ - /* st2 = BlueScoreToString(team1score); */ - /* else if (sec == 2) */ - /* st2 = RedScoreToString(team2score); */ - /* else if (sec == 3) */ - /* st2 = YellowScoreToString(team3score); */ - /* else */ - /* st2 = GreenScoreToString(team4score); */ st1 = ""; st2 = ""; diff --git a/tfort.qc b/tfort.qc index 5cb9340a..cebf3ee1 100644 --- a/tfort.qc +++ b/tfort.qc @@ -140,6 +140,7 @@ void (float inp) TeamFortress_ChangeClass = { if ((intermission_running != 0) || (intermission_exittime > time)) return; + override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); if (self.playerclass != 0) { if ((deathmatch != 3) && (!cb_prematch)) return; @@ -157,7 +158,7 @@ void (float inp) TeamFortress_ChangeClass = { sprint(self, PRINT_HIGH, "You cannot change class\n"); return; } - if (!IsLegalClass(inp)) { + if (!IsLegalClass(inp) && !override_mapclasses) { sprint(self, PRINT_HIGH, "Your team cannot play that class\n"); TeamFortress_DisplayLegalClasses(); @@ -202,7 +203,7 @@ void (float inp) TeamFortress_ChangeClass = { sprint(self, PRINT_HIGH, "You have no lives left\n"); return; } - if (!IsLegalClass(inp) && (inp != 11)) { + if (!IsLegalClass(inp) && !override_mapclasses && (inp != 11)) { sprint(self, PRINT_HIGH, "You cannot play that class on this map\n"); TeamFortress_DisplayLegalClasses(); @@ -307,9 +308,14 @@ void () TeamFortress_DisplayLegalClasses = { local float gotone; local float ill; + override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); sprint(self, PRINT_HIGH, "Legal classes for your team are:\n"); gotone = 0; - ill = TeamFortress_TeamGetIllegalClasses(self.team_no); + if(override_mapclasses) { + ill = -1; //Nothing is illegal unless restricted on server + } else { + ill = TeamFortress_TeamGetIllegalClasses(self.team_no); + } if (!(illegalclasses & 1) && !(ill & 1)) { if (gotone) { sprint(self, PRINT_HIGH, ", "); @@ -410,9 +416,13 @@ void () TeamFortress_Inventory = { sprint(self, PRINT_HIGH, ftos(fl)); if (self.tp_grenades_1 == GR_TYPE_NORMAL) sprint(self, PRINT_HIGH, " normal grenade"); - else if (self.tp_grenades_1 == GR_TYPE_NAIL) - sprint(self, PRINT_HIGH, " nail grenade"); - else if (self.tp_grenades_1 == GR_TYPE_MIRV) + else if (self.tp_grenades_1 == GR_TYPE_NAIL) { + if (nailgren_type == NGR_TYPE_LASER) { + sprint(self, PRINT_HIGH, " shock grenade"); + } else { + sprint(self, PRINT_HIGH, " nail grenade"); + } + } else if (self.tp_grenades_1 == GR_TYPE_MIRV) sprint(self, PRINT_HIGH, " mirv grenade"); else if (self.tp_grenades_1 == GR_TYPE_NAPALM) sprint(self, PRINT_HIGH, " napalm grenade"); @@ -439,9 +449,13 @@ void () TeamFortress_Inventory = { sprint(self, PRINT_HIGH, " normal grenade"); else if (self.tp_grenades_2 == GR_TYPE_CONCUSSION) sprint(self, PRINT_HIGH, " concussion grenade"); - else if (self.tp_grenades_2 == GR_TYPE_NAIL) - sprint(self, PRINT_HIGH, " nail grenade"); - else if (self.tp_grenades_2 == GR_TYPE_MIRV) + else if (self.tp_grenades_2 == GR_TYPE_NAIL) { + if (nailgren_type == NGR_TYPE_LASER) { + sprint(self, PRINT_HIGH, " shock grenade"); + } else { + sprint(self, PRINT_HIGH, " nail grenade"); + } + } else if (self.tp_grenades_2 == GR_TYPE_MIRV) sprint(self, PRINT_HIGH, " mirv grenade"); else if (self.tp_grenades_2 == GR_TYPE_NAPALM) sprint(self, PRINT_HIGH, " napalm grenade"); @@ -577,6 +591,7 @@ void () TeamFortress_ShowTF = { CF_PrintSetting("Spawn with full health/armor", spawnfull, "", 1); CF_PrintSetting("Stock players with full health/armor", stockfull, "", 1); CF_PrintSetting("Stock player on cap", stock_on_cap, "", 1); + CF_PrintSetting("Stock reloadable clip", stock_reload, "", 1); CF_PrintSetting("Old dropflag behaviour", old_dropflag, "", 1); CF_PrintSetting("Remember weapon", remember_weapon, "", 1); CF_PrintSetting("Pick up discarded ammo", discammo_pickup, "", 1); @@ -592,6 +607,26 @@ void () TeamFortress_ShowTF = { } CF_PrintSetting("Grenade timers", grentimers, "", 1); + CF_PrintSetting("Scout max grenades type 1 (caltrops)", max_gren1_scout, "", PC_SCOUT_GRENADE_MAX_1); + CF_PrintSetting("Sniper max grenades type 1 (normal)", max_gren1_sniper, "", PC_SNIPER_GRENADE_MAX_1); + CF_PrintSetting("Soldier max grenades type 1 (normal)", max_gren1_soldier, "", PC_SOLDIER_GRENADE_MAX_1); + CF_PrintSetting("Demoman max grenades type 1 (normal)", max_gren1_demoman, "", PC_DEMOMAN_GRENADE_MAX_1); + CF_PrintSetting("Medic max grenades type 1 (normal)", max_gren1_medic, "", PC_MEDIC_GRENADE_MAX_1); + CF_PrintSetting("Heavy Weapons max grenades type 1 (normal)", max_gren1_hwguy, "", PC_HVYWEAP_GRENADE_MAX_1); + CF_PrintSetting("Pyro max grenades type 1 (normal)", max_gren1_pyro, "", PC_PYRO_GRENADE_MAX_1); + CF_PrintSetting("Spy max grenades type 1 (normal)", max_gren1_spy, "", PC_SPY_GRENADE_MAX_1); + CF_PrintSetting("Engineer max grenades type 1 (normal)", max_gren1_engineer, "", PC_ENGINEER_GRENADE_MAX_1); + + CF_PrintSetting("Scout max grenades type 2 (concussion)", max_gren2_scout, "", PC_SCOUT_GRENADE_MAX_2); + CF_PrintSetting("Sniper max grenades type 2 (flare)", max_gren2_sniper, "", PC_SNIPER_GRENADE_MAX_2); + CF_PrintSetting("Soldier max grenades type 2 (nail/shock)", max_gren2_soldier, "", PC_SOLDIER_GRENADE_MAX_2); + CF_PrintSetting("Demoman max grenades type 2 (mirv)", max_gren2_demoman, "", PC_DEMOMAN_GRENADE_MAX_2); + CF_PrintSetting("Medic max grenades type 2 (concussion)", max_gren2_medic, "", PC_MEDIC_GRENADE_MAX_2); + CF_PrintSetting("Heavy Weapons max grenades type 2 (mirv)", max_gren2_hwguy, "", PC_HVYWEAP_GRENADE_MAX_2); + CF_PrintSetting("Pyro max grenades type 2 (napalm)", max_gren2_pyro, "", PC_PYRO_GRENADE_MAX_2); + CF_PrintSetting("Spy max grenades type 2 (gas)", max_gren2_spy, "", PC_SPY_GRENADE_MAX_2); + CF_PrintSetting("Engineer max grenades type 2 (emp)", max_gren2_engineer, "", PC_ENGINEER_GRENADE_MAX_2); + sprint(self, PRINT_HIGH, "Concussion effect lasts "); sprint(self, PRINT_HIGH, ftos(cussgrentime)); sprint(self, PRINT_HIGH, " seconds"); @@ -660,6 +695,7 @@ void () TeamFortress_ShowTF = { CF_PrintSetting("Allow feign death while airborne", feign_air, "", 1); CF_PrintSetting("Drop feign backpack", feign_pack, "", 1); CF_PrintSetting("Print feign death message", feign_msg, "", 1); + CF_PrintSetting("Override Map Class Limits", override_mapclasses, "", 0); if (server_faithful) { sprint(self, PRINT_HIGH, "\nThis server is running faithful Team Fortress settings.\n"); @@ -712,9 +748,13 @@ void (float inp) TeamFortress_PrimeGrenade = { if (self.tp_grenades_1 == 2) gs = "Concussion grenade"; - else if (self.tp_grenades_1 == 3) - gs = "Nail grenade"; - else if (self.tp_grenades_1 == 4) + else if (self.tp_grenades_1 == 3) { + if (nailgren_type == NGR_TYPE_LASER) { + gs = "Shock grenade"; + } else { + gs = "Nail grenade"; + } + } else if (self.tp_grenades_1 == 4) gs = "Mirv grenade"; else if (self.tp_grenades_1 == 5) gs = "Napalm grenade"; @@ -774,9 +814,13 @@ void (float inp) TeamFortress_PrimeGrenade = { if (self.tp_grenades_2 == 2) gs = "Concussion grenade"; - else if (self.tp_grenades_2 == 3) - gs = "Nail grenade"; - else if (self.tp_grenades_2 == 4) + else if (self.tp_grenades_2 == 3) { + if (nailgren_type == NGR_TYPE_LASER) { + gs = "Shock grenade"; + } else { + gs = "Nail grenade"; + } + } else if (self.tp_grenades_2 == 4) gs = "Mirv grenade"; else if (self.tp_grenades_2 == 5) gs = "Napalm grenade"; @@ -993,9 +1037,13 @@ void () TeamFortress_GrenadeSwitch = { self.tp_grenade_switch = 0; if (self.tp_grenades_1 == 2) gs = "Concussion grenade"; - else if (self.tp_grenades_1 == 3) - gs = "Nail grenade"; - else if (self.tp_grenades_1 == 4) + else if (self.tp_grenades_1 == 3) { + if (nailgren_type == NGR_TYPE_LASER) { + gs = "Shock grenade"; + } else { + gs = "Nail grenade"; + } + } else if (self.tp_grenades_1 == 4) gs = "Mirv grenade"; else if (self.tp_grenades_1 == 5) gs = "Napalm grenade"; @@ -1011,9 +1059,13 @@ void () TeamFortress_GrenadeSwitch = { self.tp_grenade_switch = 1; if (self.tp_grenades_2 == 2) gs = "Concussion grenade"; - else if (self.tp_grenades_2 == 3) - gs = "Nail grenade"; - else if (self.tp_grenades_2 == 4) + else if (self.tp_grenades_2 == 3) { + if (nailgren_type == NGR_TYPE_LASER) { + gs = "Shock grenade"; + } else { + gs = "Nail grenade"; + } + } else if (self.tp_grenades_2 == 4) gs = "Mirv grenade"; else if (self.tp_grenades_2 == 5) gs = "Napalm grenade"; @@ -1064,8 +1116,9 @@ float (float pc) IsLegalClass = { else if (pc == PC_RANDOM) bit = TF_ILL_RANDOMPC; + override_mapclasses = CF_GetSetting("omc", "override_mapclasses", "off"); if ((illegalclasses & bit) || - (TeamFortress_TeamGetIllegalClasses(self.team_no) & bit)) + (TeamFortress_TeamGetIllegalClasses(self.team_no) & bit && !override_mapclasses)) return (FALSE); return (TRUE); @@ -1412,8 +1465,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SCOUT_MAXAMMO_SHOT; self.ammo_cells = PC_SCOUT_MAXAMMO_CELL; self.armortype = PC_SCOUT_MAXARMORTYPE; - self.no_grenades_1 = PC_SCOUT_GRENADE_MAX_1; - self.no_grenades_2 = PC_SCOUT_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_scout; + self.no_grenades_2 = max_gren2_scout; if (old_hp_armor) self.armorvalue = 50; else @@ -1424,8 +1477,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SCOUT_INITAMMO_SHOT; self.ammo_cells = PC_SCOUT_INITAMMO_CELL; self.armortype = PC_SCOUT_INITARMORTYPE; - self.no_grenades_1 = PC_SCOUT_GRENADE_INIT_1; - self.no_grenades_2 = PC_SCOUT_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_SCOUT_GRENADE_INIT_1,max_gren1_scout); + self.no_grenades_2 = min(PC_SCOUT_GRENADE_INIT_2,max_gren2_scout); if (old_hp_armor) self.armorvalue = 25; @@ -1443,8 +1496,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_SCOUT_MAXAMMO_NAIL; self.maxammo_shells = PC_SCOUT_MAXAMMO_SHOT; self.maxammo_cells = PC_SCOUT_MAXAMMO_CELL; - self.max_grenades_1 = PC_SCOUT_GRENADE_MAX_1; - self.max_grenades_2 = PC_SCOUT_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_scout; + self.max_grenades_2 = max_gren2_scout; if (old_grens == 1) self.tp_grenades_1 = GR_TYPE_FLASH; @@ -1479,8 +1532,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SNIPER_MAXAMMO_SHOT; self.ammo_cells = PC_SNIPER_MAXAMMO_CELL; self.armortype = PC_SNIPER_MAXARMORTYPE; - self.no_grenades_1 = PC_SNIPER_GRENADE_MAX_1; - self.no_grenades_2 = PC_SNIPER_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_sniper; + self.no_grenades_2 = max_gren2_sniper; if (old_hp_armor) self.armorvalue = 50; else @@ -1491,8 +1544,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SNIPER_INITAMMO_SHOT; self.ammo_cells = PC_SNIPER_INITAMMO_CELL; self.armortype = PC_SNIPER_INITARMORTYPE; - self.no_grenades_1 = PC_SNIPER_GRENADE_INIT_1; - self.no_grenades_2 = PC_SNIPER_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_SNIPER_GRENADE_INIT_1,max_gren1_sniper); + self.no_grenades_2 = min(PC_SNIPER_GRENADE_INIT_2,max_gren2_sniper); if (old_hp_armor) self.armorvalue = 0; else @@ -1509,8 +1562,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_SNIPER_MAXAMMO_NAIL; self.maxammo_shells = PC_SNIPER_MAXAMMO_SHOT; self.maxammo_cells = PC_SNIPER_MAXAMMO_CELL; - self.max_grenades_1 = PC_SNIPER_GRENADE_MAX_1; - self.max_grenades_2 = PC_SNIPER_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_sniper; + self.max_grenades_2 = max_gren2_sniper; self.tp_grenades_1 = PC_SNIPER_GRENADE_TYPE_1; self.tp_grenades_2 = PC_SNIPER_GRENADE_TYPE_2; @@ -1537,8 +1590,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SOLDIER_MAXAMMO_SHOT; self.ammo_cells = PC_SOLDIER_MAXAMMO_CELL; self.armortype = PC_SOLDIER_MAXARMORTYPE; - self.no_grenades_1 = PC_SOLDIER_GRENADE_MAX_1; - self.no_grenades_2 = PC_SOLDIER_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_soldier; + self.no_grenades_2 = max_gren2_soldier; if (old_hp_armor) self.armorvalue = 200; else @@ -1549,8 +1602,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SOLDIER_INITAMMO_SHOT; self.ammo_cells = PC_SOLDIER_INITAMMO_CELL; self.armortype = PC_SOLDIER_INITARMORTYPE; - self.no_grenades_1 = PC_SOLDIER_GRENADE_INIT_1; - self.no_grenades_2 = PC_SOLDIER_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_SOLDIER_GRENADE_INIT_1,max_gren1_soldier); + self.no_grenades_2 = min(PC_SOLDIER_GRENADE_INIT_2,max_gren2_soldier); if (old_hp_armor) self.armorvalue = 100; else @@ -1567,8 +1620,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_SOLDIER_MAXAMMO_NAIL; self.maxammo_shells = PC_SOLDIER_MAXAMMO_SHOT; self.maxammo_cells = PC_SOLDIER_MAXAMMO_CELL; - self.max_grenades_1 = PC_SOLDIER_GRENADE_MAX_1; - self.max_grenades_2 = PC_SOLDIER_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_soldier; + self.max_grenades_2 = max_gren2_soldier; self.tp_grenades_1 = PC_SOLDIER_GRENADE_TYPE_1; self.tp_grenades_2 = PC_SOLDIER_GRENADE_TYPE_2; @@ -1596,8 +1649,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_DEMOMAN_MAXAMMO_SHOT; self.ammo_cells = PC_DEMOMAN_MAXAMMO_CELL; self.armortype = PC_DEMOMAN_MAXARMORTYPE; - self.no_grenades_1 = PC_DEMOMAN_GRENADE_MAX_1; - self.no_grenades_2 = PC_DEMOMAN_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_demoman; + self.no_grenades_2 = max_gren2_demoman; if (old_hp_armor) self.armorvalue = 120; else @@ -1608,8 +1661,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_DEMOMAN_INITAMMO_SHOT; self.ammo_cells = PC_DEMOMAN_INITAMMO_CELL; self.armortype = PC_DEMOMAN_INITARMORTYPE; - self.no_grenades_1 = PC_DEMOMAN_GRENADE_INIT_1; - self.no_grenades_2 = PC_DEMOMAN_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_DEMOMAN_GRENADE_INIT_1,max_gren1_demoman); + self.no_grenades_2 = min(PC_DEMOMAN_GRENADE_INIT_2,max_gren2_demoman); if (old_hp_armor) self.armorvalue = 50; else @@ -1626,8 +1679,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_DEMOMAN_MAXAMMO_NAIL; self.maxammo_shells = PC_DEMOMAN_MAXAMMO_SHOT; self.maxammo_cells = PC_DEMOMAN_MAXAMMO_CELL; - self.max_grenades_1 = PC_DEMOMAN_GRENADE_MAX_1; - self.max_grenades_2 = PC_DEMOMAN_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_demoman; + self.max_grenades_2 = max_gren2_demoman; self.tp_grenades_1 = PC_DEMOMAN_GRENADE_TYPE_1; self.tp_grenades_2 = PC_DEMOMAN_GRENADE_TYPE_2; @@ -1656,8 +1709,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_MEDIC_MAXAMMO_SHOT; self.ammo_cells = PC_MEDIC_MAXAMMO_CELL; self.armortype = PC_MEDIC_MAXARMORTYPE; - self.no_grenades_1 = PC_MEDIC_GRENADE_MAX_1; - self.no_grenades_2 = PC_MEDIC_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_medic; + self.no_grenades_2 = max_gren2_medic; if (old_hp_armor) self.armorvalue = 100; else @@ -1668,8 +1721,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_MEDIC_INITAMMO_SHOT; self.ammo_cells = PC_MEDIC_INITAMMO_CELL; self.armortype = PC_MEDIC_INITARMORTYPE; - self.no_grenades_1 = PC_MEDIC_GRENADE_INIT_1; - self.no_grenades_2 = PC_MEDIC_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_MEDIC_GRENADE_INIT_1,max_gren1_medic); + self.no_grenades_2 = min(PC_MEDIC_GRENADE_INIT_2,max_gren2_medic); if (old_hp_armor) self.armorvalue = 50; else @@ -1686,8 +1739,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_MEDIC_MAXAMMO_NAIL; self.maxammo_shells = PC_MEDIC_MAXAMMO_SHOT; self.maxammo_cells = PC_MEDIC_MAXAMMO_CELL; - self.max_grenades_1 = PC_MEDIC_GRENADE_MAX_1; - self.max_grenades_2 = PC_MEDIC_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_medic; + self.max_grenades_2 = max_gren2_medic; self.tp_grenades_1 = PC_MEDIC_GRENADE_TYPE_1; self.tp_grenades_2 = PC_MEDIC_GRENADE_TYPE_2; @@ -1735,8 +1788,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_HVYWEAP_MAXAMMO_SHOT; self.ammo_cells = PC_HVYWEAP_MAXAMMO_CELL; self.armortype = PC_HVYWEAP_MAXARMORTYPE; - self.no_grenades_1 = PC_HVYWEAP_GRENADE_MAX_1; - self.no_grenades_2 = PC_HVYWEAP_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_hwguy; + self.no_grenades_2 = max_gren2_hwguy; if (old_hp_armor) self.armorvalue = 300; @@ -1748,8 +1801,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_HVYWEAP_INITAMMO_SHOT; self.ammo_cells = PC_HVYWEAP_INITAMMO_CELL; self.armortype = PC_HVYWEAP_INITARMORTYPE; - self.no_grenades_1 = PC_HVYWEAP_GRENADE_INIT_1; - self.no_grenades_2 = PC_HVYWEAP_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_HVYWEAP_GRENADE_INIT_1,max_gren1_hwguy); + self.no_grenades_2 = min(PC_HVYWEAP_GRENADE_INIT_2,max_gren2_hwguy); if (old_hp_armor) self.armorvalue = 150; @@ -1767,8 +1820,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_HVYWEAP_MAXAMMO_NAIL; self.maxammo_shells = PC_HVYWEAP_MAXAMMO_SHOT; self.maxammo_cells = PC_HVYWEAP_MAXAMMO_CELL; - self.max_grenades_1 = PC_HVYWEAP_GRENADE_MAX_1; - self.max_grenades_2 = PC_HVYWEAP_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_hwguy; + self.max_grenades_2 = max_gren2_hwguy; self.tp_grenades_1 = PC_HVYWEAP_GRENADE_TYPE_1; self.tp_grenades_2 = PC_HVYWEAP_GRENADE_TYPE_2; @@ -1796,8 +1849,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_PYRO_MAXAMMO_SHOT; self.ammo_cells = PC_PYRO_MAXAMMO_CELL; self.armortype = PC_PYRO_MAXARMORTYPE; - self.no_grenades_1 = PC_PYRO_GRENADE_MAX_1; - self.no_grenades_2 = PC_PYRO_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_pyro; + self.no_grenades_2 = max_gren2_pyro; if (old_hp_armor) self.armorvalue = 150; else @@ -1808,8 +1861,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_PYRO_INITAMMO_SHOT; self.ammo_cells = PC_PYRO_INITAMMO_CELL; self.armortype = PC_PYRO_INITARMORTYPE; - self.no_grenades_1 = PC_PYRO_GRENADE_INIT_1; - self.no_grenades_2 = PC_PYRO_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_PYRO_GRENADE_INIT_1,max_gren1_pyro); + self.no_grenades_2 = min(PC_PYRO_GRENADE_INIT_2,max_gren2_pyro); if (old_hp_armor) self.armorvalue = 50; else @@ -1826,8 +1879,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_PYRO_MAXAMMO_NAIL; self.maxammo_shells = PC_PYRO_MAXAMMO_SHOT; self.maxammo_cells = PC_PYRO_MAXAMMO_CELL; - self.max_grenades_1 = PC_PYRO_GRENADE_MAX_1; - self.max_grenades_2 = PC_PYRO_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_pyro; + self.max_grenades_2 = max_gren2_pyro; self.tp_grenades_1 = PC_PYRO_GRENADE_TYPE_1; self.tp_grenades_2 = PC_PYRO_GRENADE_TYPE_2; @@ -1912,8 +1965,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SPY_MAXAMMO_SHOT; self.ammo_cells = PC_SPY_MAXAMMO_CELL; self.armortype = PC_SPY_MAXARMORTYPE; - self.no_grenades_1 = PC_SPY_GRENADE_MAX_1; - self.no_grenades_2 = PC_SPY_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_spy; + self.no_grenades_2 = max_gren2_spy; if (old_hp_armor) self.armorvalue = 100; @@ -1925,8 +1978,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_SPY_INITAMMO_SHOT; self.ammo_cells = PC_SPY_INITAMMO_CELL; self.armortype = PC_SPY_INITARMORTYPE; - self.no_grenades_1 = PC_SPY_GRENADE_INIT_1; - self.no_grenades_2 = PC_SPY_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_SPY_GRENADE_INIT_1,max_gren1_spy); + self.no_grenades_2 = min(PC_SPY_GRENADE_INIT_2,max_gren2_spy); if (old_hp_armor) self.armorvalue = 25; @@ -1944,8 +1997,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_SPY_MAXAMMO_NAIL; self.maxammo_shells = PC_SPY_MAXAMMO_SHOT; self.maxammo_cells = PC_SPY_MAXAMMO_CELL; - self.max_grenades_1 = PC_SPY_GRENADE_MAX_1; - self.max_grenades_2 = PC_SPY_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_spy; + self.max_grenades_2 = max_gren2_spy; self.tp_grenades_1 = PC_SPY_GRENADE_TYPE_1; self.tp_grenades_2 = PC_SPY_GRENADE_TYPE_2; @@ -1980,8 +2033,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_ENGINEER_MAXAMMO_SHOT; self.ammo_cells = PC_ENGINEER_MAXAMMO_CELL; self.armortype = PC_ENGINEER_MAXARMORTYPE; - self.no_grenades_1 = PC_ENGINEER_GRENADE_MAX_1; - self.no_grenades_2 = PC_ENGINEER_GRENADE_MAX_2; + self.no_grenades_1 = max_gren1_engineer; + self.no_grenades_2 = max_gren2_engineer; if (old_hp_armor) self.armorvalue = 50; @@ -1993,8 +2046,8 @@ void () TeamFortress_SetEquipment = { self.ammo_shells = PC_ENGINEER_INITAMMO_SHOT; self.ammo_cells = PC_ENGINEER_INITAMMO_CELL; self.armortype = PC_ENGINEER_INITARMORTYPE; - self.no_grenades_1 = PC_ENGINEER_GRENADE_INIT_1; - self.no_grenades_2 = PC_ENGINEER_GRENADE_INIT_2; + self.no_grenades_1 = min(PC_ENGINEER_GRENADE_INIT_1,max_gren1_engineer); + self.no_grenades_2 = min(PC_ENGINEER_GRENADE_INIT_2,max_gren2_engineer); if (old_hp_armor) self.armorvalue = 25; else @@ -2011,8 +2064,8 @@ void () TeamFortress_SetEquipment = { self.maxammo_nails = PC_ENGINEER_MAXAMMO_NAIL; self.maxammo_shells = PC_ENGINEER_MAXAMMO_SHOT; self.maxammo_cells = PC_ENGINEER_MAXAMMO_CELL; - self.max_grenades_1 = PC_ENGINEER_GRENADE_MAX_1; - self.max_grenades_2 = PC_ENGINEER_GRENADE_MAX_2; + self.max_grenades_1 = max_gren1_engineer; + self.max_grenades_2 = max_gren2_engineer; self.tp_grenades_1 = PC_ENGINEER_GRENADE_TYPE_1; self.tp_grenades_2 = PC_ENGINEER_GRENADE_TYPE_2; @@ -2794,46 +2847,39 @@ void () NormalGrenadeExplode = { }; void () TeamFortress_DisplayDetectionItems = { - local entity Goal; + local entity tfdet; local entity te; + te = world; - Goal = find(world, classname, "info_tfdetect"); - if (!Goal) + tfdet = find(world, classname, "info_tfdetect"); + if (!tfdet) return; - if (Goal.display_item_status1 != 0) { - te = Finditem(Goal.display_item_status1); - if (te) - DisplayItemStatus(Goal, self, te); - else - sprint(self, PRINT_HIGH, "Item is missing\n"); - } else - return; - - if (Goal.display_item_status2 != 0) { - te = Finditem(Goal.display_item_status2); - if (te) - DisplayItemStatus(Goal, self, te); - else - sprint(self, PRINT_HIGH, "Item is missing\n"); - } else - return; - - if (Goal.display_item_status3 != 0) { - te = Finditem(Goal.display_item_status3); - if (te) - DisplayItemStatus(Goal, self, te); - else - sprint(self, PRINT_HIGH, "Item is missing\n"); - } else - return; + for (float t = 1; t <= number_of_teams; t++) { + switch (t) + { + case 1: + te = Finditem(tfdet.display_item_status1); + break; + case 2: + te = Finditem(tfdet.display_item_status2); + break; + case 3: + te = Finditem(tfdet.display_item_status3); + break; + case 4: + te = Finditem(tfdet.display_item_status4); + break; + } - if (Goal.display_item_status4 != 0) { - te = Finditem(Goal.display_item_status4); if (te) - DisplayItemStatus(Goal, self, te); + { + sprint(self, PRINT_HIGH, strcat(GetItemStatus(self, te, t), "\n")); + } else + { sprint(self, PRINT_HIGH, "Item is missing\n"); + } } }; diff --git a/tforthlp.qc b/tforthlp.qc index b5757015..aa576908 100644 --- a/tforthlp.qc +++ b/tforthlp.qc @@ -181,6 +181,7 @@ void () TeamFortress_MOTD = { stuffcmd(self, "is_aliased\n"); TeamFortress_Alias ("ready", TF_PLAYER_READY, 0); TeamFortress_Alias ("notready", TF_PLAYER_NOT_READY, 0); + TeamFortress_Alias ("nginfo", TF_NAILGREN_INFO, 0); //nailgreninfo } else if (self.motd == 400 && self.team_no == 0) { Menu_Team(1); } diff --git a/tfortmap.qc b/tfortmap.qc index ace8c73d..89162d3b 100644 --- a/tfortmap.qc +++ b/tfortmap.qc @@ -233,34 +233,51 @@ void () TF_PlaceItem = { }; void () TF_StartItem = { - if (self.model == "progs/tf_flag.mdl" || self.model == "progs/tf_stan.mdl") { - self.effects = self.effects | EF_DIMLIGHT; - - if (self.skin == 1.0) { + local entity tfdet; //info_tfdetect entity + tfdet = find(world, classname, "info_tfdetect"); + if (tfdet && (tfdet.display_item_status1 == self.goal_no || tfdet.display_item_status2 == self.goal_no || tfdet.display_item_status3 == self.goal_no || tfdet.display_item_status4 == self.goal_no)) { + if (self.owned_by == 1.0) { self.effects = self.effects | EF_BLUE; } - if (self.skin == 2.0) { + if (self.owned_by == 2.0) { self.effects = self.effects | EF_RED; } - if (self.skin == 3.0) { + if (self.owned_by == 3.0) { self.effects = self.effects | EF_RED; self.effects = self.effects | EF_MUZZLEFLASH; } - if (self.skin == 4.0) { + if (self.owned_by == 4.0) { self.effects = self.effects | EF_MUZZLEFLASH; } - } + } else { + if (self.model == "progs/tf_flag.mdl" || self.model == "progs/tf_stan.mdl") { + self.effects = self.effects | EF_DIMLIGHT; - if (self.model == "progs/basrkey.bsp" ) { - self.effects = self.effects | EF_DIMLIGHT; - self.effects = self.effects | EF_RED; - } + if (self.skin == 1.0) { + self.effects = self.effects | EF_BLUE; + } + if (self.skin == 2.0) { + self.effects = self.effects | EF_RED; + } + if (self.skin == 3.0) { + self.effects = self.effects | EF_RED; + self.effects = self.effects | EF_MUZZLEFLASH; + } + if (self.skin == 4.0) { + self.effects = self.effects | EF_MUZZLEFLASH; + } + } - if (self.model == "progs/basbkey.bsp" ) { - self.effects = self.effects | EF_DIMLIGHT; - self.effects = self.effects | EF_BLUE; - } + if (self.model == "progs/basrkey.bsp" ) { + self.effects = self.effects | EF_DIMLIGHT; + self.effects = self.effects | EF_RED; + } + if (self.model == "progs/basbkey.bsp" ) { + self.effects = self.effects | EF_DIMLIGHT; + self.effects = self.effects | EF_BLUE; + } + } UpdateAbbreviations(self); self.nextthink = time + 0.2; self.think = TF_PlaceItem; @@ -571,7 +588,7 @@ void (entity AD) ParseTFDetect = { entity(float ino) Finditem = { local entity tg; - local string st; + //local string st; tg = find(world, classname, "item_tfgoal"); while (tg) { @@ -579,10 +596,10 @@ entity(float ino) Finditem = return (tg); tg = find(tg, classname, "item_tfgoal"); } - dprint("Could not find an item with a goal_no of "); - st = ftos(ino); - dprint(st); - dprint(".\n"); + //dprint("Could not find an item with a goal_no of "); + //st = ftos(ino); + //dprint(st); + //dprint(".\n"); return world; }; @@ -652,6 +669,7 @@ void (entity Goal) RestoreGoal = { Goal.goal_state = 2; if (Goal.mdl != string_null) { setmodel(Goal, Goal.mdl); + setsize(Goal, Goal.goal_min, Goal.goal_max); } if (Goal.model == "progs/tf_flag.mdl" || Goal.model == "progs/tf_stan.mdl") { Goal.effects = Goal.effects | EF_DIMLIGHT; @@ -800,12 +818,71 @@ void (entity Goal, entity Player, entity AP, float addb) Apply_Results = { Player.ammo_cells = Player.ammo_cells + Goal.ammo_cells; Player.ammo_medikit = Player.ammo_medikit + Goal.ammo_medikit; Player.ammo_detpack = Player.ammo_detpack + Goal.ammo_detpack; + //refill the clip if stock_reload is 2 + if (stock_reload == 2) { + if(Goal.ammo_shells) { + if(Player.current_weapon == WEAP_SHOTGUN) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_shotgun = max(Player.reload_shotgun - Goal.ammo_shells, 0); + if(Player.current_weapon == WEAP_SUPER_SHOTGUN) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_super_shotgun = max(Player.reload_super_shotgun - Goal.ammo_shells, 0); + if(Player.current_weapon == WEAP_SNIPER_RIFLE) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_sniper_rifle = max(Player.reload_sniper_rifle - Goal.ammo_shells, 0); + } + if(Goal.ammo_rockets) { + if(Player.current_weapon == WEAP_GRENADE_LAUNCHER) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_grenade_launcher = max(Player.reload_grenade_launcher - Goal.ammo_rockets, 0); + if(Player.current_weapon == WEAP_ROCKET_LAUNCHER) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_rocket_launcher = max(Player.reload_rocket_launcher - Goal.ammo_rockets, 0); + } + } else { + //for use in map entities without specifically enabling the general override + if(Goal.reload_shotgun) { + if(Player.current_weapon == WEAP_SHOTGUN) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_shotgun = max(Player.reload_shotgun - Goal.ammo_shells, 0); + } + if(Goal.reload_super_shotgun) { + if(Player.current_weapon == WEAP_SUPER_SHOTGUN) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_super_shotgun = max(Player.reload_super_shotgun - Goal.ammo_shells, 0); + } + if(Goal.reload_sniper_rifle) { + if(Player.current_weapon == WEAP_SNIPER_RIFLE) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_sniper_rifle = max(Player.reload_sniper_rifle - Goal.ammo_shells, 0); + } + if(Goal.reload_grenade_launcher) { + if(Player.current_weapon == WEAP_GRENADE_LAUNCHER) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_grenade_launcher = max(Player.reload_grenade_launcher - Goal.ammo_rockets, 0); + } + if(Goal.reload_rocket_launcher) { + if(Player.current_weapon == WEAP_ROCKET_LAUNCHER) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + } + Player.reload_rocket_launcher = max(Player.reload_rocket_launcher - Goal.ammo_rockets, 0); + } + } Player.no_grenades_1 = Player.no_grenades_1 + Goal.no_grenades_1; Player.no_grenades_2 = Player.no_grenades_2 + Goal.no_grenades_2; - if (Player.no_grenades_1 > Player.max_grenades_1) { + if (Player.no_grenades_1 > Player.max_grenades_1) { Player.no_grenades_1 = Player.max_grenades_1; } if (Player.no_grenades_2 > Player.max_grenades_2) { @@ -952,6 +1029,15 @@ void (entity Goal, entity Player, entity AP, float addb) Apply_Results = { te = find(Player, netname, "flashtimer"); dremove(te); } + //Refill the clip while restocking + if (stock_reload) { + Player.tfstate = Player.tfstate - (Player.tfstate & TFSTATE_RELOADING); + Player.reload_shotgun = 0; + Player.reload_super_shotgun = 0; + Player.reload_grenade_launcher = 0; + Player.reload_rocket_launcher = 0; + Player.reload_sniper_rifle = 0; + } } } } @@ -1649,6 +1735,7 @@ void (entity Goal, entity AP, float addb) DoResults = { te.owner = AP; te.enemy = Goal; te.weapon = addb; + Goal.bubble_count = time + Goal.delay_time; return; } @@ -1998,6 +2085,10 @@ void () CF_FlagFollowPlayer = { } }; +void () idle_think = { + self.nextthink = time + 0.1; +} + void () item_tfgoal_touch = { local entity te, flw; @@ -2017,12 +2108,6 @@ void () item_tfgoal_touch = { if (trace_fraction < 1) return; - flw = spawn(); - flw.real_owner = other; - flw.owner = self; - flw.think = CF_FlagFollowPlayer; - flw.nextthink = time + 0.1; - if (CTF_Map == 1) { if (self.goal_no == 1) { if (self.origin != self.oldorigin) { @@ -2099,8 +2184,22 @@ void () item_tfgoal_touch = { if (te) { AttemptToActivate(te, other, self); } + } else { + //Make sure we don't try to follow someone who fails the criteria + return; } } + + if (flag_follow) { + flw = spawn(); + flw.real_owner = other; + flw.owner = self; + flw.think = CF_FlagFollowPlayer; + //flw.solid = SOLID_NOT; + //self.solid = SOLID_NOT; + self.think = idle_think; + flw.nextthink = time + 0.1; + } }; void (entity Item, entity AP, entity Goal) tfgoalitem_GiveToPlayer = { @@ -2375,13 +2474,13 @@ void () tfgoalitem_dropthink = { self.movetype = 6; if (self.pausetime != 0) { pos = pointcontents(self.origin); - if (pos == -4) { + if (pos == -4) { //CONTENT_SLIME self.nextthink = time + (self.pausetime / 4); } else { - if (pos == -5) { + if (pos == -5) { //CONTENT_LAVA self.nextthink = time + 5; } else { - if ((pos == -2) || (pos == -6)) { + if ((pos == -2) || (pos == -6)) { //CONTENT_SOLID || CONTENT_SKY if (self.camdist < 3) { self.origin = self.camangle; setorigin(self, self.origin); @@ -2479,11 +2578,13 @@ void (entity Item, float PAlive, entity P) tfgoalitem_drop = { } Item.touch = SUB_Null; Item.nextthink = time + 0.75; + Item.bubble_count = time + Item.pausetime + 0.75 + 4.25; //used by the return timer Item.think = tfgoalitem_droptouch; } else { Item.touch = item_tfgoal_touch; Item.nextthink = time + 5; Item.think = tfgoalitem_dropthink; + Item.bubble_count = time + Item.pausetime + 5; //used by the return timer } Item.owner = world; }; @@ -2500,6 +2601,7 @@ void () tfgoalitem_remove = { te.weapon = 3; te.nextthink = time + 0.1; te.think = ReturnItem; + te.bubble_count = 0; //reset return time counter return; } dremove(self); @@ -2821,7 +2923,7 @@ void (entity P) ForceRespawn = { void () DropGoalItems = { local entity te, search; - + newmis = spawn(); makevectors(self.v_angle); v_forward = normalize(v_forward) * 64; @@ -2834,17 +2936,33 @@ void () DropGoalItems = { tfgoalitem_RemoveFromPlayer(te, self, 2); } } - else if (self.effects & EF_DIMLIGHT) { + //Always allow dropping 4096 + else if (self.effects & EF_DIMLIGHT || te.goal_activation & 4096) { te.angles = '0 0 0'; tfgoalitem_RemoveEffectsFromPlayer(te, self); tfgoalitem_drop(te, 1, self); - if (self.team_no == 1) - bprint(PRINT_HIGH, self.netname, Q" \sdropped red's flag!\s\n"); - else if (self.team_no == 2) - bprint(PRINT_HIGH, self.netname, Q" \sdropped blue's flag!\s\n"); - else - bprint(PRINT_HIGH, self.netname, Q" \sdropped the enemy's flag!\s\n"); - + if (!te.netname_team_drop || !te.netname_non_team_drop) { + if (te.netname) { + bprint(PRINT_HIGH, self.netname, Q" \sdropped ", te.netname ,"!\s\n"); + } else if (te.owned_by > 0) { + if (te.owned_by == 1) + bprint(PRINT_HIGH, self.netname, Q" \sdropped blue's flag!\s\n"); + else if (te.owned_by == 2) + bprint(PRINT_HIGH, self.netname, Q" \sdropped red's flag!\s\n"); + else if (te.owned_by == 3) + bprint(PRINT_HIGH, self.netname, Q" \sdropped yellow's flag!\s\n"); + else if (te.owned_by == 4) + bprint(PRINT_HIGH, self.netname, Q" \sdropped green's flag!\s\n"); + } else { + if (self.team_no == 1) + bprint(PRINT_HIGH, self.netname, Q" \sdropped red's flag!\s\n"); + else if (self.team_no == 2) + bprint(PRINT_HIGH, self.netname, Q" \sdropped blue's flag!\s\n"); + else + bprint(PRINT_HIGH, self.netname, Q" \sdropped the enemy's flag!\s\n"); + } + } + Status_Print(self, "\n\n\n", "You dropped the flag!"); search = find(world, classname, "player"); while (search) { @@ -2854,6 +2972,14 @@ void () DropGoalItems = { } else { Status_Print(search, "\n\n\n", "The enemy dropped your flag!"); } + if (te.owned_by) { + if (te.netname_team_drop && te.netname_non_team_drop && search.team_no == te.owned_by) { + sprint(search, PRINT_HIGH, self.netname, te.netname_team_drop); + } + if (te.netname_team_drop && te.netname_non_team_drop && search.team_no != te.owned_by) { + sprint(search, PRINT_HIGH, self.netname, te.netname_non_team_drop); + } + } search = find(search, classname, "player"); } } diff --git a/tsoldier.qc b/tsoldier.qc index 77623476..178ba90d 100644 --- a/tsoldier.qc +++ b/tsoldier.qc @@ -5,6 +5,8 @@ void () NailGrenadeExplode; void () NailGrenadeNailEm; void () NailGrenadeLaunchNail; +void () NailGrenLaser; +void () NailGrenBurst; void () NailGrenadeTouch = { if (other == self.owner) @@ -37,7 +39,20 @@ void () NailGrenadeExplode = { setorigin(self, self.origin + '0 0 32'); self.avelocity = '0 500 0'; self.nextthink = time + 0.7; + if (nailgren_type == NGR_TYPE_LASER) + { + self.playerclass = 0; + self.think = NailGrenLaser; + } + else if (nailgren_type == NGR_TYPE_BURST) + { + self.playerclass = 0; + self.think = NailGrenBurst; + } + else + { self.think = NailGrenadeNailEm; + } }; void () NailGrenadeNailEm = { @@ -77,3 +92,117 @@ void () NailGrenadeLaunchNail = { self.think = GrenadeExplode; } }; + +void () NailGrenLaser = { //using self.playerclass to count thinks + local float current_yaw; + local vector org; + + if(self.playerclass == 0){ + self.velocity = '0 0 0'; + self.real_owner = self.owner; + self.owner = world; //work-around because traceent wouldnt hit self or self.owner + current_yaw = 0; + lasergren_reqthinks = (lasergren_rotationcount * lasergren_rotationtime) / lasergren_thinktime; + lasergren_angleperthink = (lasergren_rotationcount * 360) / lasergren_reqthinks; + self.v_angle = self.angles; + } else { + current_yaw = anglemod(self.v_angle_y + lasergren_angleperthink); + } + self.v_angle_y = current_yaw; + self.v_angle_x = 0; + self.v_angle_z = 0; + self.angles = self.v_angle; + makevectors(self.v_angle); + + org = self.origin; + traceline(org, org + v_forward * lasergren_range, 0, self); + + WriteByte(MSG_MULTICAST, SVC_TEMPENTITY); + WriteByte(MSG_MULTICAST, TE_LIGHTNING2); + WriteEntity(MSG_MULTICAST, self); + WriteCoord(MSG_MULTICAST, org_x); + WriteCoord(MSG_MULTICAST, org_y); + WriteCoord(MSG_MULTICAST, org_z); + WriteCoord(MSG_MULTICAST, trace_endpos_x); + WriteCoord(MSG_MULTICAST, trace_endpos_y); + WriteCoord(MSG_MULTICAST, trace_endpos_z); + multicast(org, MULTICAST_PHS); + + if (trace_ent.takedamage){ + + WriteByte(MSG_MULTICAST, SVC_TEMPENTITY); + WriteByte(MSG_MULTICAST, TE_LIGHTNINGBLOOD); + WriteCoord(MSG_MULTICAST, trace_endpos_x); + WriteCoord(MSG_MULTICAST, trace_endpos_y); + WriteCoord(MSG_MULTICAST, trace_endpos_z); + multicast(trace_endpos, MULTICAST_PVS); + + deathmsg = DMSG_GREN_NAIL; + TF_T_Damage(trace_ent, self, self.real_owner, lasergren_damage, TF_TD_NOTTEAM, TF_TD_ELECTRICITY); + } + if (self.t_width < time) { + sound(self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM); + self.t_width = time + 0.8; + } + + self.nextthink = time + lasergren_thinktime; + self.playerclass++; + //already did this above + //current_yaw = anglemod(self.angles_y + lasergren_angleperthink); + + if (self.playerclass > lasergren_reqthinks) { //not >= to give an extra think so it hits start again + self.owner = self.real_owner; + self.weapon = DMSG_GREN_NAIL; + self.think = GrenadeExplode; + } +}; + +void () NailGrenBurst = { + local float i; + local float current_yaw; + current_yaw = 0; + i = 0; + self.velocity = '0 0 0'; + + while (i < 16){ + self.angles_y = current_yaw; + self.angles_x = 0; + self.angles_z = 0; + makevectors(self.angles); + + sound(self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM); + + deathmsg = DMSG_GREN_NAIL; + launch_spike(self.origin, v_forward); + newmis.velocity = v_forward * 1000; + newmis.touch = superspike_touch; + newmis.weapon = DMSG_GREN_NAIL; + newmis.nextthink = time + burstgren_range; + i++; + current_yaw = anglemod(self.angles_y + 22.5); + } + self.playerclass++; + self.nextthink = time + burstgren_interval; + + if (self.playerclass >= burstgren_count){ + self.nextthink = time + 0.1; + self.weapon = DMSG_GREN_NAIL; + self.think = GrenadeExplode; + } +}; + +void () TeamFortress_NailGrenInfo = { + sprint(self,2,Q"\n\snailgren info - num in brackets are default - num shown are to one dec place - updated on map change\s\n"); + sprint(self,2,Q"\n\s----------------------------------------------------------------------------------------------\s\n"); + sprint(self,2,Q"ngt nailgren_type ",ftos(nailgren_type)," (",ftos(NGR_TYPE_DEFAULT),") \s// 0 default, 1 laser, 2 burst \n\n"); + sprint(self,2,Q"lgrc lasergren_rotationcount ",ftos(lasergren_rotationcount)," (",ftos(NGR_LASER_DEFAULT_ROTATIONCOUNT),") \s// how many rotations to perform\n"); + sprint(self,2,Q"lgrt lasergren_rotationtime ",ftos(lasergren_rotationtime)," (",ftos(NGR_LASER_DEFAULT_ROTATIONTIME),") \s// time to complete one rotation\n"); + sprint(self,2,Q"lgr lasergren_range ",ftos(lasergren_range)," (",ftos(NGR_LASER_DEFAULT_RANGE),") \s// range\n"); + sprint(self,2,Q"lgd lasergren_damage ",ftos(lasergren_damage)," (",ftos(NGR_LASER_DEFAULT_DAMAGE),") \s// damage\n"); + sprint(self,2,Q"lgtt lasergren_thinktime ",ftos(lasergren_thinktime)," (0.1) \s// time between thinks, lower to smooth rotation \n\n"); + sprint(self,2,Q"bgc burstgren_count ",ftos(burstgren_count)," (",ftos(NGR_BURST_DEFAULT_COUNT),") \s// how many bursts of nails\n"); + sprint(self,2,Q"bgi burstgren_interval ",ftos(burstgren_interval)," (",ftos(NGR_BURST_DEFAULT_INTERVAL),") \s// time between bursts\n"); + sprint(self,2,Q"bgr burstgren_range ",ftos(burstgren_range)," (",ftos(NGR_BURST_DEFAULT_RANGE),") \s// time before nail projectiles destroyself\n"); + sprint(self,2,Q"\s----------------------------------------------------------------------------------------------\s\n"); + self.impulse = 0; +}; diff --git a/weapons.qc b/weapons.qc index ffc01b20..8afc4b90 100644 --- a/weapons.qc +++ b/weapons.qc @@ -89,6 +89,7 @@ void (entity gun) Engineer_UseSentryGun; void () TeamFortress_MOTD; void () TeamFortress_HelpMap; +void () TeamFortress_NailGrenInfo; void () BioInfection_Decay; void () BioInfection_MonsterDecay; @@ -2583,7 +2584,6 @@ float (entity pl) W_WeaponState_Check = { } void (float inp) W_ChangeWeapon = { - if (inp < 1 || inp > GetLastWeaponImpulse()) return; @@ -2595,9 +2595,9 @@ void (float inp) W_ChangeWeapon = { self.queue_weaponslot = inp; // halt if weapon is not ready to be fired - if (!WeaponReady(self)) + if (!WeaponReady(self) && chweap_wait_attfinished) return; - + if (IsUsingOldImpulses()) { // check for ammo if (! W_OldAmmoSlot(inp)) { @@ -3002,22 +3002,25 @@ void () DeadImpulses = { self.current_menu_page = 1; Menu_Admin(); } - else if (self.impulse == TF_ADMIN_FORCESTARTMATCH) + else if (self.impulse == TF_ADMIN_FORCESTARTMATCH) { StartTimer(); + } else if (self.impulse == TF_ADMIN_READYSTATUS) Broadcast_Players_NotReady(); } if (self.impulse == TF_HELP_MAP) TeamFortress_HelpMap(); + else if (self.impulse == TF_NAILGREN_INFO) + TeamFortress_NailGrenInfo(); else if (self.impulse == TF_STATUS_QUERY) TeamFortress_StatusQuery(); - else if (self.impulse == TF_TEAM_1) + else if (self.impulse == TF_TEAM_1 && number_of_teams > 0) TeamFortress_TeamSet(1); - else if (self.impulse == TF_TEAM_2) + else if (self.impulse == TF_TEAM_2 && number_of_teams > 1) TeamFortress_TeamSet(2); - else if (self.impulse == TF_TEAM_3) + else if (self.impulse == TF_TEAM_3 && number_of_teams > 2) TeamFortress_TeamSet(3); - else if (self.impulse == TF_TEAM_4) + else if (self.impulse == TF_TEAM_4 && number_of_teams > 3) TeamFortress_TeamSet(4); else if (self.impulse == TF_TEAM_SCORES) TeamFortress_TeamShowScores(0); @@ -3158,17 +3161,23 @@ void () W_WeaponFrame = { } // slot 1-4 (or 1-7) binds - if (self.impulse >= 1 && self.impulse <= GetLastWeaponImpulse() && WeaponReady(self) + if (self.impulse >= 1 && self.impulse <= GetLastWeaponImpulse() && (WeaponReady(self) || !chweap_wait_attfinished) && !self.is_building && !self.is_detpacking) { - // load weapon state if current state doesn't match stored state - if (!W_WeaponState_Check(self)) - W_WeaponState_Load(self, 0); - - // obviously not quickfiring if we're changing weapon - self.is_quickfiring = 0; - self.has_quickfired = 0; - W_ChangeWeapon(self.impulse); + if (!(self.tfstate & TFSTATE_RELOADING)) { + // load weapon state if current state doesn't match stored state + if (!W_WeaponState_Check(self)) + W_WeaponState_Load(self, 0); + + // obviously not quickfiring if we're changing weapon + self.is_quickfiring = 0; + self.has_quickfired = 0; + W_ChangeWeapon(self.impulse); + } + else if (!chweap_wait_attfinished) { + //clears impulse so it doesn't switch weapons just after reloading + self.impulse = 0; + } // regular attack (both +attack and -attack) } else if (!self.impulse && !self.is_quickfiring) { diff --git a/world.qc b/world.qc index 460b1f5e..c4b385f1 100644 --- a/world.qc +++ b/world.qc @@ -122,6 +122,8 @@ void () worldspawn = { WriteByte(MSG_INIT, 9/*svc_stufftext*/); WriteString(MSG_INIT, "set fo_serverscripts 1\n"); + loadloc(); + local string st; lastspawn = world;