Map Specifications

From Soldat Community Wiki
Jump to: navigation, search

Script by: Curt

//Script by Curt (DorkeyDear)
//ReturnFlag modified by Curt; origonal author is J-Factor

type
  tGroup = record
    SpreadSpawn, DisableFlags, IgnoreWeapons: boolean;
    Command, Welcome: array of string;
    Map: array of record
      Style: byte;
      Name: string;
    end;
    Team: array[0..5] of record
      AllowPickup: boolean;
      Balance: byte;
      DealDmgMtp, RecvDmgMtp: single;
      Weapon: array[1..14] of boolean;
    end;
  end;

var
  AfterMapChange: boolean;
  GID: byte;
  Group: array of tGroup;

function StrtoBool(Text: string; Default: boolean): boolean;
begin
  Result := Default;
  case (LowerCase(Text)) of
    '1', 'true', 'enabled', 'enable', 'on': Result := true;
    '0', 'false', 'disabled', 'disable', 'off': Result := false;
  end;
end;

function VnttoInt(Value: Variant): integer;
begin
  Result := Value;
end;

function RealtoListWeapNum(Weapon: byte): byte;
begin
  if (Weapon = 0) then Result := 11 else if (Weapon <= 10) then Result := Weapon else if ((Weapon >= 14) and (Weapon <= 16)) then Result := Result - 2 else Result := 0;
end;

procedure ReturnFlag(Team: byte);
var
  i: byte;
begin
  for i := 1 to 254 do begin
    if ((GetObjectStat(i, 'Active') = true) and (GetObjectStat(i, 'Style') = Team)) then begin
      KillObject(i);
      break;
    end;
  end;
end;

function ReadData(Filename: string): array of tGroup;
var
  i, j, k, HighA, HighB: byte;
  Weapons: string;
begin
  try
    HighA := StrtoInt(ReadINI(Filename, 'Groups', 'GHigh', ' '));
    SetArrayLength(Result, HighA + 1);
    for i := 0 to HighA do begin
      if (i <> 0) then begin
        HighB := StrtoInt(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'MHigh', ' '));
        SetArrayLength(Result[i].Map, HighB);
        if (HighB >= 0) then for j := 0 to HighB - 1 do begin
          case (LowerCase(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'M' + InttoStr(j + 1) + 'Style', ' '))) of
            '0', 'normal', 'regular', 'exact', 'match': Result[i].Map[j].Style := 0;
            '1', 'mask', 'maskcheck', 'wildcard', 'wildcards': Result[i].Map[j].Style := 1;
            '2', 'regular expressions', 'regular expression', 'reg exp', 'regularexpressions', 'regularexpression', 'regexp': Result[i].Map[j].Style := 2;
          end;
          Result[i].Map[j].Name := ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'M' + InttoStr(j + 1), '');
        end;
      end;
      Result[i].DisableFlags := StrtoBool(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'DisableFlags', ' '), false);
      Result[i].IgnoreWeapons := StrtoBool(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'IgnoreWeapons', ' '), false);
      for j := 0 to 5 do begin
        if (j <> 5) then begin
          if (Result[i].IgnoreWeapons = false) then begin
            Weapons := ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'T' + InttoStr(j) + 'Weapons', '');
            if (Length(Weapons) = 14) then for k := 1 to 14 do Result[i].Team[j].Weapon[k] := StrtoBool(Weapons[k], false) else begin
              WriteLn(' [*] [Error] ' + ScriptName + ' -> (ReadData): Invalid datatype');
              Result := Group;
              exit;
            end;
          end;
          Result[i].Team[j].AllowPickup := StrtoBool(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'T' + InttoStr(j) + 'AllowPickup', ' '), true);
          Result[i].Team[j].DealDmgMtp := StrtoFloat(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'T' + InttoStr(j) + 'DealDmgMtp', ' '));
          Result[i].Team[j].RecvDmgMtp := StrtoFloat(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'T' + InttoStr(j) + 'RecvDmgMtp', ' '));
        end;
        Result[i].Team[j].Balance := StrtoInt(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'T' + InttoStr(j) + 'Balance', ' '));
      end;
      HighB := StrtoInt(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'CHigh', ' '));
      SetArrayLength(Result[i].Command, HighB);
      if (HighB > 0) then for j := 0 to HighB - 1 do Result[i].Command[j] := ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'C' + InttoStr(j + 1), '');
      HighB := StrtoInt(ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'WHigh', ' '));
      SetArrayLength(Result[i].Welcome, HighB);
      if (HighB > 0) then for j := 0 to HighB - 1 do Result[i].Welcome[j] := ReadINI(Filename, 'Groups', 'G' + InttoStr(i) + 'W' + InttoStr(j + 1), '');
    end;
  except
    WriteLn(' [*] [Error] ' + ScriptName + ' -> (ReadData): Invalid datatype');
    Result := Group;
  end;
end;

procedure ActivateServer();
var
  i, j: byte;
begin
  if (CurrentMap = '') then CurrentMap := GetPiece(ReadFile('mapslist.txt'), Chr(13) + Chr(10), 0);
  Group := ReadData('scripts/' + ScriptName + '/data.ini');
  AfterMapChange := true;
  GID := 0;
  for i := 1 to GetArrayLength(Group) - 1 do for j := 0 to GetArrayLength(Group[i].Map) - 1 do begin
    case (Group[i].Map[j].Style) of
      0: if (LowerCase(Group[i].Map[j].Name) = LowerCase(CurrentMap)) then begin
        GID := i;
        break;
      end;
      1: if (MaskCheck(LowerCase(CurrentMap), LowerCase(Group[i].Map[j].Name))) then begin
        GID := i;
        break;
      end;
      2: if (RegExpMatch(LowerCase(Group[i].Map[j].Name), LowerCase(CurrentMap))) then begin
        GID := i;
        break;
      end;
    end;
  end;
end;

procedure AppOnIdle(Ticks: integer);
var
  i, j: byte;
begin
  if (AfterMapChange) then begin
    AfterMapChange := false;
    if (Group[GID].IgnoreWeapons = false) then for i := 1 to 32 do if (GetPlayerStat(i, 'Active') = true) then for j := 1 to 14 do SetWeaponActive(i, j, Group[GID].Team[VnttoInt(GetPlayerStat(i, 'Team'))].Weapon[j]);
  end;
end;

procedure OnMapChange(NewMap: string);
var
  i, j: byte;
begin
  AfterMapChange := true;
  GID := 0;
  for i := 1 to GetArrayLength(Group) - 1 do for j := 0 to GetArrayLength(Group[i].Map) - 1 do begin
    case (Group[i].Map[j].Style) of
      0: if (LowerCase(Group[i].Map[j].Name) = LowerCase(NewMap)) then begin
        GID := i;
        break;
      end;
      1: if (MaskCheck(LowerCase(NewMap), LowerCase(Group[i].Map[j].Name))) then begin
        GID := i;
        break;
      end;
      2: if (RegExpMatch(LowerCase(Group[i].Map[j].Name), LowerCase(NewMap))) then begin
        GID := i;
        break;
      end;
    end;
  end;
  if (GetArrayLength(Group[GID].Command) > 0) then for i := 0 to GetArrayLength(Group[GID].Command) - 1 do Command('/' + Group[GID].Command[i]);
end;

procedure OnJoinGame(ID, Team: byte);
var
  i: byte;
begin
  if (GetArrayLength(Group[GID].Welcome) > 0) then for i := 0 to GetArrayLength(Group[GID].Welcome) - 1 do SaytoPlayer(ID, Group[GID].Welcome[i]);
end;

procedure OnJoinTeam(ID, Team: byte);
var
  i: byte;
  Players: array[0..4] of byte;
  Points: array[0..4] of integer;
  High: integer;
  HighTeams: string;
begin
  for i := 1 to 32 do if (GetPlayerStat(i, 'Team') <> 5) then Players[VnttoInt(GetPlayerStat(i, 'Team'))] := Players[VnttoInt(GetPlayerStat(i, 'Team'))] + 1;
  if (Team <> 5) then Players[Team] := Players[Team] - 1;
  for i := 0 to 4 do Points[i] := Group[GID].Team[i].Balance * Players[i];
  for i := 0 to 4 do if (Group[GID].Team[i].Balance <> 255) then if (Points[i] < High) then begin
    High := Points[i];
    HighTeams := InttoStr(i)
  end else if (Points[i] = High) then HighTeams := HighTeams + InttoStr(i);
  for i := 0 to 5 do if ((ContainsString(HighTeams, InttoStr(i)) = false) and (Group[GID].Team[i].Balance = 0)) then HighTeams := HighTeams + InttoStr(i);
  if (ContainsString(HighTeams, InttoStr(Team)) = false) then begin
    i := Random(0, 5);
    while (ContainsString(HighTeams, InttoStr(i)) = false) do i := Random(0, 5);
    Command('/setteam' + InttoStr(i) + ' ' + InttoStr(ID));
    SaytoPlayer(ID, 'That team is full with players.');
  end;
  if ((Group[GID].IgnoreWeapons = false) and (Team <> 5)) then for i := 1 to 14 do SetWeaponActive(ID, i, Group[GID].Team[Team].Weapon[i]);
end;

procedure OnWeaponChange(ID, PrimaryNum, SecondaryNum: byte);
begin
  PrimaryNum := RealtoListWeapNum(PrimaryNum);
  if ((PrimaryNum <> 0) and (Group[GID].Team[VnttoInt(GetPlayerStat(ID, 'Team'))].AllowPickup = false)) then if (Group[GID].Team[VnttoInt(GetPlayerStat(ID, 'Team'))].Weapon[PrimaryNum] = false) then ForceWeapon(ID, SecondaryNum, 255, 0);
end;

function OnPlayerDamage(Victim, Shooter: byte; Damage: integer): integer;
begin
  Damage := Round(Damage * Group[GID].Team[VnttoInt(GetPlayerStat(Shooter, 'Team'))].DealDmgMtp * Group[GID].Team[VnttoInt(GetPlayerStat(Victim, 'Team'))].RecvDmgMtp);
  Result := Damage;
end;

procedure OnFlagGrab(ID, TeamFlag: byte; GrabbedInBase: boolean);
begin
  if (Group[GID].DisableFlags) then ReturnFlag(TeamFlag);
end;

data.ini example

[Groups]
GHigh=1

G0DisableFlags=false
G0IgnoreWeapons=true
G0T0Weapons=11111111111111
G0T0AllowPickup=true
G0T0Balance=-1
G0T0DealDmgMtp=1
G0T0RecvDmgMtp=1
G0T1Weapons=11111111111111
G0T1AllowPickup=true
G0T1Balance=1
G0T1DealDmgMtp=1
G0T1RecvDmgMtp=1
G0T2Weapons=11111111111111
G0T2AllowPickup=true
G0T2Balance=1
G0T2DealDmgMtp=1
G0T2RecvDmgMtp=1
G0T3Weapons=11111111111111
G0T3AllowPickup=true
G0T3Balance=-1
G0T3DealDmgMtp=1
G0T3RecvDmgMtp=1
G0T4Weapons=11111111111111
G0T4AllowPickup=true
G0T4Balance=-1
G0T4DealDmgMtp=1
G0T4RecvDmgMtp=1
G0T5Balance=0
G0CHigh=2
G0C1=loadwep weapons
G0C2=say No mod available on this map
G0WHigh=1
G0W1=Welcome! No mod on this map.

G1MHigh=1
G1M1=ctf_*
G1M1Style=mask
G1DisableFlags=true
G1IgnoreWeapons=false
G1T0Weapons=00000000001000
G1T0AllowPickup=false
G1T0Balance=-1
G1T0DealDmgMtp=0
G1T0RecvDmgMtp=10
G1T1Weapons=11111101101100
G1T1AllowPickup=false
G1T1Balance=0
G1T1DealDmgMtp=1
G1T1RecvDmgMtp=10
G1T2Weapons=00000000000010
G1T2AllowPickup=false
G1T2Balance=0
G1T2DealDmgMtp=10
G1T2RecvDmgMtp=0.25
G1T3Weapons=00000000001000
G1T3AllowPickup=false
G1T3Balance=-1
G1T3DealDmgMtp=0
G1T3RecvDmgMtp=10
G1T4Weapons=00000000001000
G1T4AllowPickup=false
G1T4Balance=-1
G1T4DealDmgMtp=0
G1T4RecvDmgMtp=10
G1T5Balance=0
G1CHigh=2
G1C1=loadwep zombies
G1C2=say Zombies! Alpha for humans; Bravo for zombies
G1WHigh=1
G1W1=Welcome to ZOMBIES! Alpha=humans; Bravo=zombies