//======================================================================================= // Team Damage messages - by Mental Trousers as part of the Tribes scripting documents at // http://planetstarsiege.com/mt/ //======================================================================================= // // This script is intended as a follow on from the nuisance_filter.cs. // // Things covered in this script // ----------------------------- // // Everything from nuisance_filter.cs // String matching and replacing // Shows anti flooding/spamming measures // // This script was written because I'm not the best shot in the world :) // *Occassionally* I would hit a teammate or two when I didn't mean too, and I didn't // want to stop to type something in because I'm not the worlds fastest or most accurate // typist. I extended it to include messages for mines and also people on my team // shooting me. // // This script doesn't do a simply "Sorry xxxxxx" or "Watch it xxxxxx". It cycles through // a list of 8 different messages for when I damage someone and when I get shot by // someone. The mine damage list has four messages. // // Flood protection is included ie anti spamming from this client. This is provided by a // couple of functions taken from Prodigy's Madhud. // // There is also a built in delay of 3/10 secs before the message is sent. This to pick // up multiple messages of the same type ie ever trying elf'ing a teammate ? The same // message appears alot in a very short period. So it checks to see whether I have hit // the same person multiple times, or whether muliple people were hit, and only sends one // message for the lot. // // Other than those couple of things, this is just an extention of the techniques etc // illustrated in the nuisance_filter.cs, with a couple of other functions thrown in // //======================================================================================= $listOfNames::[myMine]=""; //List of teammates who stepped on one of my mines in //the last 3/10 secs $listOfNames::[myShot]=""; //List of teammates I've shot in the last 3/10 secs $listOfNames::[beenShot]=""; //List of teammates shooting me in the last 3/10 sec $messageNumber=1; //What message number we're up to. This variable //determines which of the messages is broadcast. It is //used by all 3 different types of messages. //These are the various messages. The word "person" is required. When the message is sent // "person" is replaced with the list of names from the appropriate $listOfNames::[] //Change them as you see fit, just remember to put "person" into them somewhere, //otherwise nothing will be sent. $TeamDamageMessage::msg[myMine, 1]="Look down person"; $TeamDamageMessage::msg[myMine, 2]="Watch your step person"; $TeamDamageMessage::msg[myMine, 3]="Don't stand on those person"; $TeamDamageMessage::msg[myMine, 4]="Open your eyes person"; $TeamDamageMessage::msg[myShot, 1]="Had my eyes closed person~wsorry"; $TeamDamageMessage::msg[myShot, 2]="Oh, you're on my team person~woops1"; $TeamDamageMessage::msg[myShot, 3]="Sorry person~wsorry"; $TeamDamageMessage::msg[myShot, 4]="Didn't mean to do that person~woops2"; $TeamDamageMessage::msg[myShot, 5]="Aw crap, sorry person~wcolor7"; $TeamDamageMessage::msg[myShot, 6]="Unfortunate accident person~woops2"; $TeamDamageMessage::msg[myShot, 7]="Apologies person~woops1"; $TeamDamageMessage::msg[myShot, 8]="Sorry person~wsorry"; $TeamDamageMessage::msg[beenShot, 1]="Open your eyes person~wwshoot1"; $TeamDamageMessage::msg[beenShot, 2]="What are you're smoking person !!~wwshoot1"; $TeamDamageMessage::msg[beenShot, 3]="How much have you had to drink person ?~wwshoot3"; $TeamDamageMessage::msg[beenShot, 4]="Will you put your glasses on person~wwshoot3"; $TeamDamageMessage::msg[beenShot, 5]="Shoot the guys with the red triangles person~wwshoot3"; $TeamDamageMessage::msg[beenShot, 6]="Who gave you a weapon person~wwshoot1"; $TeamDamageMessage::msg[beenShot, 7]="Now you know it's loaded person~wwshoot1"; $TeamDamageMessage::msg[beenShot, 8]="Lay off the liquor person~wwshoot3"; //======================================================================================= // I have no idea who wrote these, I simply copied them from the Madhud by Prodigy // Flood::Protect stops you from spamming. //======================================================================================= function Flood::Protect(%tag, %protectTime) { %lastTime = $Flood::[%tag]; %time = GetSimTime(); $Flood::[%tag] = %time; return %lastTime == "" || (%time - %lastTime >= %protectTime ); } function Flood::Reset() { deleteVariables("$Flood::*"); } //======================================================================================= // This function figures up which message to say (adjusting for the mine damage messages // as there are only four of them rather than eight), and whether you're spamming or not //======================================================================================= $dontFlood=2; //Set the time to wait before sending same message again - it's a constant //declaration, nothing more function TDMessages::sayMessage (%client, %type) { // echo ("function TDMessages::sayMessage ("@%client@", "@%type@")"); %number=$messageNumber; $messageNumber++; //message we're up to if ($messageNumber>8) //check to see if at end of message list $messageNumber=1; //reset to 1 if we are if (%type=="myMine"&&!(%number&1)) //if a mine damage message and an even number %number=%number/2; // then half it - only have 4 mine damage messages if (%number<1) //make sure nothing dodgy happened %number=1; //make sure we have a valid team damage message and replace "person" with the //appropriate list of names. //There are 2 different styles of messages, those with nothing after the persons //name, and those with other stuff ie !! or a sound if (Match::paramString ($TeamDamageMessage::msg[%type, %number], "%a person")) %msg=Match::Result(a)@" "@$listOfNames::[%type]; else if (Match::paramString ($TeamDamageMessage::msg[%type, %number], "%a person%b")) %msg=Match::Result(a)@" "@$listOfNames::[%type]@Match::Result(b); //Check to see if we're flooding, if not, say sorry or whatever. Up to 3 times per //minute if (Flood::Protect ("Dont flood", $dontFlood) && $perMinute<=2) { say (1, %msg); $perMinute++; } $listOfNames::[%type]=""; //Reset the list of names return; } //======================================================================================= // Sometimes we accidentally hurt more than one of our own team, so rather than // apologising to each individually, we wait for 3/10 sec to see how many damage // messages come through and compile a list of names. Then do one big apology to all on // the list. // If you want to see this in action, go and elf a teammate, or mortar everyone standing // around an inventory station, by "accident" of course :) //======================================================================================= function TDMessages::slightDelay (%client, %type, %person) { // echo ("TDMessages::slightDelay ()"); //Check to see if we've already hurt someone if ($listOfNames::[%type]=="") //Haven't hurt anyone, so start a new list, then schedule to say sorry or //whatever after waiting 3/10 sec { $listOfNames::[%type]=%person; schedule ("TDMessages::sayMessage ("@%client@", "@%type@");", 0.3); } //Already got somebody in the list, so check to make sure we're not entering the same //name again. If the person is already in the list, then do nothing, otherwise put //them in the list else { if (!Match::String ($listOfNames::[%type], "*"@%person@"*")) $listOfNames::[%type]=$listOfNames::[%type]@", "@%person; } return; } //======================================================================================= // This is where all the sorting for the team damage messages into the different types // is done. We have 3 different types of messages. The first is Mine damage messages, the // second is someone that I shot, the third is someone shot me. // You will notice that often I will specify multiple paramterized wildcards is the // match::paramString function call, but only obtain the result for one. This is because // we must find a match FOR THE ENTIRE STRING, from the start to the end, accounting for // every single character. Many messages are very similar and rather than searching for // each one explicitly, we can use the paramterized wildcards to match the stuff that is // slightly different, then ignore it. For instance, we don't care about the gender of // the person, however we still have to account for it in some messages. //======================================================================================= function TDMessages::teamDamage (%client, %msg) { // echo ("function TDMessages::teamDamage (%client, %msg)"); //Check to see if I just shot someone. Check out Match.cs for the docs on // match::paramString and match::result functions if (Match::String(%msg, "You just harmed Teammate *")) { if (Match::ParamString(%msg, "You just harmed Teammate %b with your mine%c")) { %iBlewup=Match::Result(b); TDMessages::slightDelay (getClientByName(%iBlewup), myMine, %iBlewup); } //getClientByName returns the client id number else if (Match::ParamString(%msg, "You just harmed Teammate %s!")) { %iShot=Match::Result(s); TDMessages::slightDelay (getClientByName(%iShot), myShot, %iShot); } } //Check to see if someone shot me !!! else if (Match::ParamString(%msg, "You took Friendly Fire from %s!")) { %shooter=Match::Result(s); TDMessages::slightDelay (getClientByName(%shooter), beenShot, %shooter); } //Check to see if someone just TK'ed me // Client::getName takes the client id number as the only parameter else if (Match::String(%msg, "* mows down*"@Client::getName(getManagerID()))) { if (Match::ParamString(%msg, "%s mows down %g teammate,%r")) { %shooter=Match::Result(s); TDMessages::slightDelay (getClientByName(%shooter), beenShot, %shooter); } else if (Match::ParamString(%msg, "%s mows down %r")) { %shooter=Match::Result(s); TDMessages::slightDelay (getClientByName(%shooter), beenShot,%shooter); } else say (1, "Look out you idiot !!"); } //Check to see if I *accidentally* TK'ed someone else if (Match::String(%msg, Client::getName(getManagerID())@" mows down *")) { if (Match::ParamString(%msg, "%s mows down %g teammate, %r")||Match::ParamString(%msg, "%s mows down %r")) { %ranDown=Match::Result(r); TDMessages::slightDelay (getClientByName(%ranDown), myShot, %ranDown); } else say (1, "Be careful dammit !!"); } return; } //resets the messages per minute counter every 60 secs function TDMessage::_resetCount () { $perMinute=0; schedule ("TDMessage::_resetCount();", 60); } //wait until the play screen opens and then set the messages per minute counter going function TDMessage::resetCount (%gui) { if (%gui==playGui) { event::detach (eventGuiOpen, TDMessage::resetCount); TDMessage::_resetCount (); } } //======================================================================================= // Here is where all of the messages to the client are caught and checked for team // damage messages //======================================================================================= function TDMessages::clientMessage (%client, %msg) { // echo ("function TDMessages::clientMessage (%client, %msg)"); //Quickly check for ANY team damage message if (String::findSubStr(%msg, "eammate ")!=-1 || String::findSubStr(%msg, " friendly fire ")!=-1 || String::findSubStr(%msg, " mows down ")!=-1) TDMessages::teamDamage (%client, %msg); } // Attach the above function to the event queue for eventClientMessage and also implement // one of the flood protection measures. If it's attached to the play gui then it will // wait until the play screen opens before activating. This is done because before that // time, not everything is available ie scheduler and others. Event::Attach (eventClientMessage, TDMessages::clientMessage, %client, %msg); Event::Attach (eventGuiOpen, TDMessage::resetCount, %gui);