Scripts:TXT File base Automatic Announcements

From BF2 Technical Information Wiki
Jump to navigation Jump to search

I just finished this and it's late, so I'm just going to throw it up and beef up the text later. It's pretty well documented, so you shouldn't have much trouble. Refer to Woody's Automatic Announcements script for installation. The only change to that being that I had to install the script in the admin/default.py script. This could've just been me, so keep in mind.

NOTE: By default, logging is turned off since the files can get large, You should enable logging if you are having a problem and you need to debug it.

"""
    advert.py - written by Dave Lawrence - [email protected]
   
    Based on Woody's "Automatic Announcements" script
    Loads messages from the text file "advert_msgs.txt"
        Use one line per message
    Log file can be used - advert_log.txt
        NOTE: Only use the log file for debug.  The output buffer is frequently
            flushed to ensure you see timely debug messages.  This *may* slow the
            game server down
    If you are having problems you can enable opt_SAdebug
        This will allow the script to run outside BF2
        There are no wrapers for the script, so the timer wont work, but you can
         debug probs with the message file
    NOTE: The advert_msgs.txt file is loaded into memory and I have no idea what'll
        happen if you try to use an enormous file.  Food for thought :)

Release notes:
    advert.py v1.0

ToDo:
    - Allow messages to be reloaded while the server is running (if that is even possible)
       Perhaps a command from the console
       Can anyone point me in the right direction on how to do this?
    - Put the dbgWriter class into it's own py so we can use it everywhere!
"""


"""""""""""""""""""""""
   Top-Level Imports
"""""""""""""""""""""""
import sys

"""""""""""""""""""""""
        OPTIONS
"""""""""""""""""""""""
opt_Interval = 14   # Number of seconds between announcements
opt_SAdebug = 0     # For standalone debugging outside of bf2 enable this
# You can use this option to more easily figure out if your ads are loading

# Enable logging to advert_log.txt
# Warning: only do this for debugging.  This log file could get huge!
opt_Debuglog = 0    # Logs to advert_log.txt
opt_Stdoutlog = 0   # Enable if you want ALL stdout msgs to be logged, you'll see the actual msh go out


"""""""""""""""""""""""
        GLOBALS
"""""""""""""""""""""""
glob_dictMsgs = {}       # Where all the advert messages are stored
glob_hdlDbgout = {}
glob_IdxMsg = 0


"""""""""""""""""""""""""""""""""
    Functions and Classes
"""""""""""""""""""""""""""""""""
# This is where it happens :)
def tmrhdlAdvert(data):
    global glob_IdxMsg
    global glob_dictMsgs
    # Handle the index overflow
    if glob_IdxMsg >= len(glob_dictMsgs):
        glob_IdxMsg = 0
    host.rcon_invoke('game.sayall "%s"' % glob_dictMsgs[glob_IdxMsg])
    dprint('game.sayall "%s"\n' % glob_dictMsgs[glob_IdxMsg], 1)
    glob_IdxMsg += 1

class dbgWriter:
    flog = {}
    def __init__(self):
        global glob_hdlDbgout
        glob_hdlDbgout = self
        if opt_Debuglog == 1 or opt_SAdebug == 0:
            self.flog = open('advert_log.txt', 'w')
            self.stream = self.flog
        else:
            self.stream = sys.stdout

        # Do we modify STDOUT or leave it as the default cfg from somewhere else?
        if opt_Stdoutlog == 1:
            sys.stdout = self

    def write(self, str):
        self.stream.write(str)

    def prt(self, str):
        self.stream.write(str)
       
    def flush(self):
        self.stream.flush()

def dprint(msg, flush=0):
    glob_hdlDbgout.prt(msg)
    if flush == 1:
        glob_hdlDbgout.flush()
       

"""""""""""""""""""""""""""""""""
  Initialization and main code
"""""""""""""""""""""""""""""""""

# Init the debug writer
dbgWriter()

dprint("BF2 Advert Starting\n", 1)

# Check the interval and make sure it's not too short.  Let's clamp it at 15 secs
if opt_Interval < 15:
    dprint("opt_Interval=%s which is too small, changing to 15 seconds\n" % opt_Interval)
    opt_Interval = 15

# TODO: There should be some way to auto detect if we're running inside the BF2 engine, hmm :-\
# Allows BF2 modules to be disabled for local debugging
if(opt_SAdebug == 0):
    dprint("Importing BF2 libs\n", 1)
    import bf2
    import bf2.Timer
    import host
else:
    dprint("Running in standalone mode\n")

dprint("Importing advertisment messages\n", 1)
try:
    try:
        config = open('advert_msgs.cfg', 'rt')
    except:
        dprint("Error opening advert_msgs.cfg- Is it missing?\n")
    for line_ in config:
        line = line_.strip()
        if len(line) == 0 or line.startswith('#'):  continue
        glob_dictMsgs[glob_IdxMsg] = line
        dprint("%s\n" % glob_dictMsgs[glob_IdxMsg])
        glob_IdxMsg += 1
except IOError:
    dprint("I/O Error on advert.cfg read - does it exist?\n", 1)
    pass

#Reset the glob_IdxMsg to point to the first message
glob_IdxMsg = 0

# Let's make sure that the timer gets initialized correctly
# It works now, but EA could "F" us later :)
try:
    # We bypass this initialization if we're not running in BF2, this doesn;t *really* warrant a wrapper
    if opt_SAdebug == 0:
        timer = bf2.Timer(tmrhdlAdvert, opt_Interval, 1)
except:
    dprint("'timer = bf2.Timer(tmrhdlAdvert, 1)' FAILED!!\n", 1)

try:
    # We bypass this initialization if we're not running in BF2
    if opt_SAdebug == 0:
        timer.setRecurring(opt_Interval)
except:
    dprint("'timer.setRecurring(optInterval))' FAILED!!\n", 1)

dprint("tmrhadlAdvert istalled successfully\n")
dprint("BF2 Advert Started  %d messages\n" % len(glob_dictMsgs), 1)

Just call it advert.py, save it in admin/ and add the following to your admin/__init__.py or admin/default.py

import advert 

The advert_msgs.cfg file needs to be in the root BF2 directory. The log file, advert_log.txt will show up in the root BF2 folder as well.

Have fun!