Script Name: MovePlayer Weapon- and Flag-loss Protection
Original Author(s): The One (loadspawninfo() from the hexer-code)
Core Version: 2.3
Server Version: 2.7.2
Script Description: Protection for annoying weapon- and flagloss bugs caused by MovePlayer(), catches 95% of those.
Usage: Simply call MoveplayerX(ID: byte; X, Y: Single) instead of the usual MovePlayer.
const
MAXSPAWNS = 254;
MAXOBJECTS = 130;
cWarning = $FF0000;
type
tplayer = record
primary,secondary,ammo, protecttimer: byte;
end;
tSpawn = record
active: boolean;
style: integer;
x,y: single;
end;
var soldier: array[1..32] of tplayer;
FlagReturnDelay, forceWeap: boolean;
AlphaFlagger, BravoFlagger, AlphaFlagSpawn, BravoFlagSpawn, HighestID: Byte;
spawns: array[0..254] of tSpawn;
A few help-procedures/functions are needed.
procedure loadspawninfo();
var i: integer;
begin
for i := 1 to MAXSPAWNS do
if (GetSpawnStat(i,'Active') = false) then
spawns[i].active := false
else begin
spawns[i].active := true;
spawns[i].style := GetSpawnStat(i,'Style');
spawns[i].x := GetSpawnStat(i,'X');
spawns[i].y := GetSpawnStat(i,'Y');
if spawns[i].style = 5 then AlphaFlagSpawn := i
else if spawns[i].style = 6 then BravoFlagSpawn := i;
end;
end;
function GOS(Primary: byte): byte;
begin
if Primary < 11 then Result := Primary + 4
else case Primary of
14: Result := 25;
15: Result := 24;
16: Result := 26;
end;
end;
function CalcMaxID: byte;
var i: byte;
begin
result := 0;
for i := 32 downto 1 do
If GetPlayerStat(i,'Active') = true then
begin
result := i;
exit;
end;
end;
procedure MovePlayerX(ID: byte; X, Y: single);
var Xb, Yb: single;
i: integer;
begin
//Moving Bots around will cause problems when trying to join the server, besides from not working
if not GetPlayerStat(ID, 'human') then exit;
for i := 1 to HighestID do
if i <> ID then
if GetPlayerStat(i, 'Active') then
begin
Soldier[i].Ammo := GetPlayerStat(i, 'Ammo');
Soldier[i].ProtectTimer := 2;
end;
Soldier[ID].Ammo := GetPlayerStat(ID, 'Ammo');
if Soldier[ID].Ammo = 0 then
if (Soldier[ID].Primary <> 15) or (Soldier[ID].Primary <> 255) then Soldier[ID].Ammo := 255;
Soldier[ID].ProtectTimer := 3;
MovePlayer(ID, X, Y);
end;
procedure TriggerFlagProtection;
var i, AlphaFlag, BravoFlag: byte;
X, Y: single;
begin
if spawns[250].active then
if not FlagReturnDelay then
begin
SetSpawnStat(250, 'Active', False);
spawns[250].active := False;
//Re-Enable old spawn
SetSpawnStat(AlphaFlagSpawn, 'Active', True);
spawns[AlphaFlagSpawn].active := True;
SetSpawnStat(BravoFlagSpawn, 'Active', True);
spawns[BravoFlagSpawn].active := True;
WriteLn('Hurray and +1 for the protection.');
end else FlagReturnDelay := False;
if AlphaFlagger > 0 then
If not GetPlayerStat(AlphaFlagger, 'Flagger') then
begin
for i := 1 to MAXOBJECTS do
if GetObjectStat(i, 'Active') then
if GetObjectStat(i, 'Style') = 2 then
begin
BravoFlag := i;
break;
end;
if BravoFlag = 0 then Exit;
i := AlphaFlagger;
AlphaFlagger := 0;
GetPlayerXY(i, X, Y);
//Bravo Flag thrown?
if (Distance(X, Y, GetObjectStat(BravoFlag, 'X'), GetObjectStat(BravoFlag, 'Y')) > 300) or (Soldier[i].ProtectTimer > 0) then
begin
X := X + GetPlayerStat(i, 'VelX') * 5; //You might need to play around with this.
Y := Y + GetPlayerStat(i, 'VelY') * 5; //since flag respawns with some delay, it doesn't land in player's arms always
//Disable old spawn
SetSpawnStat(BravoFlagSpawn, 'Active', False);
//Enable new spawn
SetSpawnStat(250, 'Active', True);
SetSpawnStat(250, 'Style', 6);
SetSpawnStat(250, 'X', X);
SetSpawnStat(250, 'Y', Y);
Spawns[250].Active := True;
FlagReturnDelay := True;
//Kill the flag
KillObject(BravoFlag);
WriteConsole(i, 'You lost the bravo flag! Flag spawning at your position in one second.', cWarning);
end else WriteConsole(i, 'You lost the bravo flag! Go get it!', cWarning);
end;
if BravoFlagger > 0 then
if not GetPlayerStat(BravoFlagger, 'Flagger') then
begin
for i := 1 to MAXOBJECTS do
if GetObjectStat(i, 'Active') then
if GetObjectStat(i, 'Style') = 1 then
begin
AlphaFlag := i;
break;
end;
if AlphaFlag = 0 then Exit;
i := BravoFlagger;
BravoFlagger := 0;
GetPlayerXY(i, X, Y);
//Alpha Flag thrown?
if (Distance(X, Y, GetObjectStat(AlphaFlag, 'X'), GetObjectStat(AlphaFlag, 'Y')) > 300) or (Soldier[i].ProtectTimer > 0) then
begin
X := X + GetPlayerStat(i, 'VelX') * 5; //You might need to play around with this.
Y := Y + GetPlayerStat(i, 'VelY') * 5; //since flag respawns with some delay, it doesn't land in player's arms always
//Disable old spawn
SetSpawnStat(AlphaFlagSpawn, 'Active', False);
//Enable new spawn
SetSpawnStat(250, 'Active', True);
SetSpawnStat(250, 'Style', 5);
SetSpawnStat(250, 'X', X);
SetSpawnStat(250, 'Y', Y);
Spawns[250].Active := True;
FlagReturnDelay := True;
//Kill the flag
KillObject(AlphaFlag);
WriteConsole(i, 'You lost the alpha flag! Flag spawning at your position in one second.', cWarning);
end else WriteConsole(i, 'You lost the alpha flag! Go get it!.', cWarning);
end;
end;
Here the events.
procedure OnWeaponChange(ID, PrimaryNum, SecondaryNum: byte);
var i: byte;
X, Y: single;
begin
if forceWeap then
begin
forceWeap := false;
Soldier[ID].Primary := PrimaryNum;
Soldier[ID].Secondary := SecondaryNum;
exit;
end;
if (Soldier[ID].ProtectTimer > 0) then
if PrimaryNum = 255 then //his primary changed to fists
if Soldier[ID].Primary <> 255 then //He had a primary weapon before
if Soldier[ID].Primary <> 14 then //it was no knife
if (Soldier[ID].Secondary <> 255) or (SecondaryNum <> Soldier[ID].Primary) then //He didn't switch weapons
begin
//Destroy the dropped weapon
for i := 1 to MAXOBJECTS do
if GetObjectStat(i, 'Style') = GOS(Soldier[ID].Primary) then
begin
GetPlayerXY(ID, X, Y);
if Distance(X, Y, GetObjectStat(i, 'X'), GetObjectStat(i, 'Y')) < 200 then
begin
KillObject(i);
Break;
end;
end;
//Return the old weapon
ForceWeap := True;
ForceWeapon(ID, Soldier[ID].Primary, Soldier[ID].Secondary, Soldier[ID].Ammo);
Soldier[ID].ProtectTimer := 2;
exit;
end;
Soldier[ID].Primary := PrimaryNum;
Soldier[ID].Secondary := SecondaryNum;
end;
procedure AppOnIdle(Ticks: integer);
var ii: byte;
begin
TriggerFlagProtection;
for ii := 1 to HighestID do
if soldier[ii].ProtectTimer > 0 then
Soldier[ii].ProtectTimer := Soldier[ii].ProtectTimer - 1;
end;
procedure OnMapChange(NewMap: string);
begin
AlphaFlagger := 0;
BravoFlagger := 0;
loadspawninfo();
end;
procedure OnPlayerKill(Killer, Victim: byte; Weapon: string);
begin
if Victim = AlphaFlagger then AlphaFlagger := 0
else if Victim = BravoFlagger then BravoFlagger := 0;
end;
procedure OnFlagReturn(ID, TeamFlag: byte);
begin
if TeamFlag = 1 then BravoFlagger := 0
else AlphaFlagger := 0;
end;
procedure OnFlagGrab(ID, TeamFlag: byte; GrabbedInBase: boolean);
begin
if TeamFlag = 1 then BravoFlagger := ID
else AlphaFlagger := ID;
end;
procedure OnJoinGame(ID, Team: byte);
begin
HighestID := CalcMaxID;
end;
procedure OnJoinTeam(ID, Team: byte);
begin
Soldier[ID].ProtectTimer := 0;
if ID = AlphaFlagger then AlphaFlagger := 0
else if ID = BravoFlagger then BravoFlagger := 0;
end;
procedure OnLeaveGame(ID, Team: byte; Kicked: boolean);
begin
HighestID := CalcMaxID;
Soldier[ID].ProtectTimer := 0;
if ID = AlphaFlagger then AlphaFlagger := 0
else if ID = BravoFlagger then BravoFlagger := 0;
end;
procedure OnFlagScore(ID, TeamFlag: byte);
begin
AlphaFlagger := 0;
BravoFlagger := 0;
end;
I extracted this from a bigger script, if you notice a mistake, please report it.