Groovy maid scripts

Forum for alternative clients, mods & discussions on the same.

Moderator: Phades

Re: Groovy maid scripts

Postby mvgulik » Sun May 31, 2015 7:37 am

Anemone client.
Code: Select all
// general session break detection support.
gmf_ind = MaidFrame.index;
gmf_str = MaidFrame.getSessionList()[gmf_ind].toString();
boolean session_exit() {
   return (MaidFrame.getSessionList()[gmf_ind].toString() != gmf_str);
}// bailout check => "if (session_exit()) {return}"
[v0.2]
Cleaned up version from this post.
index
Last edited by mvgulik on Wed Jul 15, 2015 9:40 am, edited 1 time in total.
mvgulik
 
Posts: 3742
Joined: Fri May 21, 2010 2:29 am

Re: Groovy maid scripts

Postby mvgulik » Tue Jun 23, 2015 1:32 pm

Just for fun and giggles.
(default/minimum client size advised, and a bunch of open seedbags of course.)

Anemone client.
Code: Select all
maid.doSay(">> Seedbags_Move_Test()");
maid.doSay("");

startSound();
Seedbags_Move_Test();
return;//alt quit.

def startSound() {
   def Resource resSound = Resource.load("sfx/fail");
   Audio.play(resSound);
}

def Seedbags_Move_Test() {
   int step_time = 50;
   int steps = 10;
   
   windows = getOpenSeedbags();
   int win_count = windows.size();
   if (win_count < 2) return; // exit, nothing to do.
   Collections.shuffle(windows);
   
   def win_size = windows[0].sz;
   def ui_size = MaidFrame.innerSize;
   int max_x = ui_size.x / win_size.x;
   int max_y = ui_size.y / win_size.y;
   List loc_org = [];
   for (win in windows) {loc_org.add(new Coord(win.c))}
   List loc_des = [];
   int loop_count = 0;
   for (win in windows) {
      int x = loop_count%max_x;
      int y = loop_count/max_x;
      loc_des.add(new Coord(x*win_size.x, y*win_size.y));
      loop_count += 1;
   }
   for (i in 1..steps) {
      int win_counter = 0;
      for (win in windows) {
         diff = new Coord(0,0);
         diff.x = loc_des[win_counter].x - loc_org[win_counter].x;
         diff.y = loc_des[win_counter].y - loc_org[win_counter].y;
         new_pos = new Coord(0,0);
         new_pos.x = loc_org[win_counter].x + (diff.x/steps*i);
         new_pos.y = loc_org[win_counter].y + (diff.y/steps*i);
         win.c = new_pos;
         win_counter += 1;
      }
      Thread.sleep(step_time);
   }
}

List getOpenSeedbags() {
   List list = [];
   Widget root = UI.instance.root;
   for (Widget wdg = root.child; wdg != null; wdg = wdg.next) {
      if (wdg.getClass() == haven.Window && wdg.cap.text == "Seedbag") {
         list.add(wdg);
      }
   }
   return list;
}
[v0.1]: None optimized code.
index
Last edited by mvgulik on Wed Jul 15, 2015 9:41 am, edited 1 time in total.
mvgulik
 
Posts: 3742
Joined: Fri May 21, 2010 2:29 am

Re: Groovy maid scripts

Postby mvgulik » Mon Jul 13, 2015 11:50 am

getPlayerOrientation()

Anemone client.
Code: Select all
import haven.*;
maid.doLeftClick(cord_offset(maid.getCoord(), orientationToCoord(getPlayerOrientation()), 11))
return //alt quit.

def int getPlayerOrientation() {
   player_gob = maid.getPlayer()
   def l = player_gob.resnames()
   def m = [:]
   for (e in l) {
      r = e.find("\\d+\$")
      if (r==null) continue
      if (!m.containsKey(r)) m[r]=0
      m[r]+=1
   }
   di = m.max {it.value}.key
   return di.toInteger()
}

def Coord orientationToCoord(int di) {
   def Map oc = [0:[-1,-1], 1:[0,-1], 2:[1,-1], 3:[1,0], 4:[1,1], 5:[0,1], 6:[-1,1], 7:[-1,0]]
   return new Coord(oc[di][0], oc[di][1])
}
def Coord cord_offset(Coord cord1, Coord cord2, f=1) {
   return new Coord(cord1.x - (cord2.x * f), cord1.y - (cord2.y * f))
}
[v0.1]: working snippet.
index
mvgulik
 
Posts: 3742
Joined: Fri May 21, 2010 2:29 am

Re: Groovy maid scripts

Postby mvgulik » Wed Jul 15, 2015 9:47 am

getTileCenter()

Anemone client.
Code: Select all
import haven.*;
maid.doLeftClick(getTileCenter(maid.getCoord()))
return;//alt quit.

def Coord getTileCenter(Coord rc) {
   def tc = [(rc.x/11).toBigInteger(), (rc.y/11).toBigInteger()]
   if (tc[0]>0) tc[0]+=1
   if (tc[1]<0) tc[1]-=1
   tc = [tc[0]*11, tc[1]*11]
   tc = [tc[0]-5, tc[1]+5]
   return new Coord(tc[0], tc[1])
}
[v0.1]: working snippet.
Note: Same process also works for minimap's, or server sectors for that matter. Just plug in the right values.
Note2: This is not the same auto selected position when using certain actions like dig.

index
mvgulik
 
Posts: 3742
Joined: Fri May 21, 2010 2:29 am

Re: Groovy maid scripts

Postby mvgulik » Thu Aug 06, 2015 4:33 pm

"Walk around object" experiment.

Anemone client.
Code: Select all
//import java.util.* // default Groovy import.
//import java.lang.* // default Groovy import.
import haven.*

maid.doSay("")
maid.doSay("Walk around object experiment)")

startSound()
Map negMAP = load_ResNEG_data("scripts/ResNEG.dat")
test_case()
return

def void test_case() {
   // walk around some object(with known hitbox).
   
   // optionals
   def int range = 8
   def String name = "cart"
   def int steps = 8 // Pos:clockwise, Neg:anti-clockwise. FullCircle:8.
   def skip1st = true // false|true
   
   name = "trough"
   name = "raftpart"
   name = "plow"
   name = "cart"
   
   steps = 0
   steps = -8
   steps = -8-8
   
   
   
   def home = maid.getCoord()
   def targ_gob = maid.doAreaFind(range, name)
   if (!targ_gob)  {
      maid.doSay('No "'+name+'" Found!')
      warningSound()
      return
   }
   
   if(!moveAroundObject(targ_gob, steps, skip1st)) return
   
   // assuming character finished at general same side as home location.
   if (!move_checked(home)) return
}

// ---- MAIN STUFF ----

def boolean moveAroundObject(targ_gob, steps, skip1st=true){
   def targ_hit = getHitboxPoints(targ_gob)
   if (!targ_hit) {warningSound();return false}
   
   def player_gob = maid.getPlayer()
   def player_hit = getHitboxPoints(player_gob)
   if (!player_hit) {warningSound();return false}
   
   def hit_both = listMath(targ_hit, player_hit, {a,b -> a+b})
   
   def Map d = [W:0, N:1, E:2, S:3]
   def Map hb = [
      0:new Coord(-hit_both[d.E], -hit_both[d.S]),
      1:new Coord(             0, -hit_both[d.S]),
      2:new Coord(-hit_both[d.W], -hit_both[d.S]),
      3:new Coord(-hit_both[d.W],              0),
      4:new Coord(-hit_both[d.W], -hit_both[d.N]),
      5:new Coord(             0, -hit_both[d.N]),
      6:new Coord(-hit_both[d.E], -hit_both[d.N]),
      7:new Coord(-hit_both[d.E],              0),
   ]
   
   // ISSUE: when to close to the target, it could pick an angle that will not work as intended.
   // Case: picking diagonal angle when start location is inside ver/hor width of target.
   def double rad = getDirectionAngle(player_gob.c, targ_gob.c)
   def int di = radToOrientationId(rad)
   
   if (!skip1st && !steps) {
      if (!move_checked(cord_offset(targ_gob.c, hb[di], 1))) return false
   }
   
   // InCON: same steps can give different result for perpendicular or diagonal starting point.
   while (steps!=0) { // kinda unsave bailout.
      if (steps>0) {
         if (di%2 || steps==1) {di++;steps--}else{di+=2;steps-=2}
         if (di>7) di-=8
         if (steps<0) steps=0 // failsafe.
      }else{
         if (di%2 || steps==-1) {di--;steps++}else{di-=2;steps+=2}
         if (di<0) di+=8
         if (steps>0) steps=0 // failsafe.
      }
      if (!move_checked(cord_offset(targ_gob.c, hb[di], 1))) return false
   }
   
   return true
}

def double getDirectionAngle(cord1, cord2) {
   def delta = cord_offset(cord2, cord1)
   return Math.atan2(delta.y, delta.x)
}
def int radToOrientationId(double rad) {
   def tmp = rad/Math.PI * 4 + 1/2 + 3
   if (tmp < 0) tmp+=8
   return tmp
}
def Coord orientationIdToCoord(int di) {
   //def Map o1 = [0:'SE', 1:'S', 2:'SW', 3:'W', 4:'NW', 5:'N', 6:'NE', 7:'E']
   def Map o2 = [0:[-1,-1], 1:[0,-1], 2:[1,-1], 3:[1,0], 4:[1,1], 5:[0,1], 6:[-1,1], 7:[-1,0]]
   return new Coord(o2[di][0], o2[di][1])
}

def List getHitboxPoints(Gob targ_gob) {
   def Coord bc1, bc2
   def List neg_alt = null
   def Map map = file_base_data()
   
   for (e in map) {
      if (targ_gob.resname().contains(e.key.toLowerCase())) {
         neg_alt = e.value
         bc1 = new Coord(neg_alt[0], neg_alt[1])
         bc2 = new Coord(neg_alt[2], neg_alt[3])
         bc1 = MapView.s2m(bc1)
         bc2 = MapView.s2m(bc2)//.add(bc1.inv())
         break
      }
   }
   
   if (!neg_alt) {
      def neg = targ_gob.getneg()
      bc1 = neg.bc
      bc2 = neg.bs.add(bc1)
   }
   
   def List hitpoints = null
   if (bc1.x || bc1.y || bc2.x || bc2.y) {
      hitpoints = [bc1.x, bc1.y, bc2.x, bc2.y]
   }
   
   return hitpoints
}

// ---- GENERAL STUFF ----

def startSound() {
   def Resource resSound = Resource.load("sfx/fail")
   Audio.play(resSound)
   Thread.sleep(100)
}
def warningSound() {
   def Resource resSound = Resource.load("sfx/fail")
   Audio.play(resSound)
   Thread.sleep(150)
   Audio.play(resSound)
   Thread.sleep(100)
}

def Coord cord_offset(Coord cord1, Coord cord2, int f=1) {
   return new Coord(cord1.x - (cord2.x * f), cord1.y - (cord2.y * f))
}
static List listMath(List A, List B, Closure closure){
   def tmp = []
   A.eachWithIndex { item, i -> tmp << closure.call(A[i], B[i]) }
   return tmp
}// Quick 'copied and pasted' general list-math solution code.

def move_checked(Coord ct) {
   maid.doLeftClick(ct)
   maid.waitForMoveStop(5000, 100)
   if (maid.getCoord() != ct) {
         maid.doSay("\tPath Blocked ?")
         maid.doSay("\t\tct" +" == "+ ct)
         maid.doSay("\t\tmaid.getCoord()" +" == "+ maid.getCoord())
      maid.doLeftClick(ct)
      maid.waitForMoveStop(5000, 100)
      if (maid.getCoord() != ct) {
         maid.doSay("\tPath Blocked !")
         maid.doSay("\t\tct" +" == "+ ct)
         maid.doSay("\t\tmaid.getCoord()" +" == "+ maid.getCoord())
         warningSound()
         return false
      }
   }
   return true
}

def Map load_ResNEG_data(String filespec) {
   def Map map = null
   def file = new File(filespec)
   if (file.isFile()) {
      map = Eval.me(file.text)
   } else {
      map = file_base_data()
      file.text = map.inspect()
   }
   return map
}
def file_base_data() {
   Map map = [:]
   map["/boat/"] = [0,-24,0,28] // WNES:[-12,-12,14,14]
   map["/cart/"] = [0,-10,0,10] // WNES:[-5,-5,5,5]
   map["/plow/"] = [0,-6,0,6] // WNES:[-3,-3,3,3]
   map["/bed-sturdy"] = [-6,-13,4,18] // WNES:[-8,-5,10,8]
   map["/cclosed"] = [0,-6,6,5] // WNES:[-3,-3,4,1] // chest
   map["/copen"] = [0,-6,6,5] // WNES:[-3,-3,4,1] // chest
   map["/htable"] = [6,-7,-4,12] // WNES:[-2, -5, 5, 7]
   map["/ladder"] = [-6,-5,8,6] // WNES:[-4, -1, 5, 1]
   map["/trough"] = [-6,-11,16,20] // WNES:[-7,-4,14,6]
   map["/vclaim"] = [-16,-16,22,19] // WNES:[-12,-4,15,4]
   
   //map["/hare/"] = [0,0,0,2] // WNES:[..] // issue: is using other named res as base res.
   //map["/frog/"] = [0,0,0,2] // WNES:[..] // issue: is using other named res as base res.
   
   // general fix for none blocking items.
   map["/plants/"] = [0,0,0,0]
   map["/anthill-r"] = [0,0,0,0]
   map["/flavobjs/"] = [0,0,0,0]
   //map["/moth/"] = [0,0,0,0] // seems not really needed.
   //map["/eagle/"] = [0,0,0,0] // seems not really needed.
   
   // verified to be ok:
   // [borka,skeleton,raftpart,runestone,wbasket|wbasketo,lbox,coffer,bhive|bhived,
   // bumlings/02|,bumlings/03,barrel,chair,table,dreca,demijohn,winepress,quern|querna,
   // alloyer,churn|churna,sbasket|sbasketo,ttub|ttuba|ttubw,cndlbr|cndlbrc|cndlbrl,
   // cupboard,cauldron,cheeserack,swheel|swheela,mgrind,loom,crate,birchbasket,torchpost,
   // urn,oven,kiln|kilna,pow|powf|powr/roast|hearth-play,well|wella,bed-sprucebough,anthill,
   // bonfire,germania,sherlock,surg,(all tree's:06), ..]
   
   return map
   
   // Xcom converted leftover data.
   // Source-link: http://www.havenandhearth.com/forum/viewtopic.php?p=471487#p471487
   map["gfx/arch/door-inn"] = [-18,-13,10,11]
   map["gfx/arch/gates/brick-ns"] = [12,-16,-10,15]
   map["gfx/arch/gates/brick-we"] = [-12,-16,10,15]
   map["gfx/arch/gates/fence-ns"] = [12,-16,-10,15]
   map["gfx/arch/gates/fence-we"] = [-12,-16,10,15]
   map["gfx/arch/gates/palisade-ns"] = [12,-16,-10,15]
   map["gfx/arch/gates/palisade-we"] = [-12,-16,10,15]
   map["gfx/arch/stairs-inn"] = [8,-18,-14,17]
   map["gfx/kritter/bear/s"] = [0,-16,0,16]
   map["gfx/kritter/cow/s"] = [0,-8,0,14]
   map["gfx/kritter/deer/s"] = [0,-8,0,14]
   map["gfx/kritter/fox/s"] = [0,-6,0,8]
   map["gfx/kritter/rat/s"] = [0,0,0,2]
   map["gfx/kritter/troll/s"] = [0,-16,0,16]
   map["gfx/terobjs/blood"] = [0,-10,0,12] // none blocking.(?)
   map["gfx/terobjs/dframe2"] = [10,-11,-18,11]
   map["gfx/terobjs/furniture/leanto"] = [-8,-14,14,17]
   map["gfx/terobjs/furniture/wardrobe"] = [-10,-11,12,18]
   map["gfx/terobjs/mining/ladder"] = [-6,-5,8,6]
   map["gfx/terobjs/ridges/grass/e"] = [20,-14,-14,17]
   map["gfx/terobjs/ridges/grass/e2s"] = [44,-22,44,28]
   map["gfx/terobjs/ridges/grass/ee"] = [12,-14,-2,7]
   map["gfx/terobjs/ridges/grass/es"] = [2,-11,-16,12]
   map["gfx/terobjs/ridges/grass/s2w"] = [0,-22,-2,23]
   map["gfx/terobjs/ridges/grass/ss"] = [-12,-14,2,7]
   map["gfx/terobjs/ridges/mountain/ee"] = [20,-10,22,11]
   map["gfx/terobjs/ridges/mountain/ne"] = [0,-22,-22,11]
   map["gfx/terobjs/ridges/mountain/ns"] = [22,-11,0,22]
   map["gfx/terobjs/ridges/mountain/ss"] = [-20,-10,-22,11]
   map["gfx/terobjs/ridges/mountain/we"] = [-22,-11,0,22]
   map["gfx/terobjs/ridges/mountain/ws"] = [0,-22,22,11]
}
[v0.2]: working test example.
Main v0.2 fix: Hitbox processing. Should now work for all solid objects (with correct Neg-Res data).
++ Added additional checked hitbox data.

index
Last edited by mvgulik on Tue Aug 18, 2015 12:31 pm, edited 3 times in total.
mvgulik
 
Posts: 3742
Joined: Fri May 21, 2010 2:29 am

Re: Groovy maid scripts

Postby mvgulik » Fri Aug 14, 2015 12:40 pm

Major Update:
* "Walk around object" experiment. [v0.2]

--- --- ---

Plugin this code for easy testing on other objects.
Code: Select all
//def targ_gob = distanceSort_gobList(maid.getCoord(), maid.doAreaList(6))[1]
def distanceSort_gobList(cord1, data_list) {
   def Map data_map = list_to_map(data_list)
   for (e in data_list) {data_map[e] = cord1.dist(e.c)}
   data_map = data_map.sort {it.value}
   data_list = map_to_list(data_map)
   return data_list
}
def Map list_to_map(list_in) {
   def Map map_out = [:]
   for (item in list_in) {map_out[item] = null}
   return map_out
}
def List map_to_list(map_in) {
   def List list_out = []
   for (e in map_in) {list_out.add(e.key)}
   return list_out
}
... Darn doors.
mvgulik
 
Posts: 3742
Joined: Fri May 21, 2010 2:29 am

Previous

Return to The Wizards' Tower

Who is online

Users browsing this forum: No registered users and 2 guests