07-25-2013, 14:19
Hi guys and girls,
This is an idea that I got from @MADD_DOGG who made a very valid point about campers who won't shoot when they are last in infected servers, so I decided to come up with my own design that solves a couple of issues that memory pointers have if your server has a limited amount of resource assigned to it and problems with the icon resetting on map change and fast restart.
PLEASE NOTE
I do not take responsibility for your server crashing if you use this plugin, memory pointers run in an unsafe context which are known to cause crashes.
So what does this plugin do?
This plugin is pretty much self explanatory, simply download the DLL, setup the sv_config.ini options for the icon and delay until the last human alive appears on the mini map. When you're in-game a timer will be started if there is one human left alive which will then trigger an icon to appear on everyone's mini map, upon this icon appearing on the mini map the built in timer in the addon plugin will keep looping over itself which constantly checks the total number of humans against the total number of infected players, if it finds there is more then one human left alive the icon will be deactivated and you will need to hunt down everyone until one human remains again.
What commands can I use?
See the below for the installation instructions.
Changelog:
Source Code:
Credits:
@8q4s8 - Waypoint plugin creator
@MADD_DOGG - For such a simple yet cool idea
@Nukem - For such a great code base to work with
Apart from that the plugin will work its magic in the background without any input been required by the client. Enjoy!
[attachment=2736][attachment=2713][attachment=2709]
This is an idea that I got from @MADD_DOGG who made a very valid point about campers who won't shoot when they are last in infected servers, so I decided to come up with my own design that solves a couple of issues that memory pointers have if your server has a limited amount of resource assigned to it and problems with the icon resetting on map change and fast restart.
PLEASE NOTE
I do not take responsibility for your server crashing if you use this plugin, memory pointers run in an unsafe context which are known to cause crashes.
So what does this plugin do?
This plugin is pretty much self explanatory, simply download the DLL, setup the sv_config.ini options for the icon and delay until the last human alive appears on the mini map. When you're in-game a timer will be started if there is one human left alive which will then trigger an icon to appear on everyone's mini map, upon this icon appearing on the mini map the built in timer in the addon plugin will keep looping over itself which constantly checks the total number of humans against the total number of infected players, if it finds there is more then one human left alive the icon will be deactivated and you will need to hunt down everyone until one human remains again.
What commands can I use?
Quote:!icon - Allows you to set what icon is visible in game
See the below for the installation instructions.
- Copy the configuration defaults below and place them in your sv_config.ini
- Enjoy!
Code:
[WhereIsShe]
// The default icon for the mini map
//
// Default: 40 = Skull
// Version: 0.1 BETA
Icon=40
// The delay between when one human is left alive until the icon appears on the mini map.
// This value is based on "seconds" and must be at least 1
//
// Default: 30
// Version: 0.1 BETA
Timer=30
// Set the following option to true if you only want the icon to appear based on player
// movements around the map, setting this will override the above timer value with the
// reset time below
//
// Default: false
// Accepts: true or false
// Version: 0.3 BETA
DetectMovement=false
// The amount of movement required in order for the mini map icon to be hidden once the
// last human begins moving again, the higher the number the longer it will take for the
// icon to disappear from the mini map
//
// Default: 100 = About 2-3 seconds of movement
// Version: 0.3 BETA
Threshold=100
// The amount of time until the icon reappears on the mini map after the last human stops
// moving again, again this overrides the original timer so make sure its a number that's
// fair for everyone in the game.
//
// This value is based on "seconds" and must be at least 1
//
// Default: 5
// Version: 0.3 BETA
ResetTime=5
Changelog:
Spoiler (Click to View)
v0.3
- Lots of re-factoring for the detect movement feature
- Addition of movement detection
- Bug fix for team detection, now correctly determines if the player is joining or if there are only 2 players on the server
- General code clean up
v0.2
- Cleaned up and simplified core methods/functions
- Merged Activate and Deactivate functions into one function
- Updated the team check to run individual loops so it doesn't stop when there is more than one human left alive
- General typo fixes
v0.1
- Initial BETA release
- Lots of re-factoring for the detect movement feature
- Addition of movement detection
- Bug fix for team detection, now correctly determines if the player is joining or if there are only 2 players on the server
- General code clean up
v0.2
- Cleaned up and simplified core methods/functions
- Merged Activate and Deactivate functions into one function
- Updated the team check to run individual loops so it doesn't stop when there is more than one human left alive
- General typo fixes
v0.1
- Initial BETA release
Source Code:
CSHARP Code
- using System;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Timers;
- using Addon;
-
- namespace WhereIsShe
- {
- public class Main : CPlugin
- {
- private IntPtr _activate, _icon, _originX, _originY;
- private float _x, _y;
- private Timer _lastManStanding;
- private Stopwatch _stopWatch;
- private Configuration _configuration;
-
- /// <summary>
- /// Executes when the MW3 server loads
- /// </summary>
- public override void OnServerLoad()
- {
- ServerPrint("\n[Where Is She] Created by SgtLegend. Version 0.3 BETA");
- ServerPrint("[Where Is She] Code from waypoint plugin created by 8q4s8");
-
- // Grab the configuration for the icon
- _configuration = new Configuration
- {
- IconNumber = int.Parse(GetServerCFG("WhereIsShe", "Icon", "40")),
- GirlyTime = int.Parse(GetServerCFG("WhereIsShe", "Timer", "30")),
- DetectMovement = bool.Parse(GetServerCFG("WhereIsShe", "DetectMovement", "false")),
- Threshold = int.Parse(GetServerCFG("WhereIsShe", "Threshold", "30")),
- ResetTime = int.Parse(GetServerCFG("WhereIsShe", "ResetTime", "5"))
- };
-
- // Memory pointers found by 8q4s8
- _activate = (IntPtr) Convert.ToInt32(0x01B1EE9C);
- _icon = (IntPtr) Convert.ToInt32(0x01B1EEBC);
- _originX = (IntPtr) Convert.ToInt32(0x01B1EEA0);
- _originY = (IntPtr) Convert.ToInt32(0x01B1EEA4);
-
- // Set the initial icon
- ChangeIcon();
-
- // Create a new stop watch so we can track the amount of time that the girl has been camping
- // in a corner for
-
- // Create a new timer which can be re-used as many times as its needed
- _lastManStanding = new Timer
- {
- Enabled = false,
- Interval = 500
- };
-
- _lastManStanding.Elapsed += FindTheGirl;
- }
-
- /// <summary>
- /// Executes when the addon frame base method gets called
- /// </summary>
- public override void OnAddonFrame()
- {
- try
- {
-
- // Update the total number of clients on the server
- _gameStats.ClientsTotal = clients.Count;
- _gameStats.ClientsInfected = 0;
-
- // Go through all the clients on the server and increment the total number of infected
- // players so can determine if there is one player left alive
- if (clients.Count == 0) return;
-
- foreach (ServerClient client in clients)
- {
- switch (client.Team)
- {
- case Teams.Axis:
- _gameStats.ClientsInfected++;
- break;
-
- case Teams.Allies:
- _gameStats.ClientsHuman++;
- break;
- }
- }
-
- // Now check the number of infected players against the number of humans remaining in the
- // game, if the total number of clients minus the total number of zombies equals one then
- // we can be sure that we need to seek out the girl
- if ((_gameStats.ClientsTotal - _gameStats.ClientsInfected) == 1 ||
- (_gameStats.ClientsHuman == 1 && _gameStats.ClientsInfected == 1))
- {
- foreach (ServerClient client in clients)
- {
- if (client.Team != Teams.Allies || client.SpectateType == SpectateTypes.None) continue;
-
- // Set who the girl is and start the timer
- if (_gameStats.TheGirl == null)
- {
- _gameStats.TheGirl = client;
- _stopWatch.Start();
- _lastManStanding.Start();
- }
-
- // Set the clients position for the mini map icon
- _x = client.OriginX;
- _y = client.OriginY;
-
- // Check if the clients last known position is different from their current position
- if (_gameStats.LastKnownPosition != null)
- {
- _gameStats.IsNotMovingAround = !IsClientMoving(client);
- }
-
- // Update the icon details
- ChangeIcon();
- SetPosition();
-
-
- break;
- }
- }
- else
- {
- UpdateMiniMapIcon(true);
- }
- }
- catch (Exception)
- {
- // Doesn't get used, its here to simply catch any errors that occur while the MW3 server
- // is booting up or changing maps
- }
- }
-
- /// <summary>
- /// Executes when the map changes
- /// </summary>
- public override void OnMapChange()
- {
- UpdateMiniMapIcon(true);
- }
-
- /// <summary>
- /// Executes when the current game map restarts
- /// </summary>
- public override void OnFastRestart()
- {
- UpdateMiniMapIcon(true);
- }
-
- /// <summary>
- /// Executes when a player types something into the game chat
- /// </summary>
- /// <param name="message"></param>
- /// <param name="client"></param>
- /// <param name="teamchat"></param>
- /// <returns></returns>
- public override ChatType OnSay(string message, ServerClient client, bool teamchat)
- {
- string[] command = message.Split(' ');
-
- if (command[0] != "!icon") return ChatType.ChatContinue;
-
- // Parse the given icon number if one was given otherwise let the client know they did
- // something when typing the "!icon" command
- if (command[1] == null || command[1].Length == 0 || !int.TryParse(command[1], out _configuration.IconNumber))
- {
- TellClient(client.ClientNum, "^1Invalid icon number, E.g. ^7!icon 1", true);
- }
- else
- {
- ChangeIcon();
- }
-
- return ChatType.ChatNone;
- }
-
- /// <summary>
- /// Updates the position of the mini map icon given that is there only one player on the allies team
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void FindTheGirl(object sender, ElapsedEventArgs e)
- {
- if (_gameStats.TheGirl == null)
- {
- return;
- }
-
- double elasped = Math.Abs(_stopWatch.Elapsed.TotalSeconds);
-
- // Check if we need to detect for movement, if there hasn't been any movement for the time period set
- // and the stop watch has reached its goal or if we don't need to detect for movement show the icon on
- // the mini map
- if ((_configuration.DetectMovement && _gameStats.IsNotMovingAround && elasped >= _configuration.ResetTime) ||
- elasped >= _configuration.GirlyTime)
- {
- ChangeIcon();
- IconStatus(1);
- UpdateMiniMapIcon(false);
- }
- else if (_configuration.DetectMovement && !_gameStats.IsNotMovingAround)
- {
- IconStatus(0);
- _stopWatch.Reset();
- _stopWatch.Start();
- }
- }
-
- /// <summary>
- /// Deactivates the current mini map icon and resets the last man standing timer for the next game
- /// </summary>
- private void UpdateMiniMapIcon(bool deactivate)
- {
- _gameStats.ClientsHuman = 0;
- _gameStats.ClientsInfected = 0;
- _gameStats.ClientsTotal = 0;
-
- // Deactivate the mini map icon
- if (deactivate)
- {
- IconStatus(0);
- }
-
- // Stop the timers
- if ((!deactivate && !_configuration.DetectMovement) || deactivate)
- {
- _stopWatch.Reset();
- _stopWatch.Stop();
- _lastManStanding.Stop();
-
- _gameStats.IsNotMovingAround = false;
- _gameStats.TheGirl = null;
- }
- }
-
- /// <summary>
- /// Determines if the client is moving around
- /// </summary>
- /// <param name="client"></param>
- /// <returns></returns>
- private bool IsClientMoving(ServerClient client)
- {
- return Math.Abs(Math.Abs(client.OriginX - _gameStats.LastKnownPosition.X)) >= _configuration.Threshold ||
- Math.Abs(Math.Abs(client.OriginY - _gameStats.LastKnownPosition.Y)) >= _configuration.Threshold ||
- Math.Abs(Math.Abs(client.OriginZ - _gameStats.LastKnownPosition.Z)) >= _configuration.Threshold;
- }
-
- /// <summary>
- /// Activates/deactivates the icon on the minimap
- /// </summary>
- public unsafe void IconStatus(int status)
- {
- *(int*) _activate = status;
- }
-
- /// <summary>
- /// Changes the icon on the mini map
- /// </summary>
- public unsafe void ChangeIcon()
- {
- *(int*)_icon = _configuration.IconNumber;
- }
-
- /// <summary>
- /// Sets the position of the icon on the mini map
- /// </summary>
- public unsafe void SetPosition()
- {
- *(float*) _originX = _x;
- *(float*) _originY = _y;
- }
- }
-
- internal class GameOptions
- {
- public int ClientsTotal = 0;
- public int ClientsInfected = 0;
- public int ClientsHuman = 0;
- public bool IsNotMovingAround = false;
- public ServerClient TheGirl;
- public Vector LastKnownPosition;
- }
-
- internal class Configuration
- {
- public int IconNumber = 40;
- public int GirlyTime = 30;
- public bool DetectMovement = true;
- public int Threshold = 30;
- public int ResetTime = 5;
- }
- }
Credits:
@8q4s8 - Waypoint plugin creator
@MADD_DOGG - For such a simple yet cool idea
@Nukem - For such a great code base to work with
Apart from that the plugin will work its magic in the background without any input been required by the client. Enjoy!
[attachment=2736][attachment=2713][attachment=2709]