Hello! Today I present you a script for getting the information about the RS monsters from RS Bestiary api. About Api you can read: http://services.runescape.com/m=rswiki/en/Bestiary_APIs This script is based on the my json helper library and works in the lape interpreter. With this you can always get fresh information about any RS Monster.
Requrements:
- Simba => 1.0;
- Lape
The script can be used as 'Include' for any combat scripts. This contains a test code to show how it works.
Just place json.simba into your Simba 'Include' directory and start the script.
- I wouldn't recommend getting info with this script in the loop because working with huge pieces of information can take a lot of time. Get the needed info while the script settings are being initialized.
json.simba:
Simba Code:
//json helper library by Cynic
function CopyStop(const Str: string; const start: Integer; const Stop: Integer): string;
begin
Result := Copy(Str, Start, Stop - Start + 1);
end;
function DynArrayAppend(var V: TStringArray; const R: String): Integer; overload;
begin
Result := Length(V);
SetLength(V, Result + 1);
V[Result] := R;
end;
function DynArrayAppend(var V: TIntegerArray; const R: integer): Integer; overload;
begin
Result := Length(V);
SetLength(V, Result + 1);
V[Result] := R;
end;
function JSONEscapeDecode(const JSONData: string): string;
var
ptr: integer = 1;
moji_hex: string;
moji: string = '';
begin
Result := '';
repeat
while (ptr <= length(JSONData)) do
begin
if ptr > length(JSONData) then
Exit;
case JSONData[ptr] of
'\':
begin
if ptr >= length(JSONData) then
Exit;
inc(ptr);
case JSONData[ptr] of
'u':
begin
Inc(ptr);
Moji_Hex := '';
Moji_Hex := Uppercase(Copy(JSONData, ptr, 4));
Moji := '';
Moji := ('$' + Moji_Hex);
Result := Result + Moji;
Inc(ptr, 3);
end;
else
Result := Result + JSONData[ptr];
end;
end;
else
Result := Result + JSONData[ptr];
end;
Inc(ptr);
end;
until ptr >= length(JSONData);
end;
function JSONDataIsList(const JSONData: string): Boolean;
begin
Result := false;
if Length(Trim(JSONData)) = 0 then
exit;
if Trim(JSONData)[1] in ['{', '[', '('] then
Result := True;
end;
function JSONDataIsObject(const JSONData: string): Boolean;
begin
Result := false;
if Length(Trim(JSONData)) = 0 then
exit;
if Trim(JSONData)[1] in ['{'] then
Result := True;
end;
function JSONDataIsArray(const JSONData: string): Boolean;
begin
Result := false;
if Length(Trim(JSONData)) = 0 then
exit;
if Trim(JSONData)[1] in ['['] then
Result := True;
end;
function JSONDataIsNumber(const JSONData: string): Boolean;
var
IndexPOS: Integer;
begin
Result := false;
if Length(Trim(JSONData)) = 0 then
exit;
Result := True;
for IndexPos := 1 to Length(JSONData) do
if not (JSONData[IndexPos] in [' ', '.', 'e', 'E', '-', '+', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) then
begin
Result := False;
Exit;
end;
end;
function JSONDataIsString(const JSONData: string): Boolean;
begin
Result := false;
if Length(Trim(JSONData)) = 0 then
exit;
if Trim(JSONData)[1] in ['"'] then
Result := True;
end;
function JSONDataIsKeyValuePair(const JSONData: string): Boolean;
var
InputPos: Integer = 0;
SeparCount: Integer = 0;
InQuote: Boolean = False;
BraceLevel: Integer = 0;
begin
Result := false;
if Length(Trim(JSONData)) = 0 then
exit;
while (InputPOS < length(JSONData)) do
begin
Inc(InputPos);
case JSONData[InputPos] of
'"':
begin
if InputPos = 1 then
InQuote := not InQuote
else if JSONData[InputPos - 1] <> '\' then
InQuote := not InQuote;
end;
'{': Inc(BraceLevel);
'}': Dec(BraceLevel);
end;
if (not InQuote) and (BraceLevel = 0) then
if JSONData[InputPos] = ':' then
inc(SeparCount);
end;
Result := (SeparCount = 1);
end;
function JSON2TSA(const JSONString: AnsiString; var Decoded: TStringArray): Integer;
const
ListItemSep = ',';
var
Pos: Integer;
NestCount: Integer = 0;
CopyPos: Integer = 1;
TmpStr: string;
InQuote: Boolean = False;
begin
SetLength(Decoded,0);
{ if not JSONDataIsList(JSONString) then
begin
Result := - 1;
Exit;
end; }
for Pos := 1 to Length(JSONString) do
begin
case JSONString[Pos] of
'"':
begin
if pos = 1 then
InQuote := not InQuote
else if JSONString[Pos - 1] <> '\' then
InQuote := not InQuote;
end;
'(', '[', '{':
if not InQuote then
Inc(NestCount);
')', ']', '}':
if not InQuote then
begin
Dec(NestCount);
if NestCount = 0 then
begin
TmpStr := Trim(CopyStop(JSONString, CopyPos + 1, Pos - 1));
// WriteLn(TMPStr);
DynArrayAppend(Decoded,tmpstr);
CopyPos := Pos;
end;
end;
ListItemSep:
if not InQuote then
begin
if NestCount = 1 then
begin
TmpStr := Trim(CopyStop(JSONString, CopyPos + 1, Pos - 1));
// WriteLn(TMPStr);
DynArrayAppend(Decoded,tmpstr);
CopyPos := Pos;
end;
end;
end;
end;
Result := 0;
end;
function JSONGetValueByKey(const JSONList: TStringArray; const Key: string): string;
var
i: integer;
_Key: string;
Len: integer;
DelimiterPos: Integer;
begin
Result := '';
Len := Length(JSONList);
for i := 0 to Len - 1 do
begin
DelimiterPos := Pos(':', JSONList[i]);
if DelimiterPOS > 1 then
begin
_key := copy(JSONList[i], 1, DelimiterPOS - 1);
if _key = key then
begin
Result := CopyStop(JSONList[i], DelimiterPOS + 1, Length(JSONList[i]));
Exit;
end;
end;
end;
end;
function JSONTreeGet(const JSONString: string; const JSONPath: string): string;
var
InputPOS: Integer;
SimpleKeyStartPos: Integer;
ThisKey: string;
JSONList: TSTringArray;
begin
SetLength(JSONList, 1);
if Length(JSONPath) = 0 then
exit;
InputPOS := 0;
SimpleKeyStartPos := 0;
Result := JSONString;
repeat
Inc(InputPOS);
SimpleKeyStartPos := InputPos;
while (InputPOS < length(JSONPath)) and (JSONPath[InputPos] <> ':') do
Inc(InputPos);
if JSONPath[InputPos] <> ':' then
ThisKey := CopyStop(JSONPath, SimpleKeyStartPos, InputPos)
else
ThisKey := CopyStop(JSONPath, SimpleKeyStartPos, InputPos - 1);
if Length(ThisKey) = 0 then
Exit;
JSON2TSA(Result, JSONList);
Result := JSONGetValueByKey(JSONList, ThisKey);
until InputPOS >= Length(JSONPath);
end;
procedure JSONTreeGetMultiple(const JSONString: string; const JSONPath: string; var ValueList: TStringArray);
var
InputPOS: Integer;
SimpleKeyStartPos: Integer;
ThisKey: string;
JSONList: TStringArray;
tmpStr: string;
Found: Boolean;
begin
SetLEngth(JsonList, 1);
if Length(JSONPath) = 0 then
exit;
repeat
Found := false;
InputPOS := 0;
SimpleKeyStartPos := 0;
tmpStr := JSONString;
repeat
Inc(InputPOS);
SimpleKeyStartPos := InputPos;
while (InputPOS < length(JSONPath)) and (JSONPath[InputPos] <> ':') do
Inc(InputPos);
if JSONPath[InputPos] <> ':' then
ThisKey := CopyStop(JSONPath, SimpleKeyStartPos, InputPos)
else
ThisKey := CopyStop(JSONPath, SimpleKeyStartPos, InputPos - 1);
if Length(ThisKey) = 0 then
Exit;
JSON2TSA(tmpStr, JSONList);
tmpStr := JSONGetValueByKey(JSONList, ThisKey);
if (InputPOS = Length(JSONPath)) and (tmpstr <> '') then
begin
DynArrayAppend(ValueList,TmpStr);
tmpStr := '';
Found := True;
end;
until InputPOS >= Length(JSONPath);
until not Found;
end;
function JSONGetKey(const JSONData: string): string;
var
InputPos: integer = 0;
begin
if Length(JSONData) = 0 then
exit;
if JSONData[1] in ['{', '[', '('] then
exit;
while (InputPOS < length(JSONData)) and (JSONData[InputPos] <> ':') do
Inc(InputPos);
case JSONData[InputPos] of
':': Result := Trim(CopyStop(JSONData, 1, InputPos - 1))
else
Result := '';
end;
end;
function JSONGetValue(const JSONData: string): string;
var
InputPos: integer = 0;
begin
Result := 'not set';
if Length(JSONData) = 0 then
exit;
if JSONData[1] in ['{', '[', '('] then
exit;
while (InputPOS < length(JSONData)) and (JSONData[InputPos] <> ':') do
Inc(InputPos);
case JSONData[InputPos] of
':': Result := Trim(CopyStop(JSONData, InputPos + 1, Length(JSONData)))
else
Result := 'notfound';
end;
end;
function DeQuote(const input: string): string;
var
p: integer;
begin
result := input;
p := pos('"', result);
if p > 0 then
result := copy(result, p + 1, length(result) - p);
p := pos('"', result);
if p > 0 then
result := copy(result, 1, p - 1);
end;
function DeBracket(const input: string): string;
var
p: integer;
begin
result := input;
p := pos('[', result);
if p > 0 then
result := copy(result, p + 1, length(result) - p);
p := pos(']', result);
if p > 0 then
result := copy(result, 1, p - 1);
end;
function DeBrace(const input: string): string;
var
p: integer;
begin
result := input;
p := pos('{', result);
if p > 0 then
result := copy(result, p + 1, length(result) - p);
p := pos('}', result);
if p > 0 then
result := copy(result, 1, p - 1);
end;
function DeParen(const input: string): string;
var
p: integer;
begin
result := input;
p := pos('(', result);
if p > 0 then
result := copy(result, p + 1, length(result) - p);
p := pos(')', result);
if p > 0 then
result := copy(result, 1, p - 1);
end;
bestiary_api.simba:
Simba Code:
program bestiary_api;
{$i json.simba}
type
TFindedMonsters = record
Names: TStringArray;
Ids: TIntegerArray;
end;
TMonster = record
xp: double;
name: string;
Life: integer;
lvl: integer;
SlayerCat: string;
Description: string;
Agressive,MembersOnly: boolean;
Areas: TStringArray;
end;
const
BeastSearchUrl = 'http://services.runescape.com/m=itemdb_rs/bestiary/beastSearch.json?term=';
function GetFormattedUrl(const ItemName: string):string;
begin
result:=Replace(ItemName,#32,'+',[rfReplaceAll, rfIgnoreCase]);
end;
function GetBeastSearchJson(const Name: string):string;
begin
result:=GetPage(BeastSearchUrl+GetFormattedUrl(name));
end;
function FindMonsters(const Beasts: string): TFindedMonsters;
var
i,Brace: integer;
page,value: string;
Json, Beast: TStringArray;
begin
SetLength(Result.Ids,0);
SetLength(Result.Names,0);
page:=GetBeastSearchJson(Beasts);
if JSONDataIsList(page) then
begin
Json2TSA(page,json);
for i:=0 to length(json) - 1 do
begin
Json2TSA(json[i],Beast);
if (Length(Beast) > 2) then
exit;
if JSONDataIsKeyValuePair(beast[0]) then
begin
DynArrayAppend(Result.Ids,StrToInt(DeQuote(JsonGetValue(beast[0]))));
Value:=DeQuote(JsonGetValue(beast[1]));
Brace:= Pos('(',Value);
Value:=CopyStop(Value,0,Brace-2);
if length(Value) > 0 then
DynArrayAppend(Result.Names,Value) else
DynArrayAppend(Result.Names,DeQuote(JsonGetValue(beast[1])));
end;
end;
end;
end;
function FindMonstersByABC(const ABC: char): TFindedMonsters;
const
URL = 'http://services.runescape.com/m=itemdb_rs/bestiary/bestiaryNames.json?letter=';
var
i,Brace: integer;
page,value: string;
Json, Beast: TStringArray;
begin
SetLength(Result.Ids,0);
SetLength(Result.Names,0);
page:=GetPage(URL+UpperCase(ABC));
if JSONDataIsList(page) then
begin
Json2TSA(page,json);
for i:=0 to length(json) - 1 do
begin
Json2TSA(json[i],Beast);
if (Length(Beast) > 2) then
exit;
if JSONDataIsKeyValuePair(beast[0]) then
begin
DynArrayAppend(Result.Ids,StrToInt(DeQuote(JsonGetValue(beast[0]))));
Value:=DeQuote(JsonGetValue(beast[1]));
Brace:= Pos('(',Value);
Value:=CopyStop(Value,0,Brace-2);
if length(Value) > 0 then
DynArrayAppend(Result.Names,Value) else
DynArrayAppend(Result.Names,DeQuote(JsonGetValue(beast[1])));
end;
end;
end;
end;
function FindMonstersByLvl(const StartLvl,EndLvl: integer): TFindedMonsters;
const
URL = 'http://services.runescape.com/m=itemdb_rs/bestiary/levelGroup.json?identifier=';
var
i,Brace: integer;
page,value: string;
Json, Beast: TStringArray;
begin
SetLength(Result.Ids,0);
SetLength(Result.Names,0);
page:=GetPage(URL+IntToStr(StartLvl)+'-'+IntToStr(EndLvl));
if JSONDataIsList(page) then
begin
Json2TSA(page,json);
for i:=0 to length(json) - 1 do
begin
Json2TSA(json[i],Beast);
if (Length(Beast) > 2) then
exit;
if JSONDataIsKeyValuePair(beast[0]) then
begin
DynArrayAppend(Result.Ids,StrToInt(DeQuote(JsonGetValue(beast[0]))));
Value:=DeQuote(JsonGetValue(beast[1]));
Brace:= Pos('(',Value);
Value:=CopyStop(Value,0,Brace-2);
if length(Value) > 0 then
DynArrayAppend(Result.Names,Value) else
DynArrayAppend(Result.Names,DeQuote(JsonGetValue(beast[1])));
end;
end;
end;
end;
function FindMonstersByArea(const AreaName: string): TFindedMonsters;
const
URL = 'http://services.runescape.com/m=itemdb_rs/bestiary/areaBeasts.json?identifier=';
var
i,Brace: integer;
page,value: string;
Json, Beast: TStringArray;
begin
SetLength(Result.Ids,0);
SetLength(Result.Names,0);
page:=GetPage(URL+GetFormattedUrl(AreaName));
if JSONDataIsList(page) then
begin
Json2TSA(page,json);
for i:=0 to length(json) - 1 do
begin
Json2TSA(json[i],Beast);
if (Length(Beast) > 2) then
exit;
if JSONDataIsKeyValuePair(beast[0]) then
begin
DynArrayAppend(Result.Ids,StrToInt(DeQuote(JsonGetValue(beast[0]))));
Value:=DeQuote(JsonGetValue(beast[1]));
Brace:= Pos('(',Value);
Value:=CopyStop(Value,0,Brace-2);
if length(Value) > 0 then
DynArrayAppend(Result.Names,Value) else
DynArrayAppend(Result.Names,DeQuote(JsonGetValue(beast[1])));
end;
end;
end;
end;
//for debugging
procedure PrintMonsters(Const Monsters: TFindedMonsters);
var
i: integer;
begin
if Length(Monsters.Ids) <> Length(Monsters.Names) then
exit;
for i:=0 to Length(Monsters.ids) -1 do
WriteLn('Monster ='+ Monsters.Names[i]+','+'Id ='+IntToStr(Monsters.Ids[i]));
end;
function GetMonsterById(const Id: integer): TMonster;
const
URL = 'http://services.runescape.com/m=itemdb_rs/bestiary/beastData.json?beastid=';
var
i,Brace: integer;
page,key: string;
Json, Beast: TStringArray;
begin
page:=GetPage(URL+IntToStr(Id));
if JSONDataIsList(page) then
begin
Json2TSA(page,json);
for i:=0 to length(json) - 1 do
begin
key:=DeQuote(JsonGetKey(Json[i]));
case key of
'slayercat': result.SlayerCat:=DeQuote(JsonGetValue(Json[i]));
'xp': result.xp:=StrToFloat(DeQuote(JsonGetValue(Json[i])));
'name': result.name:=DeQuote(JsonGetValue(Json[i]));
'level': result.lvl:= StrToInt(DeQuote(JsonGetValue(Json[i])));
'description': result.Description:= DeQuote(JsonGetValue(Json[i]));
'lifepoints': result.Life:=StrToInt(DeQuote(JsonGetValue(Json[i])));
'areas': JSON2Tsa(JsonGetValue(Json[i]),result.Areas);
'agressive': result.agressive:=StrToBool(DeQuote(JsonGetValue(Json[i])));
'members':Result.MembersOnly:=StrToBool(DeQuote(JsonGetValue(Json[i])));
end;
end;
end;
end;
function GetAreaNames(): TStringArray;
var
i: integer;
begin
end;
Procedure PrintMonster(const Monster: TMonster);
begin
WriteLn('Monster name: '+Monster.name);
WriteLn('Description: '+Monster.Description);
WriteLn('Lvl:'+inttostr(monster.lvl));
WriteLn('XP: '+floattostr(monster.xp));
WriteLn('Life:'+IntToStr(monster.life));
WriteLn('Members:'+Booltostr(Monster.Membersonly));
WriteLn(Monster.Areas);
WriteLn('Agressive:'+BoolToStr(Monster.Agressive));
end;
var
Monsters: TFindedMonsters;
MonstersABC: TFindedMonsters;
MonstersLVL : TFindedMonsters;
MonstersArea: TFindedMonsters;
Monster: Tmonster;
i: integer;
begin
Monsters:=FindMonsters('sheep cow');
PrintMonsters(Monsters);
MonstersABC:=FindMonstersByABC('y');
PrintMonsters(MonstersABC);
for i:= 0 to Length(MonstersABC.Ids) - 1 do
begin
Monster:=GetMonsterbyId(MonstersAbc.ids[i]);
PrintMonster(Monster);
end;
MonstersLVL:=FindMonstersByLvl(200,250);
PrintMonsters(MonstersLVL);
for i:= 0 to Length(MonstersLVL.Ids) - 1 do
begin
Monster:=GetMonsterbyId(MonstersLVL.ids[i]);
PrintMonster(Monster);
end;
MonstersArea:=FindMonstersByArea('Zanaris');
PrintMonsters(MonstersArea);
end.
Cheers,
Cynic.