Author Topic: MovePlayer Weapon- and Flag-loss Protection  (Read 1944 times)

0 Members and 1 Guest are viewing this topic.

Offline TheOne

  • Soldier
  • **
  • Posts: 208
MovePlayer Weapon- and Flag-loss Protection
« on: January 08, 2012, 09:59:38 am »
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.


Code: [Select]
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.
Code: [Select]
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;


Code: [Select]
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.

Code: [Select]
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.
« Last Edit: January 09, 2012, 07:20:37 am by TheOne »

Offline TheOne

  • Soldier
  • **
  • Posts: 208
Re: MovePlayer Weapon- and Flag-loss Protection
« Reply #1 on: January 09, 2012, 07:19:21 am »
Small change in events, OnFlagScore I forgot.

EDIT: As I figured out, OnWeaponChange is called twice when two weapons of the player will change through that call, or never, if no weapon changes. Therefor forceWeap should be integer-typed, set to the right number when you call ForceWeapon and lowered by 1 every OnWeaponChange call.
« Last Edit: January 26, 2013, 04:44:04 am by TheOne »