SystemShock
New Member
- Joined
- Aug 18, 2012
- Messages
- 87
- Reaction score
- 4
Simple (Sorc+Witchcraft) grinder + deathwalk
As the title says this is a very simplistic grinder for any set up that includes sorcery and witchcraft that also features a deathwalk(Which is broken at the moment).
The rotation is based around the idea that I want to be able to run constantly, and so it isn't mana intensive(Once mana food, and potions become more available I'll be adding a more mana intensive version for faster killing)
Buffs -
Magic Circle
Insulating Lense
Purge
Rotation -
Whenever magic circle is off cooldown - cast it
Whenever insulating lense is off cooldown - cast it
When below 75% health && Enervate and Earthern Grip are off cooldown - cast Enervate then Earthern Grip
When below 90% mana && Enervate is off - cooldown cast Enervate
when none of the above, cast fire bolt
We also use play dead to drop agro if we're low health, and as a regen ability between kills
so needed spells -
Magic Circle
Insulating Lense
Purge
Enervate
ArcheAge Builder - Arche-Base
arc lightning, chain lightning and meteor aren't used in the rotation but are simply what I have in order to unlock passives
Issues - It's handling of play dead is poor.
So due to current GPS constraints it's impossible, or atleast is as far as I'm aware to make GPS paths on the fly, so you'll have to make a path from the closest nui, to your farming zone yourself, a guide on how to do this can be found in the gps topic -> https://www.thebuddyforum.com/archebuddy-forum/archebuddy-plugins/177764-gps-system-gps-editor.html
Generate a path named, TheGrinder.db3, and put that into the folder with the script.
Installation is standard,
1) Create a folder in plugins named SystemGutted
2) Compile the script and place it in the folder
3) Generate your GPS path, name it TheGrinder.db3 and put it into the folder
4) Run the script
GuttedGrinder.cs
main.cs
This plugin is open source so I'll never charge for it, instead how about you buy me a coffee?
As the title says this is a very simplistic grinder for any set up that includes sorcery and witchcraft that also features a deathwalk(Which is broken at the moment).
The rotation is based around the idea that I want to be able to run constantly, and so it isn't mana intensive(Once mana food, and potions become more available I'll be adding a more mana intensive version for faster killing)
Buffs -
Magic Circle
Insulating Lense
Purge
Rotation -
Whenever magic circle is off cooldown - cast it
Whenever insulating lense is off cooldown - cast it
When below 75% health && Enervate and Earthern Grip are off cooldown - cast Enervate then Earthern Grip
When below 90% mana && Enervate is off - cooldown cast Enervate
when none of the above, cast fire bolt
We also use play dead to drop agro if we're low health, and as a regen ability between kills
so needed spells -
Magic Circle
Insulating Lense
Purge
Enervate
ArcheAge Builder - Arche-Base
arc lightning, chain lightning and meteor aren't used in the rotation but are simply what I have in order to unlock passives
Issues - It's handling of play dead is poor.
So due to current GPS constraints it's impossible, or atleast is as far as I'm aware to make GPS paths on the fly, so you'll have to make a path from the closest nui, to your farming zone yourself, a guide on how to do this can be found in the gps topic -> https://www.thebuddyforum.com/archebuddy-forum/archebuddy-plugins/177764-gps-system-gps-editor.html
Generate a path named, TheGrinder.db3, and put that into the folder with the script.
Installation is standard,
1) Create a folder in plugins named SystemGutted
2) Compile the script and place it in the folder
3) Generate your GPS path, name it TheGrinder.db3 and put it into the folder
4) Run the script
GuttedGrinder.cs
Code:
using System;
using System.Drawing;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using ArcheBuddy.Bot.Classes;
namespace GuttedSpace
{
public class GuttedGrinder : Core
{
public int deathcount;
internal Main mainForm { get; set; }
private Thread formThread;
private Thread paintThread;
public int mobsKilled = 0;
public long coinPursesStart = 0;
public long coinPursesCurrent = 0;
Stopwatch stopwatch = new Stopwatch();
long runTimeMilli;
private volatile bool _shouldStop;
public static string GetPluginAuthor ()
{
return "SystemShock";
}
public static string GetPluginVersion ()
{
return "Evaluation";
}
public static string GetPluginDescription ()
{
return "TheGrinder is a mob grinder developed by SystemShock, more information for about the project and proper installation guidelines can be found on the forum";
}
public void gpsPreMove (GpsPoint point)
{
/*
*
*We do nothing other than debugging in here at the moment, in the future we'll add combat checks so it can kill anything hostile it meats on the path
*
*/
Log("Moving");
}
public Creature GetBestNearestMob (Zone zone)
{
/*
*
*Simple method stole from Out's Example Grinder with a few minor tweaks
*Locates a mob, checks to make sure it's within our zone and that it either isn't tagged, or is our tag
*And then declares it as the nearest valid mob for the rest of the script
*
*/
Creature mob = null;
double dist = 999999;//How is distance treated? Nobody knows, oh great Out, are you looking within 999999 meters? or 9999999 pixels? I'd love to know... Hear me oh Great One
foreach(var obj in getCreatures())
{
if(obj.type == BotTypes.Npc && isAttackable(obj) && (obj.firstHitter == null || obj.firstHitter == me) && isAlive(obj) && me.dist(obj) < dist && zone.ObjInZone(obj)
&& (hpp(obj) == 100 || obj.aggroTarget == me))
{
mob = obj;
dist = me.dist(obj);
}
}
return mob;
}
public void CancelAttacksOnAnothersMobs ()
{
/*
*
*Again stolen from Out's example grinder
*Dude wheres my car, because this one is someone elses
*
*/
while(true)
{
if(me.isCasting && me.target != null && me.target.firstHitter != null && me.target.firstHitter != me)
CancelSkill();
Thread.Sleep(100);
}
}
public void UseSkillAndWait (string skillName, bool selfTarget = false)
{
/*
*
*I'm noticing a pattern here, another method stolen from Out
*( seriously why are these not just part of the .dll and allow us to override them ¯\_(ツ)_/¯ )
*
*/
while(me.isCasting || me.isGlobalCooldown)
Thread.Sleep(50);
if(!UseSkill(skillName, true, selfTarget))
{
if(me.target != null && GetLastError() == LastError.NoLineOfSight)
{
if(dist(me.target) <= 5)
ComeTo(me.target, 2);
else if(dist(me.target) <= 10)
ComeTo(me.target, 3);
else if(dist(me.target) < 20)
ComeTo(me.target, 8);
else
ComeTo(me.target, 8);
}
}
while(me.isCasting || me.isGlobalCooldown)
Thread.Sleep(50);
}
private void RunForm ()
{
/*
*
*Lets open the paint lads
*
*/
try
{
Application.Run(mainForm);
}
catch(Exception error)
{
Log(error.ToString());
try
{
if(mainForm != null)
{
mainForm.Invoke(new Action(() => mainForm.Close()));
mainForm.Invoke(new Action(() => mainForm.Dispose()));
}
}
catch
{ }
}
}
public void deathWalk ()
{
/*
*
*Pretty simple method, just reads your .db3 path file and walks it to the end-point which should be named "spawn"
*
*/
Gps gps = new Gps(this);
gps.LoadDataBase(Application.StartupPath + "\\plugins\\SystemGrinder\\TheGrinderPath.db3");
gps.onGpsPreMove += gpsPreMove;
gps.GpsMove("spawn");
}
public void checkBuffs ()
{
if(buffTime("Magic Defense Boost") == 0 && skillCooldown("Purge") == 0)
UseSkillAndWait("Purge", true);
if(skillCooldown("Insulating Lens") == 0)
UseSkillAndWait("Insulating Lens", true);
if(buffTime("Suspected User") > 0){
Log("SOME FUCKER JUST REPORTED US, I'M GOING TO RUN AWAY NOW");
UseSkill("Recall");
Thread.Sleep(30000);
StopPlugin("SystemGutted\\SystemGutted.dll");
}
}
public void updatePaint ()
{
/*
*
*Some simple math, timers and set methods to get the values for, and update the paint.
*
*/
while(!_shouldStop)
{
if((stopwatch.ElapsedMilliseconds % 1000) == 0)
{
runTimeMilli = (stopwatch.ElapsedMilliseconds / 1000);
mainForm.setRunTime(runTimeMilli);
mainForm.setMobsKilled(mobsKilled);
mainForm.setPursesLooted(coinPursesCurrent - coinPursesStart);
mainForm.setHourly((3600 / runTimeMilli) * (coinPursesCurrent - coinPursesStart));
}
}
}
public void requestStop ()
{
_shouldStop = true;
}
public void prepareForCombat ()
{
/*
*
*Doing some last minute things before combat, which in a daggerspells case is..... casting magic circle
*
*/
while(dist(me.target) >= 21)
ComeTo(me.target, 17);
if(skillCooldown("Magic Circle") == 0 && dist(me.target) <= 20)
{
UseSkillAndWait("Magic Circle");
Thread.Sleep(100);
}
}
public void PluginRun ()
{
Log("Welcome to theGRINDER");
/*
*
*Initializing variables for the paint
*
*/
stopwatch.Start();
coinPursesStart = itemCount(29207);
coinPursesCurrent = itemCount(29207);
/*
*
*Drawing the paint
*
*/
mainForm = new Main();
formThread = new Thread(RunForm);
formThread.SetApartmentState(ApartmentState.STA);
formThread.Start();
/*
*
*Update the paint
*
*/
paintThread = new Thread(updatePaint);
paintThread.SetApartmentState(ApartmentState.STA);
paintThread.Start();
/*
*
*Make a new task to avoid attacking tagged mobs
*And make a zone for us to look for mobs in
*
*/
new Task(() => { CancelAttacksOnAnothersMobs(); }).Start();
RoundZone zone = new RoundZone(me.X, me.Y, 100);
/*
*
*And now for something completely different
*
*/
while(true)
{
// updatePaint();
if(me.isAlive())
{
/*
*
*Does my hair look okay?
*
*/
checkBuffs();
Creature bestMob = null;
/*
*
*Well we're alive.... but are we alive 'enough'?
*
*/
if((mpp() > 40 && hpp() > 70) || getAggroMobs().Count > 0)
{
bestMob = GetBestNearestMob(zone);
}
/*
*
*Just because we've found the bestmob doesn't mean you should marry it
*
*/
if(bestMob != null)
{
try
{
while(bestMob != null && isAlive(bestMob) && isExists(bestMob) && isAlive())
{
/*
*
*Hey here is an idea, how about we don't help random people kill mobs
*
*/
if(bestMob.aggroTarget != me && bestMob.firstHitter != null && bestMob.firstHitter != me)
{
bestMob = null;
break;
}
/*
*
*Why is this random mob attacking me?
*No idea but I guess we should kill it
*
*/
if(bestMob.firstHitter == null && getAggroMobs().Count > 0 && bestMob != GetBestNearestMob(zone))
bestMob = GetBestNearestMob(zone);
/*
*
*If it's the best mob you should problably target it
*
*/
if(me.target != bestMob)
SetTarget(bestMob);
/*
*
*It helps if you look at it Dave
*
*/
if(angle(bestMob, me) > 45 && angle(bestMob, me) < 315)
TurnDirectly(bestMob);
/*
*
*AND MY AXE
*
*/
prepareForCombat();
/*
*
*If below 33% Hp, then feign death
*
*/
if(hpp() < 33 && skillCooldown("Play Dead") == 0)
{
Thread.Sleep(500);
CancelTarget();
UseSkill("Play Dead");
Thread.Sleep(15000);
}
/*
*
*If below 75% hp, Enervate is off cooldown, Earthern Grip is off cooldown - then Healing Combo
*
*/
if((hpp() < 75) && (skillCooldown("Enervate") == 0) && (skillCooldown("Earthen Grip") == 0))
{
Thread.Sleep(1000);
UseSkillAndWait("Enervate");
Thread.Sleep(250);
UseSkillAndWait("Earthen Grip");
Thread.Sleep(50);
}
/*
*
*Well we've got enough health I guess we should try make some mana back
*
*/
if((mpp() < 75) && (skillCooldown("Enervate") == 0))
UseSkillAndWait("Enervate");
/*
*
*Well now I guess I'll just throw fucking fireballs
*
*/
for(int i = 0; i < 2; i++)
UseSkillAndWait("Flamebolt");
/*
*
*And.... sleep
*
*/
Thread.Sleep(10);
}
/*
*
*Is it dead? Wow I managed to kill something
*
*/
if(bestMob != null && !isAlive(bestMob) && isExists(bestMob) && bestMob.type == BotTypes.Npc)
{
mobsKilled++;
}
/*
*
*Its DEAD and it has loot? SHWWEEETTT
*
*/
while(bestMob != null && !isAlive(bestMob) && isExists(bestMob) && bestMob.type == BotTypes.Npc && ((Npc)bestMob).dropAvailable && isAlive())
{
if(me.dist(bestMob) > 3)
ComeTo(bestMob, 1);
PickupAllDrop(bestMob);
if(itemCount(29207) > (coinPursesCurrent))
{
coinPursesCurrent++;
}
}
}
catch { }
}
}
else
{
/*
*
*Well if I'm not alive I should problably revive and run back
*
*/
while(!me.isAlive())
{
ResToRespoint();
}
Random rnd = new Random();
Log("Oh dear it appears we died");
Thread.Sleep(rnd.Next(60000, 180000));
Log("Well we can't hang around here all day, lets get moving shall we?");
MoveForward(true);
Thread.Sleep(1000);
MoveForward(false);
Gps gps = new Gps(this);
gps.LoadDataBase(Application.StartupPath + "\\plugins\\SystemGutted\\TheGrinder.db3");
gps.GpsMove("spawn");
}
Thread.Sleep(10);
}
}
public void PluginStop ()
{
try
{
if(mainForm != null)
{
mainForm.Invoke(new Action(() => mainForm.Close()));
mainForm.Invoke(new Action(() => mainForm.Dispose()));
}
requestStop();
}
catch
{ }
Log("Thank you for using TheGrinder version " + GetPluginVersion() + " by " + GetPluginAuthor());
}
}
}
main.cs
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace GuttedSpace
{
public partial class Main : Form
{
public Main()
{
InitializeComponent();
}
public void setRunTime(long setter){
this.runTimeEdit.Text = setter.ToString() + " Seconds";
}
public void setMobsKilled(int setter){
this.mobsKilledEdit.Text = setter.ToString();
}
public void setPursesLooted(long setter){
this.lootedEdit.Text = setter.ToString();
}
public void setHourly(long setter){
this.perHourEdit.Text = setter.ToString();
}
private void InitializeComponent()
{
this.label1 = new System.Windows.Forms.Label();
this.label2 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label4 = new System.Windows.Forms.Label();
this.runTimeEdit = new System.Windows.Forms.Label();
this.lootedEdit = new System.Windows.Forms.Label();
this.mobsKilledEdit = new System.Windows.Forms.Label();
this.perHourEdit = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(12, 36);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(59, 13);
this.label1.TabIndex = 0;
this.label1.Text = "Run Time :";
//
// label2
//
this.label2.AutoSize = true;
this.label2.Location = new System.Drawing.Point(13, 59);
this.label2.Name = "label2";
this.label2.Size = new System.Drawing.Size(67, 13);
this.label2.TabIndex = 1;
this.label2.Text = "Mobs Killed :";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(13, 82);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(100, 13);
this.label3.TabIndex = 2;
this.label3.Text = "Coin purses looted :";
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(13, 106);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(107, 13);
this.label4.TabIndex = 3;
this.label4.Text = "Coinpurses per hour :";
//
// runeTimeEdit
//
this.runTimeEdit.AutoSize = true;
this.runTimeEdit.Location = new System.Drawing.Point(126, 36);
this.runTimeEdit.Name = "runeTimeEdit";
this.runTimeEdit.Size = new System.Drawing.Size(0, 13);
this.runTimeEdit.TabIndex = 4;
//
// lootedEdit
//
this.lootedEdit.AutoSize = true;
this.lootedEdit.Location = new System.Drawing.Point(126, 82);
this.lootedEdit.Name = "lootedEdit";
this.lootedEdit.Size = new System.Drawing.Size(0, 13);
this.lootedEdit.TabIndex = 5;
//
// mobsKilledEdit
//
this.mobsKilledEdit.AutoSize = true;
this.mobsKilledEdit.Location = new System.Drawing.Point(126, 59);
this.mobsKilledEdit.Name = "mobsKilledEdit";
this.mobsKilledEdit.Size = new System.Drawing.Size(0, 13);
this.mobsKilledEdit.TabIndex = 6;
//
// perHourEdit
//
this.perHourEdit.AutoSize = true;
this.perHourEdit.Location = new System.Drawing.Point(126, 106);
this.perHourEdit.Name = "perHourEdit";
this.perHourEdit.Size = new System.Drawing.Size(0, 13);
this.perHourEdit.TabIndex = 7;
//
// Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(300, 173);
this.Controls.Add(this.perHourEdit);
this.Controls.Add(this.mobsKilledEdit);
this.Controls.Add(this.lootedEdit);
this.Controls.Add(this.runTimeEdit);
this.Controls.Add(this.label4);
this.Controls.Add(this.label3);
this.Controls.Add(this.label2);
this.Controls.Add(this.label1);
this.Name = "Main";
this.Text = "TheGrinder";
this.ResumeLayout(false);
this.PerformLayout();
}
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label runTimeEdit;
private System.Windows.Forms.Label lootedEdit;
private System.Windows.Forms.Label mobsKilledEdit;
private System.Windows.Forms.Label perHourEdit;
}
}
This plugin is open source so I'll never charge for it, instead how about you buy me a coffee?

Last edited: