/*********************************************************
 *          Bugblatter Monster Extension - V3.5          *
 *********************************************************
 *                                                       *
 * This plug-in is linux & win32 friendly.               *
 *                                                       *
 * Version history                                       *
 *                                                       *
 * Version 3.5:                                          *
 *                                                       *
 *  - Removed warnings compiling on Admin Mod 2.50.56    *
 *                                                       *
 * Version 3.4:                                          *
 *  - Maxplayers loop bound corrected on mania score     *
 *                                                       *
 * Version 3.3:                                          *
 *  - Fixed a bug in respawning statically configured    *
 *    monsters at the start of a round in counter-strike *
 *    This should now work properly.                     *
 *  - Some leftover log() calls from debugging removed.  *
 *                                                       *
 * Version 3.2:                                          *
 *                                                       *
 *  - Updated for language plugin version 3.3            *
 *                                                       *
 * Version 3.1:                                          *
 *                                                       *
 *  -  Works with monster DLL 3.01.01                    *
 *  -  New syntax for monster command in DLL             *
 *  -  Reads monster list from file named in the cvar    *
 *     monster_precache                                  *
 *  -  Added support for spawning at specific            *
 *     co-ordinates as well as on a player               *
 *  -  Added support for spawning at specific            *
 *     co-ordinates as well as on a player               *
 *  -  Fixed error in error message if you gave an       *
 *     invalid player name.                              *
 *                                                       *
 * Version 2.6:                                          *
 *                                                       *
 *  -  Added colour and timing settings for all          *
 *     messageex class on 2.51.xx alpha builds.          *
 *  -  Checks for freeze time during monster mania       *
 *                                                       *
 * Version 2.5:                                          *
 *  -  Monsters now killed when plugin is disabled       *
 *  -  Move prominent error messages in log              *
 *                                                       *
 * Version 2.4:                                          *
 *  -  Initial Version                                   *
 *                                                       *
 *                                                       *
 *********************************************************/
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
#include <plugin>
 
#include "settings"
#include "clientio"
#include "language"
#include "stringx"
 
new g_Version[]="3.5";
 
#define DEFAULT_ENABLED 1
#define MIN_ENABLED 0
#define MAX_ENABLED 1
 
#define DEFAULT_REPORT 1
#define MIN_REPORT 0
#define MAX_REPORT 1
 
#define DEFAULT_MAX_MONSTERS 4
#define MIN_MAX_MONSTERS 1
#define MAX_MAX_MONSTERS 30
 
#define DEFAULT_TIMEOUT 30
#define MIN_TIMEOUT 10
#define MAX_TIMEOUT 120
 
#define DEFAULT_SCORE 0
#define MIN_SCORE 0
#define MAX_SCORE 10
 
#define DEFAULT_MANIA 0
#define MIN_MANIA 0
#define MAX_MANIA 1
 
#define DEFAULT_MANIASCORE 1
#define MIN_MANIASCORE 0
#define MAX_MANIASCORE 10
 
/* Don't change this - its a limit from the monster_mm.dll */
#define MAX_MONSTER_COUNT 20
 
new g_MSG_REPORT_TITLE[]="Bugblatter Monster configuration:";
new g_MSG_RPT_ENABLED_ON[]=" - Monster spawning is currently enabled (bbmonster_enabled)";
new g_MSG_RPT_ENABLED_OFF[]=" - Monster spawning is currently disabled (bbmonster_enabled)";
new g_MSG_RPT_MAX_MONSTERS[]=" - Each player can spawn a maximum of %1i mosnters (bbmonster_maxmonsters)";
new g_MSG_RPT_TIMEOUT[]=" - Monster limit resets after %1i seconds (bbmonster_timeout)";
new g_MSG_RPT_SCORE[]=" - Players score %1i frags for killing a monster (bbmonster_score)";
new g_MSG_RPT_MANIA_ON[]=" - Monster mania is enabled, with %1i frags for killing a monster(bbmonster_mania)";
new g_MSG_RPT_MANIA_OFF[]= " - Monster mania is disabled. (bbmonster_mania)";
 
new g_MSG_AVAILABLEMONSTERS[]="Monsters:|Monstres:|Monsters:";
new g_MSG_MONSTERKILL[]="Monster %1s has killed %2s.|Monstre %1s a tue %2s.|Monster %1s hat %2s getotet.";
new g_MSG_MONSTERDEAD[]="%1s has killed monster %2s.|%1s a tue le monstre %2s.|%1s hat Monster %2s getotet.";
new g_MSG_WAIT[]="You must wait a while before spawning any more monsters|Vous devez attendre un peu avant de faire naitre d'autres monstres.|Du musst noch ein bischen warten um mehr Monster zu erschaffen.";
new g_MSG_MAXIMUM[]="There are already the maximum number of monsters in the game|Il y a deja le maximum de monstres dans le jeu|Die maximale Anzahl an Monstern für das Spiel ist schon erreicht";
/*new g_MSG_SPAWN[]="Player %1s is spawning a %2s on player %£s|Le joueur %1s fait apparaitre %2s en tant que joueur %3s|Spieler %1s erschafft ein %2s fur Spieler %3s";*/
new g_MSG_UNKNOWNPLAYER[]="Unrecognised Player %1s.|Joueur non reconnu %1s.|Spieler wurde nicht erkannt %1s";
 
new g_MSG_MANIAANNOUNCE[]="It's Monster Mania! Kill the monsters for %1i bonus points|C'est la Manie des Monstres! Tue les montres pour avoir %1i point de bonus|Es ist Monster Mania! Tote die Monster fur %1i Bonuspunkte.";
/*new g_MSG_MANIASPAWN[]="Monster Mania is spawning a %1s on player %2s.|La Manie des Monstres fait apparaitre un %1s pres du joueur %2s|Monster Mania erschafft ein %1s bei Spieler %2s.";*/
 
 
/* Configuration variables */
new g_Enabled=DEFAULT_ENABLED;                          /* Is this plugin enabled */
new g_Report=DEFAULT_REPORT;                            /* Automatically show report after command? */
 
new g_Monsters[40][MAX_NAME_LENGTH];                    /* Names of available monsters */
new g_MonstersSize=0;                                   /* Length of monsters names list */
new g_MaxMonsters= DEFAULT_MAX_MONSTERS;                /* Maximum number of monsters player can spawn in each time period */
new g_Timeout = DEFAULT_TIMEOUT;                        /* Length of time period */
new g_Score=DEFAULT_SCORE;                              /* Points per mosnter frag */
new g_Mania=DEFAULT_MANIA;                              /* Monster Mania on/off */
new g_ManiaScore=DEFAULT_MANIASCORE;                    /* Monster Mania score */
new g_ManiaProtected=0;                                 /* Is Mania protected */
 
/* Status vrariables */
new g_Spawns[MAX_PLAYERS];                              /* Number of monsters each player has spawned */
new g_ManiaTimer=0;                                     /* Monster Mania spawn timer */
new g_TimeoutTimer=0;                                  /* Timer handle for timeouts */
new g_MonsterCount=0;                                   /* Tracks number of monsters in the game */
new g_NextMonsterID=0;                                  /* ID numbers for mosnters */
 
RegisterPlugin();
BBMonsterCbSpawned(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterCbDead(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterCbKill(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterCbKilled(HLCommand,HLData,HLUserName,UserIndex);
BBLogdWorldAction(HLCommand,HLData,HLUserName,UserIndex);
ForceUnload(Timer,Repeat,HLUserName,HLParam);
ManiaProtectEnd(Timer,Repeat,HLUserName,HLParam);
BBMonsterEnabled(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterMax(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterTimeout(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterScore(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterMania(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterSpawn(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterReset(HLCommand,HLData,HLUserName,UserIndex);
BBMonsterReport(HLCommand,HLData,HLUserName,UserIndex);
ShowConfig(Force,UserIndex);
ReadMonsterList();
ReadLine(File[],i,Line[]);
ResetSpawnCounts(Timer,Repeat,HLUserName,HLParam);
ListMonsters(UserIndex);
CheckMonster(name[]);
PickMonster();
CheckMania();
ManiaTimer(Timer,Repeat,HLUserName,HLParam);
ManiaSpawn();
 
 
/*********************************************************/
/* Standard event handlers for adminmod                  */
/*********************************************************/
 
public plugin_init() {
  plugin_registerinfo("Bugblatter's Monster plugin","Spawns Halflife monsters",g_Version);
 
  /* Check server is configured properly */
  new fOK = checkFileAccessRead();
  if (fOK == 0) {
    return PLUGIN_CONTINUE;
  }
  /* No need to abort if this one fails */
  checkLanguage();
 
  ReadMonsterList();
 
  readvaultnum("bbmonster_report",g_Report,DEFAULT_REPORT,MIN_REPORT,MAX_REPORT);
  readvaultnum("bbmonster_enabled",g_Enabled,DEFAULT_ENABLED,MIN_ENABLED,MAX_ENABLED);
  readvaultnum("bbmonster_maxmonsters",g_MaxMonsters,DEFAULT_MAX_MONSTERS,MIN_MAX_MONSTERS,MAX_MAX_MONSTERS);
  readvaultnum("bbmonster_timeout",g_Timeout,DEFAULT_TIMEOUT,MIN_TIMEOUT,MAX_TIMEOUT);
  readvaultnum("bbmonster_score",g_Score,DEFAULT_SCORE,MIN_SCORE,MAX_SCORE);
  readvaultnum("bbmonster_mania",g_Mania,DEFAULT_MANIA,MIN_MANIA,MAX_MANIA);
  readvaultnum("bbmonster_maniascore",g_ManiaScore,DEFAULT_MANIASCORE,MIN_MANIASCORE,MAX_MANIASCORE);
  g_TimeoutTimer = set_timer("ResetSpawnCounts",g_Timeout,99999,"");
 
  RegisterPlugin();
 
  CheckMania();
  return PLUGIN_CONTINUE;
}
 
 
RegisterPlugin() {
  /* Register commands with adminmod */
  language_init();
  plugin_registercmd("bbmonster_enabled","BBMonsterEnabled",ACCESS_CONFIG,"bbmonster_enabled ^"on^" | ^"off^": Enables / disables monster plugin");
  plugin_registercmd("bbmonster_spawn","BBMonsterSpawn",ACCESS_KICK,"bbmonster_spawn <monster> [<player>]: Spawns a monster on aplayer");
  plugin_registercmd("bbmonster_timeout","BBMonsterTimeout",ACCESS_CONFIG,"bbmonster_timeout <seconds>: Sets timeout for reseting spawn limit");
  plugin_registercmd("bbmonster_maxmonsters","BBMonsterMax",ACCESS_CONFIG,"bbmonster_maxmonsters <seconds>: Sets maximum number of monsters in each period");
  plugin_registercmd("bbmonster_score","BBMonsterScore",ACCESS_CONFIG,"bbmonster_score <points>: Sets frags score for killing a monster");
  plugin_registercmd("bbmonster_mania","BBMonsterMania",ACCESS_CONFIG,"bbmonster_mania ^"on^" | ^"off^" | <points>: Enable monster mania mode, and sets score for a mania kill");
  plugin_registercmd("bbmonster_logdwa","BBLogdWorldAction",131072,"");
  plugin_registercmd("bbmonster_report","BBMonsterReport",ACCESS_CONFIG,"bbmonster_report [ ^"on^" | ^"off^" ]: Shows report and enables/disables automatic report");
  plugin_registercmd("bbmonster_reset","BBMonsterReset",ACCESS_CONFIG,"bbmonster_reset: sets all monster settings to defaults");
 
  plugin_registercmd("bbmonstercb_spawned","BBMonsterCbSpawned",131072,"");
  plugin_registercmd("bbmonstercb_kill","BBMonsterCbKill",131072,"");
  plugin_registercmd("bbmonstercb_killed","BBMonsterCbKilled",131072,"");
  plugin_registercmd("bbmonstercb_dead","BBMonsterCbDead",131072,"");
 
  exec("logd_reg 62 admin_command bbmonster_logdwa",0);
 
}
 
 
/*********************************************************/
/* Monster DLL callback handlers                         */
/*********************************************************/
 
 
public BBMonsterCbSpawned(HLCommand,HLData,HLUserName,UserIndex) {
  g_MonsterCount++;
 
/*  new msg[MAX_DATA_LENGTH];
  snprintf(msg,MAX_DATA_LENGTH,"There are now %i monsters in the game",g_MonsterCount);
  log(msg);
  say(msg);*/
  return PLUGIN_HANDLED;
}
 
public BBMonsterCbDead(HLCommand,HLData,HLUserName,UserIndex) {
  g_MonsterCount--;
/*  new msg[MAX_DATA_LENGTH];
  snprintf(msg,MAX_DATA_LENGTH,"There are now %i monsters in the game",g_MonsterCount);
  log(msg);
  say(msg);*/
  return PLUGIN_HANDLED;
}
 
public BBMonsterCbKill(HLCommand,HLData,HLUserName,UserIndex) {
  new Data[MAX_DATA_LENGTH];
  safe_convert(HLData,Data,MAX_DATA_LENGTH);
 
  new pos = index(Data,' ');
  Data[pos]=0;
  new TargetIndex = strtonum(Data);
  Data[pos]=32;
  strstrip(Data,pos+1);
 
  new Name[MAX_NAME_LENGTH];
 
  playerinfo(TargetIndex,Name,MAX_NAME_LENGTH);
 
  new msg[MAX_DATA_LENGTH];
  snprintf(msg,MAX_DATA_LENGTH,"Monster %s has killed %s",Data,Name);
  log(msg);
  language_sayallf(g_MSG_MONSTERKILL,print_type:print_chat,0,0,0,0,Data,Name);
  return PLUGIN_HANDLED;
}
 
public BBMonsterCbKilled(HLCommand,HLData,HLUserName,UserIndex) {
  new Data[MAX_DATA_LENGTH];
  safe_convert(HLData,Data,MAX_DATA_LENGTH);
 
  new pos = index(Data,' ');
  Data[pos]=0;
  new TargetIndex = strtonum(Data);
  Data[pos]=32;
  strstrip(Data,pos+1);
 
  new Name[MAX_NAME_LENGTH];
 
  playerinfo(TargetIndex,Name,MAX_NAME_LENGTH);
 
  new msg[MAX_DATA_LENGTH];
  snprintf(msg,MAX_DATA_LENGTH,"%s has killed monster %s",Name,Data);
  log(msg);
  language_sayallf(g_MSG_MONSTERDEAD,print_type:print_chat,0,0,0,0,Name,Data);
  return PLUGIN_HANDLED;
}
 
 
 
 
/*********************************************************/
/* LogD command handlers                                 */
/*********************************************************/
 
public BBLogdWorldAction(HLCommand,HLData,HLUserName,UserIndex) {
  new Data[MAX_DATA_LENGTH];
  safe_convert(HLData,Data,MAX_DATA_LENGTH);
  if (strmatch(Data,"Round_End",9)==1) {
    exec("slaymonsters",0);
    set_timer("ForceUnload",3,1,"");
    g_ManiaProtected = 1;
    new tl = getvar("mp_timelimit")+15;
    if (tl<20) { tl=20; }
    set_timer("ManiaProtectEnd",tl,1,"");
  }
  else {
    if (strmatch(Data,"Round_Start",11)==1) {
      exec("respawnmonsters",0);
    }
  }
  return PLUGIN_HANDLED;
}
 
public ForceUnload(Timer,Repeat,HLUserName,HLParam) {
  exec("slaymonsters force",0);
  g_MonsterCount=0;
  return PLUGIN_HANDLED;
}
 
public ManiaProtectEnd(Timer,Repeat,HLUserName,HLParam) {
  if (g_ManiaProtected==2) {
    g_ManiaTimer = set_timer("ManiaTimer",random(20),1,"");
  }
  g_ManiaProtected = 0;
  return PLUGIN_HANDLED;
}
 
/*********************************************************/
/* Command handlers for admin commands                   */
/*********************************************************/
 
public BBMonsterEnabled(HLCommand,HLData,HLUserName,UserIndex) {
  if (readHLonoff(HLData,g_Enabled,DEFAULT_ENABLED,MIN_ENABLED,MAX_ENABLED)) {
    writevaultnum("bbmonster_enabled",g_Enabled);
    CheckMania();
    if (g_Enabled ==0) {
      exec("slaymonsters force",0);
      g_MonsterCount=0;
    }
  }
 
  return ShowConfig(0,UserIndex);
}
 
public BBMonsterMax(HLCommand,HLData,HLUserName,UserIndex) {
  if (readHLnum(HLData,g_MaxMonsters,DEFAULT_MAX_MONSTERS,MIN_MAX_MONSTERS,MAX_MAX_MONSTERS)) {
    writevaultnum("bbmonster_maxmonsters",g_MaxMonsters);
  }
  return ShowConfig(UserIndex,0);
}
 
public BBMonsterTimeout(HLCommand,HLData,HLUserName,UserIndex) {
  if (readHLnum(HLData,g_Timeout,DEFAULT_TIMEOUT,MIN_TIMEOUT,MAX_TIMEOUT)) {
    kill_timer(g_TimeoutTimer);
    g_TimeoutTimer = set_timer("ResetSpawnCounts",g_Timeout,99999,"");
    writevaultnum("bbmonster_timeout",g_Timeout);
  }
  return ShowConfig(UserIndex,0);
}
 
public BBMonsterScore(HLCommand,HLData,HLUserName,UserIndex) {
  if (readHLnum(HLData,g_Score,DEFAULT_SCORE,MIN_SCORE,MAX_SCORE)) {
    writevaultnum("bbmonster_score",g_Score);
  }
  return ShowConfig(UserIndex,0);
}
 
public BBMonsterMania(HLCommand,HLData,HLUserName,UserIndex) {
  new mania=0;
  if (readHLonoff(HLData,mania,DEFAULT_MANIA,-1,MAX_MANIASCORE)) {
    if (mania == -1 ) {
      g_Mania = 1;
      g_ManiaScore = 1;
    }
    else if (mania == 0) {
      g_Mania = 0;
      g_ManiaScore = 0;
    }
    else {
      g_Mania = 1;
      g_ManiaScore = mania;
    }
    writevaultnum("bbmonster_mania",g_Mania);
    writevaultnum("bbmonster_maniascore",g_ManiaScore);
    CheckMania();
  }
  return ShowConfig(0,UserIndex);
}
 
public BBMonsterSpawn(HLCommand,HLData,HLUserName,UserIndex) {
 
  if (g_Enabled==0) {
    return PLUGIN_HANDLED;
  }
 
  new UserName[MAX_DATA_LENGTH];
  new Data[MAX_DATA_LENGTH];
  new MonsterName[MAX_DATA_LENGTH];
  new TargetName[MAX_DATA_LENGTH];
 
  safe_convert(HLUserName, UserName, MAX_DATA_LENGTH);
  safe_convert(HLData, Data, MAX_DATA_LENGTH);
  strbreak(Data,MonsterName,TargetName,MAX_DATA_LENGTH);
 
  if (strlen(MonsterName)==0) {
    ListMonsters(UserIndex);
    return PLUGIN_HANDLED;
  }
 
  if (CheckMonster(MonsterName) ==0) {
    ListMonsters(UserIndex);
    return PLUGIN_HANDLED;
  }
 
  if (g_Spawns[UserIndex] >= g_MaxMonsters) {
    language_say(UserIndex,g_MSG_WAIT,print_type:print_chat);
    return PLUGIN_HANDLED;
  }
 
  if (g_MonsterCount >= MAX_MONSTER_COUNT) {
    language_say(UserIndex,g_MSG_MAXIMUM,print_type:print_chat);
    return PLUGIN_HANDLED;
  }
 
  strtrim(TargetName," ^t");
 
  if (strlen(TargetName) ==0) {
    gettarget(UserName,TargetName,MAX_DATA_LENGTH);
    if (strlen(TargetName) ==0) {
      return PLUGIN_HANDLED;
    }
  }
 
  new i;
  new ui=get_userindex(TargetName,i);
 
  if ((ui > 0) || (TargetName[0]=='@')) {
    new cmd[MAX_DATA_LENGTH];
    snprintf(cmd,MAX_DATA_LENGTH,"Player %s is spawning a %s on player %s",UserName,MonsterName,TargetName);
    log(cmd);
    if (TargetName[0]=='@') {
      TargetName[0]=' ';
      snprintf(cmd,MAX_DATA_LENGTH,"monster model %s tag %i score %i origin %s",MonsterName, g_NextMonsterID++, g_Score, TargetName);
    }
    else if (ui <=0) {
      snprintf(cmd,MAX_DATA_LENGTH,"monster model %s tag %i score %i player %s",MonsterName, g_NextMonsterID++, g_Score, TargetName);
    }
    else {
      snprintf(cmd,MAX_DATA_LENGTH,"monster model %s tag %i score %i player #%i",MonsterName, g_NextMonsterID++, g_Score, i);
    }
    exec(cmd,0);
    g_Spawns[UserIndex] = g_Spawns[UserIndex] + 1;
  }
  else {
    language_sayf(UserIndex,g_MSG_UNKNOWNPLAYER,print_type:print_console,0,0,0,0,TargetName);
  }
 
  return PLUGIN_HANDLED;
}
 
 
public BBMonsterReset(HLCommand,HLData,HLUserName,UserIndex) {
  g_Enabled=DEFAULT_ENABLED;
  g_MaxMonsters = DEFAULT_MAX_MONSTERS;
  g_Timeout= DEFAULT_TIMEOUT;
  g_Score=DEFAULT_SCORE;
  g_Mania=DEFAULT_MANIA;
  g_ManiaScore=DEFAULT_MANIASCORE;
 
  writevaultnum("bbmonster_maxmonsters",g_MaxMonsters);
  writevaultnum("bbmonster_timeout",g_Timeout);
  writevaultnum("bbmonster_enabled",g_Enabled);
  writevaultnum("bbmonster_score",g_Score);
  writevaultnum("bbmonster_mania",g_Mania);
  writevaultnum("bbmonster_maniascore",g_ManiaScore);
 
  CheckMania();
  return ShowConfig(0,UserIndex);
}
 
 
public BBMonsterReport(HLCommand,HLData,HLUserName,UserIndex) {
  if (readHLonoff(HLData,g_Report,DEFAULT_REPORT,MIN_REPORT,MAX_REPORT)) {
    writevaultnum("bbmonster_report",g_Report);
    ShowConfig(0,UserIndex);
  }
  else {
    ShowConfig(1,UserIndex);
  }
  return PLUGIN_HANDLED;
}
 
ShowConfig(Force,UserIndex) {
  if ((Force==0) && (g_Report==0)) {
    return PLUGIN_HANDLED;
  }
 
  language_say(UserIndex,g_MSG_REPORT_TITLE,print_type:print_console);
  if (g_Enabled) {
    language_say(UserIndex,g_MSG_RPT_ENABLED_ON,print_type:print_console);
  }
  else {
    language_say(UserIndex,g_MSG_RPT_ENABLED_OFF,print_type:print_console);
  }
 
  language_sayf(UserIndex,g_MSG_RPT_MAX_MONSTERS,print_type:print_console,0,0,0,0,g_MaxMonsters);
  language_sayf(UserIndex,g_MSG_RPT_TIMEOUT,print_type:print_console,0,0,0,0,g_Timeout);
  language_sayf(UserIndex,g_MSG_RPT_SCORE,print_type:print_console,0,0,0,0,g_Score);
  if (g_Mania) {
    language_sayf(UserIndex,g_MSG_RPT_MANIA_ON,print_type:print_console,0,0,0,0,g_ManiaScore);
  }
  else {
    language_say(UserIndex,g_MSG_RPT_MANIA_OFF,print_type:print_console);
  }
 
  return PLUGIN_HANDLED;
}
 
 
 
 
 
ReadMonsterList() {
 
  g_MonstersSize=0;
  new File[MAX_DATA_LENGTH];
  new Line[MAX_DATA_LENGTH];
 
  getstrvar("monster_precache",File,MAX_DATA_LENGTH);
  if (fileexists(File)==0) {
    return 0;
  }
 
  new ReadCount=filesize(File,fsize_unit:lines)+1;
 
  new i;
  for(i=0;i<ReadCount;i++) {
    /* File line numbers are indexed from 1, not 0, hence the +1 */
    ReadLine(File,i,Line);
 
    if (strlen(Line)>0) {
      strcpy(g_Monsters[g_MonstersSize],Line,MAX_NAME_LENGTH);
      g_MonstersSize++;
    }
  }
  return 1;
}
 
 
 
ReadLine(File[],i,Line[]) {
  /* File line numbers are indexed from 1, not 0, hence the +1 */
  readfile(File,Line,i,MAX_DATA_LENGTH);
 
  /* Remove trailing comment or nullify the string if its nothing but a comment */
  new pos = strstr(Line, "//");
  if (pos >= 0) {
    Line[pos] = NULL_CHAR;
  }
 
  /* Remove spaces and tabs */
  strtrim(Line," ^t",2);
}
 
 
public ResetSpawnCounts(Timer,Repeat,HLUserName,HLParam) {
  new i=0;
/*  log("Reseting monster spawn counters");*/
  for(i=0;i<MAX_PLAYERS;i++) {
    g_Spawns[i]=0;
  }
}
 
 
ListMonsters(UserIndex) {
  language_say(UserIndex,g_MSG_AVAILABLEMONSTERS,print_type:print_console);
  new i=0;
  for(i=0;i<g_MonstersSize;i++) {
      selfmessage(g_Monsters[i]);
  }
}
 
CheckMonster(name[]) {
  new i=0;
  for(i=0;i<g_MonstersSize;i++) {
    if (streq(g_Monsters[i],name)) {
      return 1;
    }
  }
  return 0;
}
 
PickMonster() {
  new i;
  new tries = 100;
  while (tries>0) {
    i=random(g_MonstersSize);
    if (streq(g_Monsters[i],"apache")==0) {
      return i;
    }
    tries--;
  }
  return -1;
}
 
CheckMania() {
  if (g_Enabled && g_Mania) {
    if (g_ManiaTimer == 0) {
      g_ManiaTimer = set_timer("ManiaTimer",50+random(20),1,"");
    }
  }
  else {
    if (g_ManiaTimer) {
      kill_timer(g_ManiaTimer);
      g_ManiaTimer=0;
    }
  }
}
 
public ManiaTimer(Timer,Repeat,HLUserName,HLParam) {
  if (g_ManiaProtected == 1) {
    /* If this happens near the start of a round,
     * flag that we tried to spawn, so that when
     * the protectin period ends, the spawn will
     * take place */
    g_ManiaProtected = 2;
  }
  else {
    ManiaSpawn();
  }
}
 
ManiaSpawn() {
  new i;
  new players[MAX_PLAYERS];
  new c=playercount();
  for (i=1;i<MAX_PLAYERS;i++) {
    players[i]=i;
  }
 
  for (i=1;i<MAX_PLAYERS*4;i++) {
    new p1=random(c)+1;
    new p2=random(c)+1;
    new t=players[p2];
    players[p2]=players[p1];
    players[p1]=t;
  }
 
  new count=0;
 
  new mon = PickMonster();
  if (mon==-1) {
    g_ManiaTimer = set_timer("ManiaTimer",50+random(20),1,"");
    return PLUGIN_HANDLED;
  }
 
  new teamdone=-1;
 
  new m=maxplayercount();
  for (i=1;i<=m;i++) {
    new userid=0;
    new wonid=0;
    new AuthID[MAX_AUTHID_LENGTH];
    new teamid=0;
    new username[MAX_NAME_LENGTH];
    new dead=0;
 
    if (playerinfo(i, username, 200, userid, wonid,teamid,dead,AuthID)==1) {
      if ((dead==0) && (teamid < 5) && (teamid != teamdone)) {
        if (g_MonsterCount >= MAX_MONSTER_COUNT) {
          g_ManiaTimer = set_timer("ManiaTimer",50+random(20),1,"");
          return PLUGIN_HANDLED;
        }
 
        new cmd[MAX_DATA_LENGTH];
        language_sayallf(g_MSG_MANIAANNOUNCE,print_type:print_center,7,255,0,0,g_ManiaScore);
        snprintf(cmd,MAX_DATA_LENGTH,"Monster Mania is spawning a %s on player %s",g_Monsters[mon],username);
        log(cmd);
        snprintf(cmd,MAX_DATA_LENGTH,"monster model %s tag %i score %i player #%i",g_Monsters[mon], g_NextMonsterID++, g_ManiaScore, i);
        exec(cmd,0);
        teamdone = teamid;
        count++;
 
        if (count == 2) {
          g_ManiaTimer = set_timer("ManiaTimer",50+random(20),1,"");
          return PLUGIN_HANDLED;
        }
 
      }
    }
 
  }
  g_ManiaTimer = set_timer("ManiaTimer",50+random(20),1,"");
  return PLUGIN_HANDLED;
}