Official Soldat Forums

Server Talk => Scripting Releases => Topic started by: soldat-game on January 31, 2022, 03:59:58 pm

Title: Spawnpoints control
Post by: soldat-game on January 31, 2022, 03:59:58 pm
Script Name: Spawnpoints control
Script Description: With this script you can delete and add new respawn points without interfering with the map.
Original Author(s): Dominik
Core Version: 1.0
Test on server: 2.8.2
Download: Attachment (https://forums.soldat.pl/index.php?action=dlattach;topic=45582.0;attach=34194)

Incredibly useful script that is useful for converting maps from ctf to deatchmatch or teammatch and more.

/displayspawns - This command will enable the visibility of the player spawnpoints. The designation is a sign "+" and assigned team color. The command works in switch mode. (https://forums.soldat.pl/index.php?action=dlattach;topic=45582.0;attach=34197;image)
/removeallspawn - Clears the entire map from all spawnpoints.
/removenearspawn - Clears the entire map from all spawnpoints. The maximum distance can be set here "Nearby_Spawn_Max_Dist = 50;" at the beginning of the script
/createspawn <0-4> Creates a spawnpoin for team <0 - 4> is the team id. 0 - No team, 1 - Alpha, 2 - Bravo, 3 - Charlie, 4 - Delta. Creates in the place where you are currently.
/createspawn - Creates a spawnpoin for no team. Creates in the place where you are currently.
/countspawns - Will print a list of all available spawnpoints.
/saveallspawns - Saves your own spawn points settings. As a result, changing the map will not remove them.

If you have saved the configuration of spawnpoints, and want to restore default settings - go to the "data" folder in the script folder and remove a file named as a map name next change map.
Remember that in deathmatch (no team) mode, players can respawn on objects such as flags, when they do not have their respawn point.


Configuration:
Code: [Select]
GOOD = $66CC66;
BAD = $B22222;
Nearby_Spawn_Max_Dist = 50;


Code: (Pascal) [Select]
unit Respawn_Controls;

interface

const
GOOD = $66CC66;
BAD = $B22222;
Nearby_Spawn_Max_Dist = 50;

type TMap_Spawns = record
Active: boolean;
Style: byte;
X, Y: LongInt;
end;

var
Map_Data: array of TMap_Spawns;
Active_Display: array[1..32] of boolean;
Used_Spawns: array of boolean;
Map_Is_Change: boolean;

implementation

function GetPieceSC3(Str, Reg: string; Number: Word): string;
var Res: TStringList;
begin
try
Res := File.CreateStringList;
SplitRegExpr(QuoteRegExprMetaChars(Reg), Str, Res);
Result := Res.Strings[Number];
except
Result := '';
finally
Res.Free;
end;
end;

procedure LeaveGame(Player: TActivePlayer; Kicked: Boolean);
begin
Active_Display[Player.ID] := false;
end;

function Admins_Commands(Player: TActivePlayer; Text: string): boolean;
var New_Spawn: TNewSpawnPoint; Data: TStringList; Lower_Case_Text: String; Temp_Dist, Last_Min_Dist: Single; i, Temp_Byte: byte; Found_Data: array[0..4] of byte;
begin
Result := false;
Lower_Case_Text := LowerCase(Text);

if Lower_Case_Text = '/displayspawns' then begin
if Active_Display[Player.ID] then begin
Active_Display[Player.ID] := false;
Player.WriteConsole('displayspawns = false', BAD);
for i := 1 to 254 do Player.WorldText(i+30, ' ', 1, $808080, 0.001, 0, 0);
end else
begin
Active_Display[Player.ID] := true;
Player.WriteConsole('displayspawns = true', GOOD);
end;
exit;
end;

if Lower_Case_Text = '/removeallspawn' then begin
for i := 1 to 254 do if Map.Spawns[i].Active then begin
if (Map.Spawns[i].Style = 0) or (Map.Spawns[i].Style = 1) or (Map.Spawns[i].Style = 2) or (Map.Spawns[i].Style = 3) or (Map.Spawns[i].Style = 4) then Map.Spawns[i].Active := false;
inc(Temp_Byte, 1);
end;
Player.WriteConsole('Remove all '+inttostr(Temp_Byte)+' players spawnpoints.',GOOD);
exit;
end;

if Lower_Case_Text = '/removenearspawn' then begin
Last_Min_Dist := Nearby_Spawn_Max_Dist;
for i := 1 to 254 do if Map.Spawns[i].Active then begin
if (Map.Spawns[i].Style = 0) or (Map.Spawns[i].Style = 1) or (Map.Spawns[i].Style = 2) or (Map.Spawns[i].Style = 3) or (Map.Spawns[i].Style = 4) then begin
Temp_Dist := Distance(Map.Spawns[i].X, Map.Spawns[i].Y, Player.X, Player.Y);
if Temp_Dist < Nearby_Spawn_Max_Dist then if Temp_Dist < Last_Min_Dist then begin
Last_Min_Dist := Temp_Dist;
Temp_Byte := i;
end;
end;
end;
if Temp_Byte <> 0 then begin
Player.WriteConsole('Remove player spawnpoint ID: '+inttostr(Temp_Byte)+', X: '+inttostr(Map.Spawns[Temp_Byte].X)+', Y: '+inttostr(Map.Spawns[Temp_Byte].Y),GOOD);
Map.Spawns[Temp_Byte].Active := false;
end else Player.WriteConsole('No player spawnpoints found nearby.',BAD);
exit;
end;

if ExecRegExpr('^(\/createspawn\s[0-4]|\/createspawn)$',Lower_Case_Text) then begin
try
New_Spawn := TNewSpawnPoint.Create;
New_Spawn.Active := true;
New_Spawn.X := Round(Player.X);
New_Spawn.y := Round(Player.Y-15);
if Length(Lower_Case_Text) > 12 then New_Spawn.Style := strtoint(GetPieceSC3(Lower_Case_Text,' ', 1)) else New_Spawn.Style := 0;
Map.AddSpawnPoint(New_Spawn);
except
Player.WriteConsole('Failed to add player spawnpoint!',BAD);
finally
New_Spawn.Free;
Player.WriteConsole('Add player spawnpoint X: '+inttostr(Round(Player.X))+', Y: '+inttostr(Round(Player.Y)),GOOD);
end;
exit;
end;

if Lower_Case_Text = '/countspawns' then begin
for i := 1 to 254 do if Map.Spawns[i].Active then begin
if Map.Spawns[i].Style = 0 then inc(Found_Data[0],1);
if Map.Spawns[i].Style = 1 then inc(Found_Data[1],1);
if Map.Spawns[i].Style = 2 then inc(Found_Data[2],1);
if Map.Spawns[i].Style = 3 then inc(Found_Data[3],1);
if Map.Spawns[i].Style = 4 then inc(Found_Data[4],1);
end;
if Found_Data[0] + Found_Data[1] + Found_Data[2] + Found_Data[3] + Found_Data[4] > 0 then begin
Player.WriteConsole('Found on this map '+Game.CurrentMap+' active player spawns: ', GOOD);
Player.WriteConsole('No team spawns: '+inttostr(Found_Data[0]), GOOD);
Player.WriteConsole('Alpha   spawns: '+inttostr(Found_Data[1]), GOOD);
Player.WriteConsole('Bravo   spawns: '+inttostr(Found_Data[2]), GOOD);
Player.WriteConsole('Charlie spawns: '+inttostr(Found_Data[3]), GOOD);
Player.WriteConsole('Delta   spawns: '+inttostr(Found_Data[4]), GOOD);
end else Player.WriteConsole('No found player spawnpoint on this map '+Game.CurrentMap+'.', BAD);
end;

if Lower_Case_Text = '/saveallspawns' then begin
Data := File.CreateStringList();
for i := 1 to 254 do if Map.Spawns[i].Active then begin
if (Map.Spawns[i].Style = 0) or (Map.Spawns[i].Style = 1) or (Map.Spawns[i].Style = 2) or (Map.Spawns[i].Style = 3) or (Map.Spawns[i].Style = 4) then begin
Data.Append('true');
Data.Append(inttostr(Map.Spawns[i].Style));
Data.Append(inttostr(Map.Spawns[i].X));
Data.Append(inttostr(Map.Spawns[i].Y));
end;
end;
if Data.Count > 0 then begin
Data.SaveToFile(Script.Dir+'\data\'+Game.CurrentMap);
Player.WriteConsole('New '+inttostr(Data.Count/4)+' player spawnpoints layout has been saved.', GOOD);
end else Player.WriteConsole('No players spawn points to save.', BAD);
Data.Free;

end;

end;

procedure Timers(Ticks: integer);
var i, c: byte;
begin
for i := 1 to 32 do if Players[i].Active then if Active_Display[i] then for c := 1 to 254 do if Map.Spawns[c].Active then begin
case Map.Spawns[c].Style of
0: Players[i].WorldText(c+30, '+', 80, $808080, 0.08, Map.Spawns[c].X, Map.Spawns[c].Y);
1: Players[i].WorldText(c+30, '+', 80, $FF0000, 0.08, Map.Spawns[c].X, Map.Spawns[c].Y);
2: Players[i].WorldText(c+30, '+', 80, $0000FF, 0.08, Map.Spawns[c].X, Map.Spawns[c].Y);
3: Players[i].WorldText(c+30, '+', 80, $FFFF00, 0.08, Map.Spawns[c].X, Map.Spawns[c].Y);
4: Players[i].WorldText(c+30, '+', 80, $00FF00, 0.08, Map.Spawns[c].X, Map.Spawns[c].Y);
end;
end;
end;

procedure After_Change(NewMap: string);
var New_Spawn: TNewSpawnPoint; i: byte;
begin
if Length(Map_Data) > 0 then begin

for i := 1 to 254 do if Map.Spawns[i].Active then begin
if (Map.Spawns[i].Style = 0) or (Map.Spawns[i].Style = 1) or (Map.Spawns[i].Style = 2) or (Map.Spawns[i].Style = 3) or (Map.Spawns[i].Style = 4) then Map.Spawns[i].Active := false;
end;

for i := 0 to Length(Map_Data)-1 do begin
try
New_Spawn := TNewSpawnPoint.Create;
New_Spawn.Active := true;
New_Spawn.X := Map_Data[i].X;
New_Spawn.y := Map_Data[i].Y;
New_Spawn.Style := Map_Data[i].Style;
Map.AddSpawnPoint(New_Spawn);
except
Players.WriteConsole('Failed to add player spawnpoint! (ID: '+inttostr(i)+')',BAD);
finally
New_Spawn.Free;
end;
end;

for i := 1 to 32 do if Players[i].Active then Players[i].ChangeTeam(0, TJoinSilent);
end;

Map_Is_Change := false;
end;

procedure Before_Change(NewMap: string);
var Data: TStringList; Spawnpoints_Counts, i, Temp_Data_ID, Counts: byte;
begin
Map_Is_Change := true;
SetLength(Map_Data, 0);

if File.Exists(Script.Dir+'\data\'+NewMap) then begin
Data := File.CreateStringListFromFile(Script.Dir+'\data\'+NewMap);

if Data.Count > 0 then begin
Spawnpoints_Counts := Data.Count/4;
for i := 0 to Spawnpoints_Counts - 1 do if Data[Temp_Data_ID] = 'true' then begin
SetLength(Map_Data, Counts + 1);
SetLength(Used_Spawns, Counts + 1);
Used_Spawns[Counts] := false;
Map_Data[Counts].Active := true;
Map_Data[Counts].Style := strtoint(Data[Temp_Data_ID+1]);
Map_Data[Counts].X := strtoint(Data[Temp_Data_ID+2]);
Map_Data[Counts].Y := strtoint(Data[Temp_Data_ID+3]);
Temp_Data_ID := Temp_Data_ID + 4;
inc(Counts, 1);
end;
end;

Data.Free;
end;

end;

function OnDamage(Shooter, Victim: TActivePlayer; Damage: Single; BulletId: byte): Single;
begin
if Map_Is_Change then result := 0 else Result := Damage;
end;

procedure ScriptDecl();
var i:byte;
begin
Game.OnLeave := @LeaveGame;
Game.OnAdminCommand := @Admins_Commands;
Game.TickThreshold := 5;
Game.OnClockTick := @Timers;
Map.OnBeforeMapChange := @Before_Change;
Map.OnAfterMapChange := @After_Change;
for i := 1 to 32 do Players[i].OnDamage := @OnDamage;
end;

initialization
begin
ScriptDecl();
end;

end.

(https://forums.soldat.pl/index.php?action=dlattach;topic=45582.0;attach=34195;image)
(https://forums.soldat.pl/index.php?action=dlattach;topic=45582.0;attach=34201;image)
(https://forums.soldat.pl/index.php?action=dlattach;topic=45582.0;attach=34199;image)