SRL Archive - General

[MAGIC] Rethink MSI's Magic.simba


Coh3n

2011-01-09 18:51:32

I know it may be stupid to bring this up now instead of when it was actually written, but I'm now beginning to think it be a lot smarter to have our own TSpell type. It makes everything 100x easier. It could even be as specific as having a TBox of where to click the spell.

I think it would make our lives easier when we want to add more spells, and I think we should soon. Especially a superheater or something.

Thoughts?

3Garrett3

2011-01-09 19:19:14

I agree. Need help? :P

Coh3n

2011-01-09 19:54:28

From: 3Garrett3
I agree. Need help? :P

Lol always. ;)

Guess the first thing to do would be planning. This is what I have so far. :)

type
TMagicSpell = record
Name: string;
StatsName: string;
Level: Integer;
Experience: Integer;
ClickBox: TBox;
AutoCast: Boolean;
RequiredRunes: array[0..(RUNE_COUNT - 1)] of Integer;
end;

procedure MSI_LoadSpell(Spell: Integer);
begin
case Spell of
SPELL_WIND_STRIKE:
with MSI_Spells[Spell] do
begin
Name := 'Wind Strike';
StatsName := 'Wind Strikes';
Level := 1;
Experience := 10;
ClickBox := IntToBox();
AutoCast := True;
RequiredRunes[RUNE_AIR] := 1;
RequiredRunes[RUNE_MIND] := 1;
end;
end;
end;

NCDS

2011-01-09 20:03:42

From: Coh3n
Lol always. ;)

Guess the first thing to do would be planning. This is what I have so far. :)

type
TMagicSpell = record
Name: string;
StatsName: string;
Level: Integer;
Experience: Integer;
ClickBox: TBox;
AutoCast: Boolean;
RequiredRunes: array[0..(RUNE_COUNT - 1)] of Integer;
end;

procedure MSI_LoadSpell(Spell: Integer);
begin
case Spell of
SPELL_WIND_STRIKE:
with MSI_Spells[Spell] do
begin
Name := 'Wind Strike';
StatsName := 'Wind Strikes';
Level := 1;
Experience := 10;
ClickBox := IntToBox();
AutoCast := True;
RequiredRunes[RUNE_AIR] := 1;
RequiredRunes[RUNE_MIND] := 1;
end;
end;
end;


We would still need to accommodate for all the Spell sorts and such, unless we made the user only able to use one sort (probably wouldn't be that big of deal). Why may I ask do you feel this way now?

I personally really don't see the need since I've already added what we needed to SRL's Magic.scar, but perhaps I'm just missing something?

Please explain further. :)

Coh3n

2011-01-09 20:08:43

From: NCDS
We would still need to accommodate for all the Spell sorts and such, unless we made the user only able to use one sort (probably wouldn't be that big of deal). Why may I ask do you feel this way now?

I personally really don't see the need since I've already added what we needed to SRL's Magic.scar, but perhaps I'm just missing something?

Please explain further. :)

Well frankly, I don't want to work with SRL's magic.scar as I feel it's messy and unorganized, and sometimes, over-complicated. I think we can make this extremely simple while have it still working perfectly. I'm not sure why I feel this way now, maybe because everything else in MSI works this way, and it's all working really well. I also don't really like that we had to update (and will have to update) SRL's types, etc. just to make MSI work. I just really like this way of organizing as I feel it works really, really well.

For the spell modes, we could add to the type. Then have the script go to that spellmode before using the spell.

NCDS

2011-01-09 20:17:25

From: Coh3n
Well frankly, I don't want to work with SRL's magic.scar as I feel it's messy and unorganized, and sometimes, over-complicated. I think we can make this extremely simple while have it still working perfectly. I'm not sure why I feel this way now, maybe because everything else in MSI works this way, and it's all working really well. I also don't really like that we had to update (and will have to update) SRL's types, etc. just to make MSI work. I just really like this way of organizing as I feel it works really, really well.

I can understand that.
From: Coh3n

For the spell modes, we could add to the type. Then have the script go to that spellmode before using the spell.


Well, really we don't need to change SpellModes at all, it's just nice to have support for all of them (from the users point of view anyways). If we do this, I think it would be best to just make sure the 'normal' spell sort is selected and used with MSI.

Coh3n

2011-01-09 20:28:02

From: NCDS
I can understand that.


Well, really we don't need to change SpellModes at all, it's just nice to have support for all of them (from the users point of view anyways). If we do this, I think it would be best to just make sure the 'normal' spell sort is selected and used with MSI.

Yeah that would work, we'd need a scroll option if we needed to scroll to the bottom of the list. I'm gonna update my idea of the record. E: Nvm, just think about adding a Scroll: Boolean attribute.

NCDS

2011-01-09 20:36:40

From: Coh3n
Yeah that would work, we'd need a scroll option if we needed to scroll to the bottom of the list. I'm gonna update my idea of the record. E: Nvm, just think about adding a Scroll: Boolean attribute.


That's handled in SRL's SpellAvailable (called by SRL's Cast) assuming you still want us to use that?

Also, just so I'm on the same page, the purpose of this is mainly just to not rely on SRL's types?

Coh3n

2011-01-09 20:43:56

From: NCDS
Also, just so I'm on the same page, the purpose of this is mainly just to not rely on SRL's types?

Basically yeah. That way we can customize it as much as we need.

NCDS

2011-01-09 20:51:17

From: Coh3n
Basically yeah. That way we can customize it as much as we need.


Alright then. I would like to see RequireRunes as a 2DArray though see we can just do:

RequiredRunes := [[RUNE_AIR, 1], [RUNE_MIND, 1]];
Unless you had something in mind that wouldn't work with that?

Coh3n

2011-01-09 20:53:47

From: NCDS
Alright then. I would like to see RequireRunes as a 2DArray though see we can just do:

RequiredRunes := [[RUNE_AIR, 1], [RUNE_MIND, 1]];
Unless you had something in mind that wouldn't work with that?

No I think it would work just fine. It doesn't matter to be whether we use what I said or that. I like mine better, but that's personal preference I guess. I like it because EVERY rune is set to an amount for EVERY spell (most 0). Plus I just think it's easier. Just me though.

NCDS

2011-01-09 20:55:35

From: Coh3n
No I think it would work just fine. It doesn't matter to be whether we use what I said or that. I like mine better, but that's personal preference I guess. I like it because EVERY rune is set to an amount for EVERY spell (most 0). Plus I just think it's easier. Just me though.


Your the 'Leader' man, do your thing. :)

nickrules

2011-01-09 22:13:58

Types would be a good idea. Even better, you could use it in a super-generic form, and make it declared by the script, instead of loading a billion types into memory. Common TSpells could be kept in a file/folder somewhere.
As for TBoxes, could a box-generating algorithm be made based upon the spells default order number? Or maybe just called up by a function?
Basically what im getting at, is something like this



SPELL_WIND_STRIKE:
with MSI_Spells[Spell] do
begin
Name := 'Wind Strike';
StatsName := 'Wind Strikes';
Level := 1;
Experience := 10;
ClickBox := SpellToBox(3);
AutoCast := True;
RequiredRunes[RUNE_AIR] := 1;
RequiredRunes[RUNE_MIND] := 1;
end;

SpellToBox would then look up then return the TBox value, based upon constants
eg

case SpellNum of
0: IntToBox(2,32,3,45)
1: IntToBox(4,64,6,90)
//etc etc

NCDS

2011-01-09 22:32:37

From: nickrules
Types would be a good idea. Even better, you could use it in a super-generic form, and make it declared by the script, instead of loading a billion types into memory. Common TSpells could be kept in a file/folder somewhere.
As for TBoxes, could a box-generating algorithm be made based upon the spells default order number? Or maybe just called up by a function?
Basically what im getting at, is something like this



SPELL_WIND_STRIKE:
with MSI_Spells[Spell] do
begin
Name := 'Wind Strike';
StatsName := 'Wind Strikes';
Level := 1;
Experience := 10;
ClickBox := SpellToBox(3);
AutoCast := True;
RequiredRunes[RUNE_AIR] := 1;
RequiredRunes[RUNE_MIND] := 1;
end;

SpellToBox would then look up then return the TBox value, based upon constants
eg

case SpellNum of
0: IntToBox(2,32,3,45)
1: IntToBox(4,64,6,90)
//etc etc

SpellAvailable (called by Cast) in SRL uses an algorithm to set the boxes for the Spells. If we're going to do that, we may as well use the same one.

Coh3n

2011-01-09 23:18:17

From: NCDS
SpellAvailable (called by Cast) in SRL uses an algorithm to set the boxes for the Spells. If we're going to do that, we may as well use the same one.

There's also really no point in having a big cased function that loads a TBox when you can just set it when loading the type. Also, IIRC, the algorithm could never be tweaked right to work with all spells?

NCDS

2011-01-10 05:41:01

From: Coh3n
There's also really no point in having a big cased function that loads a TBox when you can just set it when loading the type. Also, IIRC, the algorithm could never be tweaked right to work with all spells?


I'm sure it could be, as it's quite close, but it's not right now, no.

Coh3n

2011-01-10 19:49:25

From: NCDS
I'm sure it could be, as it's quite close, but it's not right now, no.

Okay well I think we can take advantage of some of SRL's functions, but I think it would be much easier/organized if we had our own types as well.

Coh3n

2011-02-07 01:25:32

I did a little work on this tonight. I got down to MSI_Cast. I'd like to basically rewrite from MSI_Cast and down. Split things up, utilize the new type, and just generally clean it up.

const
SLOT_ALCH_LOW = 6;
SLOT_ALCH_HIGH = 16;

MAX_RUNES = 1000000000; // A billion

ANIM_COL_ALCH = 500; // Minimum pixel shift

CASTS_BEFORE_REPORT = 50; // Will perform this many casts before printing the report

SPELL_ARRAY_LENGTH = 27;

type
TMagicSpell = record
Name: string;
StatsName: string;
Level: Integer;
Experience: Integer;
Staffs: TIntegerArray;
ClickBox: TBox;
AutoCast: Boolean;
RequiredRunes: array[0..(RUNE_COUNT - 1)] of Integer;
end;

var
MSI_Spells: array[0..SPELL_ARRAY_LENGTH] of TMagicSpell;

procedure MSI_LoadSpell(Spell: Integer);
begin
case Spell of
SPELL_ALCH_LOW:
with MSI_Spells[Spell] do
begin
Name := 'Low Level Alchemy';
StatsName := 'Low Alchs';
Level := 21;
Experience := 10;
ClickBox := IntToBox();
AutoCast := False;
RequiredRunes[RUNE_FIRE] := 5;
RequiredRunes[RUNE_NATURE] := 1;
end;

SPELL_ALCH_HIGH:
with MSI_Spells[Spell] do
begin
Name := 'High Level Alchemy';
StatsName := 'High Alchs';
Level := 55;
Experience := 10;
ClickBox := IntToBox();
AutoCast := False;
RequiredRunes[RUNE_FIRE] := 5;
RequiredRunes[RUNE_NATURE] := 1;
end;
end;
end;

procedure MSI_LoadAllSpells();
var
i: Integer;
begin
for i := 0 to High(MSI_Spells) do
MSI_LoadSpell(i);
end;

function MSI_GetPossibleStaffs(Spells: TIntegerArray): TIntegerArray;
var
i: Integer;
begin
for i := 0 to High(Spells) do
Result := CombineIntArray(Result, MSI_Spells[Spells[i]].Staffs);

ClearSameIntegers(Result);
MSI_SubDebug('Possible Staffs: ' + ToStr(Result));
end;

{******************************************************************************}
{ function MSI_FindStaffs(): TIntegerArray; }
{ By: Coh3n }
{ Date: 14 November 2010 }
{ Description: Returns any staffs the player may have that would be useful for }
{ their spells }
{******************************************************************************}
function MSI_FindStaffs(Spells: TIntegerArray): TIntegerArray;
var
i, j, t, x, y: Integer;
tabs, possStaffs: TIntegerArray;
begin
MSI_AddHeader('MSI_FindStaffs');

if (GetCurrentTab = TAB_INV) then
tabs := [TAB_INV, TAB_EQUIP]
else
tabs := [TAB_EQUIP, TAB_INV];

possStaffs := MSI_GetPossibleStaffs(Spells);

for i := 0 to High(tabs) do
begin
for j := 0 to High(possStaffs) do
if (MSI_FindTool(possStaffs[j], tabs[i], x, y)) then
begin
if (tabs[i] = TAB_INV) then
MSI_Items[possStaffs[j]].InvSlot := CoordsToItem(x, y); // Set tool's inventory slot

SetLength(Result, (Length(Result) + 1));
Result[High(Result)] := possStaffs[j];
end else
Inc(t);

// If all staffs are found, it will break, otherwise check the other gametab
if (t <= 0) then
Break;
end;

MSI_CloseHeader('MSI_FindStaffs: '+ToStr(Result));
end;

function MSI_LeastRunesStaffs(): TIntegerArray;
var
a, i, j, spellMode, spellIndex: Integer;
theStaffs, runes, staffsFound: TIntegerArray;
begin
staffsFound := MSI_FindStaffs();
runes := [ RUNE_AIR, RUNE_EARTH, RUNE_FIRE, RUNE_WATER ];
theStaffs := [ STAFF_AIR, STAFF_EARTH, STAFF_FIRE, STAFF_WATER ];

if (Length(staffsFound) <= 0) then
begin
MSI_SubDebug('MSI_LeastRunesStaffs: No staffs were found');
Exit;
end;

with MSI_Players[CurrentPlayer].Scripts[CurrentScript] do
begin
SetLength(Result, Length(Spells));

for i := 0 to High(Spells) do
begin
with MSI_Spells[Spells[i]] do
begin
QuickSort(RequiredRunes);
InvertTIA(RequiredRunes);

for j := 0 to High(RequiredRunes) do
begin
if (RequiredRunes[j] <= 0) then
Break;

if (InIntArrayEx(runes, a, RequiredRunes[j])) then
if (InIntArray(staffsFound, theStaffs[a])) then // If the staff was found on the player
begin
Result[i] := theStaffs[a];
MSI_SubDebug('Using '+MSI_Items[Result[i]].Name+' for '+Capitalize(MSI_SpellToStr(Spells[i])));
Staffs[i] := Result[i]; // Set script attribute to the staff chosen
Break;
end else
Continue
else
Continue;
end;
end;
end;
end;
end;

{******************************************************************************}
{ function MSI_ChooseStaffs(): TIntegerArray; }
{ By: Coh3n }
{ Date: 14 November 2010 }
{ Description: Returns the staffs chosen for each spell for the current player }
{ Also sets the scripts 'Staffs' attributes }
{******************************************************************************}
function MSI_ChooseStaffs(): TIntegerArray;
begin
with MSI_Players[CurrentPlayer].Scripts[CurrentScript] do
begin
// Exit if the user has specified the staffs to use
if (Staffs[Low(Staffs)] > 0) then
begin
MSI_SubDebug('Staff types already set in DeclarePlayers');
Result := Staffs;
Exit;
end;

SetLength(Result, Length(Spells));

case StaffType of
MostCasts:
begin
end;

Cheapest:
begin
end;

else // By default, uses the staff that uses the most runes
Result := MSI_LeastRunesStaffs();
end;
end;
end;

{******************************************************************************}
{ function MSI_GetStaffRunes(): TIntegerArray; }
{ By: Coh3n }
{ Date: 14 November 2010 }
{ Description: Returns the runes associated with the staffs found }
{******************************************************************************}
function MSI_GetStaffRunes(): TIntegerArray;
var
i, t: Integer;
runeStaffs, possStaffs, chosenStaffs: TIntegerArray;
begin
runeStaffs := [ RUNE_AIR, RUNE_EARTH, RUNE_FIRE, RUNE_WATER ];
possStaffs := [ STAFF_AIR, STAFF_EARTH, STAFF_FIRE, STAFF_WATER ];
chosenStaffs := MSI_ChooseStaffs();

for i := 0 to High(chosenStaffs) do
if (InIntArrayEx(possStaffs, t, chosenStaffs[i])) then
begin
SetLength(Result, Length(Result) + 1);
Result[High(Result)] := runeStaffs[t];
MSI_SubDebug(MSI_Items[runeStaffs[t]+MSI_RUNE_AIR].Name+' not needed, we have a staff');
end;
end;

{******************************************************************************}
{ function MSI_GetRunesFound: TIntegerArray; }
{ By: Coh3n }
{ Date: 09 November 2010 }
{ Description: Returns the amount of each rune found in the inventory }
{******************************************************************************}
function MSI_GetRunesFound: TIntegerArray;
var
i: Integer;
exceptions: TIntegerArray;
begin
SetLength(Result, (RUNE_COUNT - 1));
exceptions := MSI_GetStaffRunes();

for i := 0 to High(Result) do
begin
if (InIntArray(exceptions, i)) then
begin
Result[i] := MAX_RUNES;
Continue;
end;

Result[i] := ItemAmount('inv', 'dtm', MSI_Items[i + MSI_RUNE_AIR].DTM, []);

if (Result[i] <= 0) then // Don't debug the ones that aren't found
Continue;

MSI_SubDebug(Capitalize(MSI_Items[i + MSI_RUNE_AIR].Name)+' found: '+IntToStr(Result[i]));
end;
end;

{******************************************************************************}
{ function MSI_CalculateCasts: TIntegerArray; }
{ By: nickrules & Coh3n }
{ Date: 09 November 2010 }
{ Description: Returns the number of casts per spell the player can cast }
{******************************************************************************}
function MSI_CalculateCasts: TIntegerArray;
var
i, j, lo, spellMode, spellIndex: Integer;
runeAmounts, casts: TIntegerArray;
begin
MSI_AddHeader('MSI_CalculateCasts');

with MSI_Players[CurrentPlayer].Scripts[CurrentScript] do
begin
SetLength(Result, Length(Spells));
runeAmounts := MSI_GetRunesFound(); // All the runes found in the inventory

for i := 0 to High(Spells) do
begin
with MSI_Spells[Spells[i]] do
begin
SetLength(casts, Length(RequiredRunes));

// Debug number of casts per individual rune type
for j := 0 to High(RequiredRunes) do
begin
if (runeAmounts[RequiredRunes[j]] >= MAX_RUNES) then
begin
casts[j] := runeAmounts[RequiredRunes[j]];
Continue;
end;

casts[j] := Floor(runeAmounts[RequiredRunes[j]] div RequiredRuneAmount[j]); // Rounds down
MSI_Debug('Enough '+MSI_Items[RequiredRunes[j]+MSI_RUNE_AIR].Name+
's to cast '+ IntToStr(casts[j])+' '+Capitalize(Name)+'s');
end;

// Set the result to the maximum number of casts depending on the runes found
for j := 0 to High(casts) do
begin
// Get the lowest number of calculated casts
if (j = 0) then
lo := casts[j]
else
if (casts[j] < lo) then
lo := casts[j];

if (j = High(casts)) then
begin
Result[i] := lo;
MSI_Debug('Player can cast '+IntToStr(Result[i])+' '+Capitalize(Name)+'s');
end;
end;

// Decrease the amount of runes found because they've been 'used' for another spell
for j := 0 to High(RequiredRunes) do
begin
if (runeAmounts[RequiredRunes[j]] >= MAX_RUNES) then
Continue;

DecEx(runeAmounts[RequiredRunes[j]], (Result[i] * RequiredRuneAmount[j]));
MSI_Debug(MSI_Items[RequiredRunes[j]+MSI_RUNE_AIR].Name+'s left: '+IntToStr(runeAmounts[RequiredRunes[j]]));
end;
end;
end;
end;

MSI_CloseHeader('MSI_CalculateCasts: ' + ToStr(Result));
end;

{******************************************************************************}
{ function MSI_ItemToSpellSlot(Spell: Integer): boolean; }
{ By: Nickrules }
{ Date: 5 August 2010 }
{ Description: Moves the item to the most ideal slot }
{******************************************************************************}
function MSI_ItemToSpellSlot(Spell, ItemIndex: Integer): boolean;
begin
with MSI_Players[CurrentPlayer].Scripts[CurrentScript] do
case Spell of
SPELL_ALCH_LOW:
result := MSI_DragItem(AlchSlots[ItemIndex], SLOT_ALCH_LOW);

SPELL_ALCH_HIGH:
result := MSI_DragItem(AlchSlots[ItemIndex], SLOT_ALCH_HIGH);

else begin
MSI_Debug('MSI_ItemToSpellSlot: Item manipulation not necessary...');
Result := True;
end;
end;
end;

{******************************************************************************}
{ function MSI_SetupMagic(): Boolean; }
{ By: Coh3n & nickrules }
{ Date: 08 November 2010 }
{ Description: Sets the player up for autoing the magic skill }
{******************************************************************************}
function MSI_SetupMagic(): Boolean;
var
i: Integer;
begin
MSI_AddHeader('MSI_SetupMagic');

with MSI_Players[CurrentPlayer].Scripts[CurrentScript] do
begin
CurrentSpell := 0;
SetupSpells; // Set all the spell information (SRL's magic.scar)
SetLength(Staffs, Length(Spells));

MaxCasts := MSI_CalculateCasts();

// If can't cast spell, delete it from the necessary arrays
for i := 0 to High(MaxCasts) do
if (MaxCasts[i] <= 0) then
begin
DeleteValueInIntArray(MaxCasts, i);
DeleteValueInIntArray(Spells, i);
end;

// Equip the staff for the CurrentSpell
if (MSI_Items[Staffs[CurrentSpell]].InvSlot > 0) then
begin
MSI_Debug('Equipping '+Capitalize(MSI_Items[Staffs[CurrentSpell]].Name));
InvMouse(MSI_Items[Staffs[CurrentSpell]].InvSlot, 1); // 1 = LeftClick
Wait(RandomRange(200, 500));
end;

Result := ((Length(MaxCasts) > 0) and (Length(Spells) > 0));
end;

MSI_CloseHeader('MSI_SetupMagic: ' + BoolToStr(Result));
end;

{******************************************************************************}
{ function MSI_Cast(spell, which: integer; isObject: boolean): boolean; }
{ By: Nickrules & Coh3n & NCDS }
{ Date: 22 August 2010 }
{ Description: Casts 'spell' on item/object 'which' }
{******************************************************************************}
function MSI_Cast(spell, which: integer; isObject: boolean): boolean;
var
x, y, slot, i: Integer;
s, spellName: string;
spellInfo: TSpell;
didCast: boolean;
iBox: TBox;
begin
spellName := MSI_SpellToStr(spell);
spellInfo := GetSpellInfo(spellName);

if (not Cast(spellName, spellInfo.autoCast)) then
begin
MSI_SubDebug('Failed to cast spell: ' + Capitalize(spellName));
exit;
end;

if (isObject) then
begin
didCast := MSI_FindObject(which, ClickLeft);
s := MSI_Objects[which].Name;
end else
begin
if ((spell = SPELL_ALCH_LOW) or (spell = SPELL_ALCH_HIGH)) then
begin
GetMousePos(x, y);
slot := CoordsToItem(x, y);
if slot = 0 then
case spell of
SPELL_ALCH_LOW : slot := SLOT_ALCH_LOW;

SPELL_ALCH_HIGH : slot := SLOT_ALCH_HIGH;
end;

if (ExistsItem(slot)) then
begin
if (not (WaitUpText('3', 120))) then
begin
iBox := InvBox(slot);
for i := 0 to 2 do
begin
MMouse(RandomRange(iBox.x1 + 5, iBox.x2 - 5), RandomRange(iBox.y1 + 5, iBox.y2 - 5), 2, 2);
if WaitUpText('3', 120) then
Break;
if i = 2 then
Exit;
end;
end;
GetMousePos(x, y);
MSI_SubDebug('Successfully cast ' + Capitalize(spellName));
Mouse(x, y, 0, 0, True);
Result := True;
Exit;
end;

MSI_SubDebug('Failed to cast ' + Capitalize(spellName));
Exit;
end;

didCast := MSI_ClickItem(which, ['ast']);
s := MSI_Items[which].Name;
end;

if (didCast) then
begin
Result := True;
MSI_SubDebug('Cast ' + Capitalize(spellName) + ' on ' + s);
end else
MSI_SubDebug('Failed to cast ' + Capitalize(spellName) + ' on ' + s);
end;

{******************************************************************************}
{ function MSI_IsAlching(WaitTime: Integer): Boolean; }
{ By: Coh3n }
{ Date: 24 November 2010 }
{ Description: Returns true if the player is alching; should eventually be }
{ written to work with several different animations }
{******************************************************************************}
function MSI_IsAlching(WaitTime: Integer): Boolean;
var
t: Integer;
b: TBox;
begin
t := (GetSystemTime + WaitTime);

b := IntToBox(MSCX - 30, MSCY - 40, MSCX + 30, MSCY + 15);
SMART_DrawBoxEx(True, b, clRed);

while (GetSystemTime < t) do
begin
if (PixelShift(b, 200) > ANIM_COL_ALCH) then
begin
MSI_SubDebug('We are alching!');
Result := True;
if GetCurrentTab = tab_Magic then
Exit;
end;

Wait(RandomRange(10, 30));
end;

Result := False;
end;

{******************************************************************************}
{ function MSI_Alch(Spell: Integer): Boolean; }
{ By: Coh3n }
{ Date: 24 November 2010 }
{ Description: Alchs until done all it can do, times out or ran out of alch }
{ items; should eventually be written to work with all spells }
{******************************************************************************}
function MSI_Alch(Spell: Integer): Boolean;
var
a, i, t, idealSlot: Integer;
spellName: string;
spellInfo: TSpell;
begin
MSI_AddHeader('MSI_Alch');

spellName := MSI_SpellToStr(Spell);
spellInfo := GetSpellInfo(spellName);

t := GetSystemTime + (60000 * 3); // Will stop if doesn't cast in 5 minutes

case Spell of
SPELL_ALCH_LOW: idealSlot := SLOT_ALCH_LOW;
SPELL_ALCH_HIGH: idealSlot := SLOT_ALCH_HIGH;
end;

with MSI_Players[CurrentPlayer].Scripts[CurrentScript] do
begin
if (Length(AlchSlots) <= 0) then
begin
MSI_Debug('No AlchSlots specified in DeclarePlayers, please specify which inventory slots your items are in.');
MSI_CloseHeader('MSI_Alch: ' + BoolToStr(Result));
Exit;
end;

for i := 0 to High(AlchSlots) do
begin
if (ExistsItem(AlchSlots[i])) and (AlchSlots[i] <> idealSlot) then
begin
DragItem(AlchSlots[i], idealSlot); // Drag alch item to ideal inventory slot
Wait(RandomRange(100, 300));
end else
if (not ExistsItem(idealSlot)) then
begin
MSI_Debug('Item doesn''t exist in AlchSlot['+IntToStr(i)+'] or idealSlot');
Continue;
end;

repeat
if (not MSI_Cast(Spell, 0, False)) then
begin
if (not (LoggedIn)) then
Exit;
MSI_FindRandoms;
if ((not ExistsItem(idealSlot))) then
if (i = High(AlchSlots)) then
begin
MSI_Debug('Ran out of items to alch!');
MSI_Players[CurrentPlayer].ReportInfo.FalseReason := 'Ran out of items to alch';
Exit;
end else
Break;
end else begin
// Adds report information (exp and casts)
MSI_AddToProggy(PROG_ADD_CASTS, -1, -1, -1);
MSI_AddToProggy(PROG_ADD_EXP, -1, -1, Round(spellInfo.Exp));
Inc(MSI_Players[CurrentPlayer].ReportInfo.Casts[CurrentScript][CurrentSpell]);

case MSI_Players[CurrentPlayer].Scripts[CurrentScript].Spells[CurrentSpell] of
SPELL_ALCH_LOW:
stats_IncVariable('Low Level Alchs', 1);

SPELL_ALCH_HIGH:
stats_IncVariable('High Level Alchs', 1);
end;

t := GetSystemTime + (60000 * 5);
end;

if IsChatBoxTextBetween(ALCH_COIN_MESSAGE, 8, 8, 6) then
begin
MSI_Debug('Alching Coins!');
Exit;
end;

a := ((GetSystemTime + 2000) + Random(1500));
while (MSI_IsAlching(2000) and (GetSystemTime < a)) do // Wait while alching
Wait(RandomRange(10, 20));

// Result is true if we've cast the maximum
if (MSI_Players[CurrentPlayer].ReportInfo.Casts[CurrentSpell][CurrentScript] >= MaxCasts[CurrentSpell]) then
begin
MSI_Debug('Cast maximum number of '+Capitalize(MSI_SpellToStr(Spell)));
MSI_CloseHeader('MSI_Alch: ' + BoolToStr(Result));
MSI_Players[CurrentPlayer].ReportInfo.FalseReason := 'Cast maximum number of '+Capitalize(MSI_SpellToStr(Spell));
Exit;
end;

if ((MSI_Players[CurrentPlayer].ReportInfo.Casts[CurrentScript][CurrentSpell] mod CASTS_BEFORE_REPORT) = 0) then
begin
Result := True;
MSI_CloseHeader('MSI_Alch: ' + BoolToStr(Result));
Exit;
end;

until(GetSystemTime > t);
end;
end;

MSI_CloseHeader('MSI_Alch: ' + BoolToStr(Result));
end;

{******************************************************************************}
{ function MSI_DoMagic(): Boolean; }
{ By: Coh3n }
{ Date: 24 November 2010 }
{ Description: Casts the maximum spells for each spell in DeclarePlayers }
{******************************************************************************}
function MSI_DoMagic(): Boolean;
begin
with MSI_Players[CurrentPlayer].Scripts[CurrentScript] do
case Spells[CurrentSpell] of
SPELL_ALCH_HIGH, SPELL_ALCH_LOW:
Result := MSI_Alch(Spells[CurrentSpell]);

else
MSI_SubDebug('Invalid spell in DoMagic');
end;
end;

I was thinking about something like this for casting:

// Returns true when the spell is clicked
// Maybe check for the white outline after it's clicked?
function MSI_ClickSpell(Spell: Integer): Boolean;
begin
end;

// Returns true when the spell was cast on an item
function MSI_CastItem(Spell: Integer): Boolean;
begin
end;

// Returns true when the spell was cast on an object (not really needed now since we just have alching)
function MSI_CastObject(Spell: Integer): Boolean;
begin
end;
The idea is to keep it as simple as possible. I also think MSI_LeastRunesStaff can be strunk down to one or two lines, I just haven't looked into it a lot yet, but I'll figure it out.

I want to change IsAlching to IsAnimating and work with any animations. I think it would be a good time to think about this also.

Anything I haven't considered please let me know, and if you can help out (even if it's a little bit) that would be great. :)

Thanks

E: I also don't like how I have the MAX_RUNE constant. I need to figure out a way to get rid of it. It's used when setting the rune amounts for a staff.

Coh3n

2011-02-08 01:39:38

This is now done, and the alcher is working nicely.

- Added "if (not LoggedIn) then Exit" to every function that needed it. Hopefully this will stop the opening of the recovery tabs.
- Added Animating.simba and animations for high and low level alching.
- Basically rewrote Magic.simba; alching works really well now (IMO)
- Fixed a few minor bugs here and there (I don't remember all of them)
- Did documentation for Animating.simba and Magic.simba
Documentation can be viewed here.

Wizzup?

2011-02-10 17:02:31

The link doesn't link to the page directly. :)