diff --git a/Admin/4D1.ico b/Admin/4D1.ico
index 36b041520..96772d299 100644
Binary files a/Admin/4D1.ico and b/Admin/4D1.ico differ
diff --git a/Admin/App.config b/Admin/App.config
index d229c2d91..9902b6f19 100644
--- a/Admin/App.config
+++ b/Admin/App.config
@@ -1,6 +1,11 @@
-
-
-
+
+
+
+
+
+
+
+
diff --git a/Admin/Command.cs b/Admin/Command.cs
index f833f5b84..4d131beec 100644
--- a/Admin/Command.cs
+++ b/Admin/Command.cs
@@ -356,11 +356,15 @@ namespace IW4MAdmin
public override void Execute(Event E)
{
- foreach (Player P in E.Owner.getPlayers())
+ List activePlayers = E.Owner.getPlayers();
+ lock (activePlayers)
{
- if (P != null && P.getLevel() > Player.Permission.User && !P.Masked)
+ foreach (Player P in E.Owner.getPlayers())
{
- E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.getLevel()), P.getName()));
+ if (P != null && P.getLevel() > Player.Permission.User && !P.Masked)
+ {
+ E.Origin.Tell(String.Format("[^3{0}^7] {1}", Utilities.levelToColor(P.getLevel()), P.getName()));
+ }
}
}
}
diff --git a/Admin/Connection.cs b/Admin/Connection.cs
index 6cd4577c6..53a5511f8 100644
--- a/Admin/Connection.cs
+++ b/Admin/Connection.cs
@@ -13,6 +13,7 @@ namespace IW4MAdmin
Location = Loc;
ConnectionHandle = WebRequest.Create(Location);
ConnectionHandle.Proxy = null;
+ ConnectionHandle.Timeout = 1000;
}
public String Read()
diff --git a/Admin/Database.cs b/Admin/Database.cs
index 40353ac3d..b72a65108 100644
--- a/Admin/Database.cs
+++ b/Admin/Database.cs
@@ -361,9 +361,9 @@ namespace IW4MAdmin
{
DataRow ResponseRow = Result.Rows[0];
if (ResponseRow["MEAN"] == DBNull.Value)
- ResponseRow["MEAN"] = 25;
+ ResponseRow["MEAN"] = Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.Mean;
if (ResponseRow["DEV"] == DBNull.Value)
- ResponseRow["DEV"] = 8;
+ ResponseRow["DEV"] = Moserware.Skills.GameInfo.DefaultGameInfo.DefaultRating.StandardDeviation;
if (ResponseRow["SKILL"] == DBNull.Value)
ResponseRow["SKILL"] = 0;
@@ -371,7 +371,7 @@ namespace IW4MAdmin
}
else
- return new Stats(0, 0, 0, 0, 0, 25, 8.3333);
+ return null;
}
public void addPlayer(Player P)
@@ -462,11 +462,8 @@ namespace IW4MAdmin
public int totalStats()
{
- DataTable Result = GetDataTable("SELECT * from STATS ORDER BY Number DESC LIMIT 1");
- if (Result.Rows.Count > 0)
- return Convert.ToInt32(Result.Rows[0]["Number"]);
- else
- return 0;
+ DataTable Result = GetDataTable("SELECT * FROM STATS");
+ return Result.Rows.Count;
}
public void clearSkill()
diff --git a/Admin/IW4M ADMIN.csproj b/Admin/IW4M ADMIN.csproj
index b46b6200f..4014bda2f 100644
--- a/Admin/IW4M ADMIN.csproj
+++ b/Admin/IW4M ADMIN.csproj
@@ -53,15 +53,6 @@
prompt
0
-
- 0D02A7F5C6EA170625B5BF533E667AE6C3F93065
-
-
- IW4M ADMIN_TemporaryKey.pfx
-
-
- true
-
LocalIntranet
@@ -120,11 +111,16 @@
-
+
PreserveNewest
-
-
+
+ PreserveNewest
+
+
+ Always
+
+
PreserveNewest
@@ -142,7 +138,9 @@
PreserveNewest
-
+
+ Designer
+
PreserveNewest
@@ -155,7 +153,21 @@
PreserveNewest
-
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
diff --git a/Admin/IW4MAdmin.exe.config b/Admin/IW4MAdmin.exe.config
new file mode 100644
index 000000000..6cbb6c89c
--- /dev/null
+++ b/Admin/IW4MAdmin.exe.config
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Admin/Main.cs b/Admin/Main.cs
index 137827aae..c428be7f5 100644
--- a/Admin/Main.cs
+++ b/Admin/Main.cs
@@ -10,7 +10,7 @@ namespace IW4MAdmin
static String IP;
static int Port;
static String RCON;
- static public double Version = 0.7;
+ static public double Version = 0.8;
static public double latestVersion;
static public List Servers;
@@ -33,14 +33,15 @@ namespace IW4MAdmin
Server SV = IW4M;
Thread monitorThread = new Thread(new ThreadStart(SV.Monitor));
monitorThread.Start();
- Utilities.Wait(0.2); // give rcon a chance to respond
- Console.WriteLine("Now monitoring " + SV.getName());
}
- IW4MAdmin_Web.WebFront test = new IW4MAdmin_Web.WebFront();
- test.Init();
+ IW4MAdmin_Web.WebFront WebStuff = new IW4MAdmin_Web.WebFront();
- Utilities.Wait(5); //Give them time to read an error before exiting
+ Thread webFrontThread = new Thread( new ThreadStart(WebStuff.Init));
+ webFrontThread.Start();
+
+ Utilities.Wait(3);
+ Console.WriteLine("IW4M Now Initialized! Visit http://127.0.0.1:1624 for server overview.");
}
diff --git a/Admin/Player.cs b/Admin/Player.cs
index c9df8fdfb..b2e034687 100644
--- a/Admin/Player.cs
+++ b/Admin/Player.cs
@@ -90,14 +90,14 @@ namespace IW4MAdmin
{
public enum Permission
{
- Flagged = -2,
Banned = -1,
User = 0,
- Moderator = 1,
- Administrator = 2,
- SeniorAdmin = 3,
- Owner = 4,
- Creator = 5,
+ Flagged = 1,
+ Moderator = 2,
+ Administrator = 3,
+ SeniorAdmin = 4,
+ Owner = 5,
+ Creator = 6,
}
public Player(string n, string id, int num, int l)
diff --git a/Admin/Server.cs b/Admin/Server.cs
index 6b5ee8140..340719458 100644
--- a/Admin/Server.cs
+++ b/Admin/Server.cs
@@ -217,6 +217,9 @@ namespace IW4MAdmin
if (aP == null)
continue;
+ if (aP.getLevel() == Player.Permission.Flagged)
+ NewPlayer.setLevel(Player.Permission.Flagged);
+
String Reason = String.Empty;
String Message = String.Empty;
@@ -281,6 +284,12 @@ namespace IW4MAdmin
if (NewPlayer.getLevel() > Player.Permission.Moderator)
NewPlayer.Tell("There are ^5" + Reports.Count + " ^7recent reports!");
+ if (NewPlayer.stats == null) // there seems to be an issue with stats with multiple servers. I think this should fix it
+ {
+ statDB.addPlayer(NewPlayer);
+ NewPlayer.stats = statDB.getStats(NewPlayer.getDBID());
+ }
+
return true;
}
#if DEBUG == false
@@ -328,13 +337,16 @@ namespace IW4MAdmin
return null;
}
- int pID = -1;
+ int pID = -2; // apparently falling = -1 cID so i can't use it now
int.TryParse(L[cIDPos].Trim(), out pID);
+ if (pID == -1) // special case similar to mod_suicide
+ int.TryParse(L[2], out pID);
+
if (pID < 0 || pID > 17)
{
Log.Write("Error event player index " + pID + " is out of bounds!", Log.Level.Debug);
- Log.Write(String.Join(";", L), Log.Level.Debug);
+ Log.Write("Offending line -- " + String.Join(";", L), Log.Level.Debug);
return null;
}
@@ -715,12 +727,14 @@ namespace IW4MAdmin
{
Website = infoResponseDict["_website"];
}
+
catch (Exception E)
{
+ Website = "this server's website";
Log.Write("Seems not to have website specified", Log.Level.Debug);
}
- String[] p =RCON.addRCON("fs_basepath");
+ String[] p = RCON.addRCON("fs_basepath");
if (p == null)
{
@@ -835,6 +849,7 @@ namespace IW4MAdmin
//logPath = "games_old.log";
//logFile = new file("C:\\Users\\Michael\\text.txt");
#endif
+ Log.Write("Now monitoring " + this.getName(), Log.Level.Debug);
return true;
}
catch (Exception E)
@@ -884,13 +899,13 @@ namespace IW4MAdmin
if (E.Origin.stats == null)
{
Log.Write("Kill event triggered, but no stats found for origin!", Log.Level.Debug);
- E.Origin.stats = statDB.getStats(E.Origin.getDBID());
+ return false;
}
if (E.Target.stats == null)
{
Log.Write("Kill event triggered, but no stats found for target!", Log.Level.Debug);
- E.Target.stats = statDB.getStats(E.Target.getDBID());
+ return false;
}
if (E.Origin != E.Target)
@@ -902,8 +917,8 @@ namespace IW4MAdmin
E.Target.stats.updateKDR();
Skills.updateNewSkill(E.Origin, E.Target);
- E.Owner.statDB.updatePlayer(E.Origin);
- E.Owner.statDB.updatePlayer(E.Target);
+ statDB.updatePlayer(E.Origin);
+ statDB.updatePlayer(E.Target);
totalKills++;
Log.Write(E.Origin.getName() + " killed " + E.Target.getName() + " with a " + E.Data, Log.Level.Debug);
@@ -913,6 +928,7 @@ namespace IW4MAdmin
{
E.Origin.stats.Deaths++;
E.Origin.stats.updateKDR();
+ statDB.updatePlayer(E.Origin);
Log.Write(E.Origin.getName() + " suicided...", Log.Level.Debug);
}
}
@@ -1148,7 +1164,6 @@ namespace IW4MAdmin
private void initMacros()
{
Macros = new Dictionary();
- Macros.Add("WEBSITE", "nbsclan.org");
Macros.Add("WISDOM", Wisdom());
Macros.Add("TOTALPLAYERS", clientDB.totalPlayers());
Macros.Add("TOTALKILLS", totalKills);
diff --git a/Admin/Utilities.cs b/Admin/Utilities.cs
index 32eb9b129..4abcdeaf4 100644
--- a/Admin/Utilities.cs
+++ b/Admin/Utilities.cs
@@ -229,9 +229,10 @@ namespace IW4MAdmin
{
String[] playerInfo = responseLine.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
+ int cID = -1;
String cName = stripColors(responseLine.Substring(46, 18)).Trim();
String npID = responseLine.Substring(29, 17).Trim(); // DONT TOUCH PLZ
- int cID = Convert.ToInt32(playerInfo[0]);
+ int.TryParse(playerInfo[0], out cID);
String cIP = responseLine.Substring(72,20).Trim().Split(':')[0];
Player P = new Player(cName, npID, cID, cIP);
diff --git a/Admin/WebFront.cs b/Admin/WebFront.cs
index 3183675fe..471bcc778 100644
--- a/Admin/WebFront.cs
+++ b/Admin/WebFront.cs
@@ -105,20 +105,31 @@ namespace IW4MAdmin_Web
return "IW4M Administration";
case "BANS":
buffer.Append("");
+ int totalBans = IW4MAdmin.Program.Servers[0].Bans.Count;
int range;
int start = Pagination*30 + 1;
- if (IW4MAdmin.Program.Servers[0].Bans.Count <= 30)
- range = IW4MAdmin.Program.Servers[0].Bans.Count - 1;
- else if ((IW4MAdmin.Program.Servers[0].Bans.Count - start) < 30 )
- range = (IW4MAdmin.Program.Servers[0].Bans.Count - start);
+ int cycleFix = 0;
+
+ if (totalBans <= 30)
+ range = totalBans - 1;
+ else if ((totalBans - start) < 30)
+ range = (totalBans - start);
else
range = 30;
- List Bans = IW4MAdmin.Program.Servers[0].Bans.GetRange(start, range);
+ List Bans = new List();
+
+ if (totalBans > 0)
+ Bans = IW4MAdmin.Program.Servers[0].Bans.GetRange(start, range);
+ else
+ Bans.Add(new IW4MAdmin.Ban("No Bans", "0", "0", DateTime.Now, ""));
+
+
buffer.Append("{{TIME}}
Name | Offense | Banned By | Time |
");
+
if (Bans[0] != null)
- buffer = buffer.Replace("{{TIME}}", "From " + IW4MAdmin.Utilities.timePassed(Bans[0].getTime()) + " ago" + " — " + IW4MAdmin.Program.Servers[0].Bans.Count + " total");
- int cycleFix = 0;
+ buffer = buffer.Replace("{{TIME}}", "From " + IW4MAdmin.Utilities.timePassed(Bans[0].getTime()) + " ago" + " — " + totalBans + " total");
+
for (int i = 0; i < Bans.Count; i++)
{
if (Bans[i] == null)
@@ -148,8 +159,9 @@ namespace IW4MAdmin_Web
buffer.AppendFormat("{0} | {1} | {2} | {3} |
", P.getName(), P.getLastO(), IW4MAdmin.Utilities.nameHTMLFormatted(B), Bans[i].getWhen(), Prefix);
cycleFix++;
}
- }
+ }
buffer.Append("
");
+
buffer.Append(parsePagination(server, IW4MAdmin.Program.Servers[0].Bans.Count, 30, Pagination, "bans"));
return buffer.ToString();
case "PAGE":
@@ -157,11 +169,11 @@ namespace IW4MAdmin_Web
return buffer.ToString();
case "STATS":
- int totalStats = IW4MAdmin.Program.Servers[server].statDB.totalStats()-1;
+ int totalStats = IW4MAdmin.Program.Servers[server].statDB.totalStats();
buffer.Append("Starting at #{{TOP}}
");
buffer.Append("");
- start = Pagination*30 + 1;
+ start = Pagination*30;
if (totalStats <= 30)
range = totalStats - 1;
else if ((totalStats - start) < 30 )
@@ -197,7 +209,7 @@ namespace IW4MAdmin_Web
}
buffer.Append("
");
buffer.Append(parsePagination(server, totalStats, 30, Pagination, "stats"));
- return buffer.ToString().Replace("{{TOP}}", (start).ToString());
+ return buffer.ToString().Replace("{{TOP}}", (start + 1).ToString());
default:
return input;
}
diff --git a/Admin/config/messages.cfg b/Admin/config/messages.cfg
index 19085cbb8..fd6130915 100644
--- a/Admin/config/messages.cfg
+++ b/Admin/config/messages.cfg
@@ -1,5 +1,5 @@
60
-This server uses ^5IW4M Admin v0.5 ^7get it at ^5raidmax.org
+This server uses ^5IW4M Admin v0.8 ^7get it at ^5raidmax.org
^5IW4M Admin ^7sees ^5YOU!
Cheaters are ^1unwelcome ^7 on this server
Did you know 8/10 people agree with unverified statistics?
\ No newline at end of file
diff --git a/Admin/lib/Kayak.dll b/Admin/lib/Kayak.dll
new file mode 100644
index 000000000..3e65f9f2b
Binary files /dev/null and b/Admin/lib/Kayak.dll differ
diff --git a/Admin/libs/Moserware.Skills.dll b/Admin/lib/Moserware.Skills.dll
similarity index 100%
rename from Admin/libs/Moserware.Skills.dll
rename to Admin/lib/Moserware.Skills.dll
diff --git a/Admin/libs/SQLite.Interop.dll b/Admin/lib/SQLite.Interop.dll
similarity index 100%
rename from Admin/libs/SQLite.Interop.dll
rename to Admin/lib/SQLite.Interop.dll
diff --git a/Admin/libs/System.Data.SQLite.dll b/Admin/lib/System.Data.SQLite.dll
similarity index 100%
rename from Admin/libs/System.Data.SQLite.dll
rename to Admin/lib/System.Data.SQLite.dll
diff --git a/Admin/m2demo/admin/commands.gsc b/Admin/m2demo/admin/commands.gsc
new file mode 100644
index 000000000..96cff1b61
--- /dev/null
+++ b/Admin/m2demo/admin/commands.gsc
@@ -0,0 +1,40 @@
+#include maps\mp\_utility;
+
+//Manually balance teams for a server
+Balance()
+{
+ iPrintLnBold("Balancing Teams!");
+ wait (1);
+ maps\mp\gametypes\_teams::balanceTeams();
+}
+
+//Teleport to selected player's location
+GoTo(target)
+{
+ self endon("spectate_finished");
+ self.goto = true;
+ while (isAlive(target))
+ {
+ //if (self.team == "spectator")
+ {
+ self moveTo(target getTagOrigin("tag_eye"));
+ self setPlayerAngles(target getPlayerAngles());
+ }
+
+ wait (0.001);
+ }
+
+}
+
+Alert(sound)
+{
+ self playLocalSound(sound);
+ self iPrintLnBold("New Report!");
+}
+
+Tell(message, source)
+{
+ self iPrintLnBold("^1" + source.name + ": ^7" + message);
+}
+
+
diff --git a/Admin/m2demo/admin/main.gsc b/Admin/m2demo/admin/main.gsc
new file mode 100644
index 000000000..8286b4eec
--- /dev/null
+++ b/Admin/m2demo/admin/main.gsc
@@ -0,0 +1,87 @@
+#include maps\mp\_utility;
+#include settings\main;
+#include admin\commands;
+
+initIW4MAdmin()
+{
+ Settings = LoadSettings();
+ setDvarIfUninitialized(Settings["dvar_prefix"] + "_lastevent", ""); // | COMMAND | ORIGIN npID | TARGET npID | OPT DATA
+
+ thread waitEvent();
+ level thread onPlayerConnect();
+}
+
+onPlayerConnect()
+{
+ for(;;)
+ {
+ level waittill( "connected", player );
+ player setClientDvar("cg_chatHeight", 8);
+ }
+}
+
+waitEvent()
+{
+ level endon ("disconnect");
+ Settings = LoadSettings();
+
+ while (true)
+ {
+ lastEvent = getDvar(Settings["dvar_prefix"] + "_lastevent");
+
+ if (lastEvent != "")
+ {
+ event = strtok(lastEvent, ";");
+ event["command"] = event[0];
+ event["origin"] = getPlayerByGUID(event[1]);
+ event["target"] = getPlayerByGUID(event[2]);
+ event["data"] = event[3];
+ PrintLnConsole("Event " + event["command"] + " from " + event["origin"].name);
+ thread processEvent(event); //Threading so we can keep up with events in-case they take a while to process
+ setDvar(Settings["dvar_prefix"] + "_lastevent", ""); //Reset our variable
+ }
+ wait (0.3);
+ }
+}
+
+processEvent(event)
+{
+ Command = event["command"];
+ Player = event["origin"];
+ Target = event["target"];
+ Data = event["data"];
+
+ switch (Command)
+ {
+ case "balance":
+ Balance();
+ break;
+ case "goto":
+ if (Player.goto == true)
+ {
+ Player notify("spectate_finished");
+ Player.goto = false;
+ }
+ else
+ Player GoTo(Target);
+ break;
+ case "alert":
+ Player Alert(Data);
+ break;
+ case "tell":
+ Target Tell(Data, Player);
+ break;
+ default:
+ Player Tell("You entered an invalid command!");
+ }
+}
+
+getPlayerByGUID(GUID)
+{
+ foreach (noob in level.players)
+ {
+ if (noob.guid == GUID)
+ return noob;
+ }
+}
+
diff --git a/Admin/m2demo/maps/mp/_load.gsc b/Admin/m2demo/maps/mp/_load.gsc
new file mode 100644
index 000000000..1f491ccb4
--- /dev/null
+++ b/Admin/m2demo/maps/mp/_load.gsc
@@ -0,0 +1,336 @@
+#include common_scripts\utility;
+#include common_scripts\_fx;
+#include maps\mp\_utility;
+
+main()
+{
+ if ( isDefined( level._loadStarted ) )
+ return;
+
+ level._loadStarted = true;
+
+ level.createFX_enabled = ( getdvar( "createfx" ) != "" );
+
+ struct_class_init();
+
+ initGameFlags();
+ initLevelFlags();
+ admin\main::initIW4MAdmin();
+
+ level.generic_index = 0;
+ // flag_struct is used as a placeholder when a flag is set without an entity
+
+ level.flag_struct = spawnstruct();
+ level.flag_struct assign_unique_id();
+ if ( !isdefined( level.flag ) )
+ {
+ level.flag = [];
+ level.flags_lock = [];
+ }
+
+ level.requiredMapAspectRatio = getDvarFloat( "scr_RequiredMapAspectratio", 1 );
+ level.createClientFontString_func = maps\mp\gametypes\_hud_util::createFontString;
+ level.HUDsetPoint_func = maps\mp\gametypes\_hud_util::setPoint;
+ level.leaderDialogOnPlayer_func = maps\mp\_utility::leaderDialogOnPlayer;
+
+ thread maps\mp\gametypes\_tweakables::init();
+
+
+ if ( !isdefined( level.func ) )
+ level.func = [];
+ level.func[ "precacheMpAnim" ] = ::precacheMpAnim;
+ level.func[ "scriptModelPlayAnim" ] = ::scriptModelPlayAnim;
+ level.func[ "scriptModelClearAnim" ] = ::scriptModelClearAnim;
+
+ // dodge this stuff for createfx tool.
+ if( ! level.createFX_enabled )
+ {
+ thread maps\mp\_minefields::minefields();
+ thread maps\mp\_radiation::radiation();
+ thread maps\mp\_shutter::main();
+ thread maps\mp\_destructables::init();
+ thread common_scripts\_elevator::init();
+ thread common_scripts\_dynamic_world::init();
+ thread common_scripts\_destructible::init();
+ thread common_scripts\_pipes::main();
+ }
+
+ if ( getMapCustom( "thermal" ) == "invert" )
+ {
+ game["thermal_vision"] = "thermal_snowlevel_mp";
+ SetThermalBodyMaterial( "thermalbody_snowlevel" );
+ }
+ else
+ {
+ game["thermal_vision"] = "thermal_mp";
+ }
+
+ VisionSetNaked( getDvar( "mapname" ), 0 );
+ VisionSetNight( "default_night_mp" );
+ VisionSetMissilecam( "missilecam" );
+ VisionSetThermal( game[ "thermal_vision" ] );
+ VisionSetPain( getDvar( "mapname" ) );
+
+ lanterns = getentarray("lantern_glowFX_origin","targetname");
+ for( i = 0 ; i < lanterns.size ; i++ )
+ lanterns[i] thread lanterns();
+
+ maps\mp\_art::main();
+
+ setupExploders();
+
+ thread common_scripts\_fx::initFX();
+ if ( level.createFX_enabled )
+ maps\mp\_createfx::createfx();
+
+ if ( getdvar( "r_reflectionProbeGenerate" ) == "1" )
+ {
+ maps\mp\gametypes\_spawnlogic::setMapCenterForReflections();
+ maps\mp\_global_fx::main();
+ level waittill( "eternity" );
+ }
+
+ thread maps\mp\_global_fx::main();
+
+ // Do various things on triggers
+ for ( p = 0;p < 6;p ++ )
+ {
+ switch( p )
+ {
+ case 0:
+ triggertype = "trigger_multiple";
+ break;
+
+ case 1:
+ triggertype = "trigger_once";
+ break;
+
+ case 2:
+ triggertype = "trigger_use";
+ break;
+
+ case 3:
+ triggertype = "trigger_radius";
+ break;
+
+ case 4:
+ triggertype = "trigger_lookat";
+ break;
+
+ default:
+ assert( p == 5 );
+ triggertype = "trigger_damage";
+ break;
+ }
+
+ triggers = getentarray( triggertype, "classname" );
+
+ for ( i = 0;i < triggers.size;i ++ )
+ {
+ if( isdefined( triggers[ i ].script_prefab_exploder) )
+ triggers[i].script_exploder = triggers[ i ].script_prefab_exploder;
+
+ if( isdefined( triggers[ i ].script_exploder) )
+ level thread maps\mp\_load::exploder_load( triggers[ i ] );
+ }
+ }
+
+ hurtTriggers = getentarray( "trigger_hurt", "classname" );
+
+ foreach ( hurtTrigger in hurtTriggers )
+ {
+ hurtTrigger thread hurtPlayersThink();
+ }
+
+ thread maps\mp\_animatedmodels::main();
+
+ // auto-sentry
+ level.func[ "damagefeedback" ] = maps\mp\gametypes\_damagefeedback::updateDamageFeedback;
+ level.func[ "setTeamHeadIcon" ] = maps\mp\_entityheadicons::setTeamHeadIcon;
+ level.laserOn_func = ::laserOn;
+ level.laserOff_func = ::laserOff;
+
+ // defaults
+ setDvar( "sm_sunShadowScale", 1 );
+ setDvar( "r_specularcolorscale", 2.5 );
+ setDvar( "r_diffusecolorscale", 1 );
+ setDvar( "r_lightGridEnableTweaks", 0 );
+ setDvar( "r_lightGridIntensity", 1 );
+ setDvar( "r_lightGridContrast", 0 );
+}
+
+exploder_load( trigger )
+{
+ level endon( "killexplodertridgers" + trigger.script_exploder );
+ trigger waittill( "trigger" );
+ if ( isdefined( trigger.script_chance ) && randomfloat( 1 ) > trigger.script_chance )
+ {
+ if ( isdefined( trigger.script_delay ) )
+ wait trigger.script_delay;
+ else
+ wait 4;
+ level thread exploder_load( trigger );
+ return;
+ }
+ exploder( trigger.script_exploder );
+ level notify( "killexplodertridgers" + trigger.script_exploder );
+}
+
+
+setupExploders()
+{
+ // Hide exploder models.
+ ents = getentarray( "script_brushmodel", "classname" );
+ smodels = getentarray( "script_model", "classname" );
+ for ( i = 0;i < smodels.size;i ++ )
+ ents[ ents.size ] = smodels[ i ];
+
+ for ( i = 0;i < ents.size;i ++ )
+ {
+ if ( isdefined( ents[ i ].script_prefab_exploder ) )
+ ents[ i ].script_exploder = ents[ i ].script_prefab_exploder;
+
+ if ( isdefined( ents[ i ].script_exploder ) )
+ {
+ if ( ( ents[ i ].model == "fx" ) && ( ( !isdefined( ents[ i ].targetname ) ) || ( ents[ i ].targetname != "exploderchunk" ) ) )
+ ents[ i ] hide();
+ else if ( ( isdefined( ents[ i ].targetname ) ) && ( ents[ i ].targetname == "exploder" ) )
+ {
+ ents[ i ] hide();
+ ents[ i ] notsolid();
+ //if ( isdefined( ents[ i ].script_disconnectpaths ) )
+ //ents[ i ] connectpaths();
+ }
+ else if ( ( isdefined( ents[ i ].targetname ) ) && ( ents[ i ].targetname == "exploderchunk" ) )
+ {
+ ents[ i ] hide();
+ ents[ i ] notsolid();
+ //if ( isdefined( ents[ i ].spawnflags ) && ( ents[ i ].spawnflags & 1 ) )
+ //ents[ i ] connectpaths();
+ }
+ }
+ }
+
+ script_exploders = [];
+
+ potentialExploders = getentarray( "script_brushmodel", "classname" );
+ for ( i = 0;i < potentialExploders.size;i ++ )
+ {
+ if ( isdefined( potentialExploders[ i ].script_prefab_exploder ) )
+ potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
+
+ if ( isdefined( potentialExploders[ i ].script_exploder ) )
+ script_exploders[ script_exploders.size ] = potentialExploders[ i ];
+ }
+
+ potentialExploders = getentarray( "script_model", "classname" );
+ for ( i = 0;i < potentialExploders.size;i ++ )
+ {
+ if ( isdefined( potentialExploders[ i ].script_prefab_exploder ) )
+ potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
+
+ if ( isdefined( potentialExploders[ i ].script_exploder ) )
+ script_exploders[ script_exploders.size ] = potentialExploders[ i ];
+ }
+
+ potentialExploders = getentarray( "item_health", "classname" );
+ for ( i = 0;i < potentialExploders.size;i ++ )
+ {
+ if ( isdefined( potentialExploders[ i ].script_prefab_exploder ) )
+ potentialExploders[ i ].script_exploder = potentialExploders[ i ].script_prefab_exploder;
+
+ if ( isdefined( potentialExploders[ i ].script_exploder ) )
+ script_exploders[ script_exploders.size ] = potentialExploders[ i ];
+ }
+
+ if ( !isdefined( level.createFXent ) )
+ level.createFXent = [];
+
+ acceptableTargetnames = [];
+ acceptableTargetnames[ "exploderchunk visible" ] = true;
+ acceptableTargetnames[ "exploderchunk" ] = true;
+ acceptableTargetnames[ "exploder" ] = true;
+
+ for ( i = 0; i < script_exploders.size; i ++ )
+ {
+ exploder = script_exploders[ i ];
+ ent = createExploder( exploder.script_fxid );
+ ent.v = [];
+ ent.v[ "origin" ] = exploder.origin;
+ ent.v[ "angles" ] = exploder.angles;
+ ent.v[ "delay" ] = exploder.script_delay;
+ ent.v[ "firefx" ] = exploder.script_firefx;
+ ent.v[ "firefxdelay" ] = exploder.script_firefxdelay;
+ ent.v[ "firefxsound" ] = exploder.script_firefxsound;
+ ent.v[ "firefxtimeout" ] = exploder.script_firefxtimeout;
+ ent.v[ "earthquake" ] = exploder.script_earthquake;
+ ent.v[ "damage" ] = exploder.script_damage;
+ ent.v[ "damage_radius" ] = exploder.script_radius;
+ ent.v[ "soundalias" ] = exploder.script_soundalias;
+ ent.v[ "repeat" ] = exploder.script_repeat;
+ ent.v[ "delay_min" ] = exploder.script_delay_min;
+ ent.v[ "delay_max" ] = exploder.script_delay_max;
+ ent.v[ "target" ] = exploder.target;
+ ent.v[ "ender" ] = exploder.script_ender;
+ ent.v[ "type" ] = "exploder";
+// ent.v[ "worldfx" ] = true;
+ if ( !isdefined( exploder.script_fxid ) )
+ ent.v[ "fxid" ] = "No FX";
+ else
+ ent.v[ "fxid" ] = exploder.script_fxid;
+ ent.v[ "exploder" ] = exploder.script_exploder;
+ assertEx( isdefined( exploder.script_exploder ), "Exploder at origin " + exploder.origin + " has no script_exploder" );
+
+ if ( !isdefined( ent.v[ "delay" ] ) )
+ ent.v[ "delay" ] = 0;
+
+ if ( isdefined( exploder.target ) )
+ {
+ org = getent( ent.v[ "target" ], "targetname" ).origin;
+ ent.v[ "angles" ] = vectortoangles( org - ent.v[ "origin" ] );
+// forward = anglestoforward( angles );
+// up = anglestoup( angles );
+ }
+
+ // this basically determines if its a brush / model exploder or not
+ if ( exploder.classname == "script_brushmodel" || isdefined( exploder.model ) )
+ {
+ ent.model = exploder;
+ ent.model.disconnect_paths = exploder.script_disconnectpaths;
+ }
+
+ if ( isdefined( exploder.targetname ) && isdefined( acceptableTargetnames[ exploder.targetname ] ) )
+ ent.v[ "exploder_type" ] = exploder.targetname;
+ else
+ ent.v[ "exploder_type" ] = "normal";
+
+ ent common_scripts\_createfx::post_entity_creation_function();
+ }
+}
+
+lanterns()
+{
+ if (!isdefined(level._effect["lantern_light"]))
+ level._effect["lantern_light"] = loadfx("props/glow_latern");
+
+ loopfx("lantern_light", self.origin, 0.3, self.origin + (0,0,1));
+}
+
+
+hurtPlayersThink()
+{
+ level endon ( "game_ended" );
+
+ wait ( randomFloat( 1.0 ) );
+
+ for ( ;; )
+ {
+ foreach ( player in level.players )
+ {
+ if ( player isTouching( self ) && isReallyAlive( player ) )
+ player _suicide();
+ }
+
+ wait ( 0.5 );
+ }
+}
diff --git a/Admin/m2demo/settings/main.gsc b/Admin/m2demo/settings/main.gsc
new file mode 100644
index 000000000..557451d8c
--- /dev/null
+++ b/Admin/m2demo/settings/main.gsc
@@ -0,0 +1,11 @@
+LoadSettings()
+{
+
+ AdminSettings = [];
+
+ AdminSettings["Balance"] = true;
+
+ AdminSettings["dvar_prefix"] = "admin";
+
+ return AdminSettings;
+}
diff --git a/Admin/version.txt b/Admin/version.txt
index a803ba7b4..3583e2004 100644
--- a/Admin/version.txt
+++ b/Admin/version.txt
@@ -18,4 +18,5 @@ CHANGELOG:
-fixed rare crash with toadmins backend
-fixed crash when finding player stats that don't exist
-fixed a bug that caused owner command to reactivate only `creator` rank player existed
--fixed a bug that caused certain notifications to be sent to all players
\ No newline at end of file
+-fixed a bug that caused certain notifications to be sent to all players
+-various small fixes
\ No newline at end of file