|
|
@ -1,13 +1,23 @@ |
|
|
|
package sig; |
|
|
|
package sig; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.awt.AWTException; |
|
|
|
|
|
|
|
import java.awt.Color; |
|
|
|
|
|
|
|
import java.awt.GraphicsEnvironment; |
|
|
|
|
|
|
|
import java.awt.Point; |
|
|
|
|
|
|
|
import java.awt.Robot; |
|
|
|
|
|
|
|
import java.awt.event.KeyEvent; |
|
|
|
|
|
|
|
import java.awt.image.BufferedImage; |
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Map; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
import java.util.regex.Pattern; |
|
|
|
|
|
|
|
|
|
|
|
import sig.skills.BasicSynthesis; |
|
|
|
import sig.skills.BasicSynthesis; |
|
|
|
import sig.skills.BasicTouch; |
|
|
|
import sig.skills.BasicTouch; |
|
|
|
import sig.skills.BrandOfTheElements; |
|
|
|
import sig.skills.BrandOfTheElements; |
|
|
|
|
|
|
|
import sig.skills.ByregotsBlessing; |
|
|
|
import sig.skills.GreatStrides; |
|
|
|
import sig.skills.GreatStrides; |
|
|
|
import sig.skills.HastyTouch; |
|
|
|
import sig.skills.HastyTouch; |
|
|
|
import sig.skills.InnerQuiet; |
|
|
|
import sig.skills.InnerQuiet; |
|
|
@ -45,6 +55,12 @@ public class SigCraft { |
|
|
|
|
|
|
|
|
|
|
|
public static Craft BEST_CRAFT; |
|
|
|
public static Craft BEST_CRAFT; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static Robot r; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static ColorPosition CRAFTING_WINDOW_PIXELS = new ColorPosition(284,68,77,77,77); |
|
|
|
|
|
|
|
public static ColorPosition CRAFT_START_PIXELS = new ColorPosition(334,130,74,77,74); |
|
|
|
|
|
|
|
public static ColorPosition READY_FOR_ACTION_PIXELS = new ColorPosition(1031,892,230,197,164); |
|
|
|
|
|
|
|
|
|
|
|
//Quality = (0.37 * Control + 32.6) * (1 - 0.05 * min(max(Recipe Level - Character Level, 0), 5))
|
|
|
|
//Quality = (0.37 * Control + 32.6) * (1 - 0.05 * min(max(Recipe Level - Character Level, 0), 5))
|
|
|
|
//Good +50%, Excellent +300%
|
|
|
|
//Good +50%, Excellent +300%
|
|
|
|
|
|
|
|
|
|
|
@ -53,23 +69,32 @@ public class SigCraft { |
|
|
|
public static ArrayList<Craft> SucceededCrafts = new ArrayList<Craft>(); |
|
|
|
public static ArrayList<Craft> SucceededCrafts = new ArrayList<Craft>(); |
|
|
|
|
|
|
|
|
|
|
|
public static void main(String[] args) { |
|
|
|
public static void main(String[] args) { |
|
|
|
SKILLLIST.put("Rapid Synthesis",new RapidSynthesis("Rapid Synthesis",0,false,9)); |
|
|
|
|
|
|
|
SKILLLIST.put("Basic Synthesis",new BasicSynthesis("Basic Synthesis",0,true,1)); |
|
|
|
try { |
|
|
|
SKILLLIST.put("Brand of the Elements",new BrandOfTheElements("Brand of the Elements",6,true,37)); |
|
|
|
r = new Robot(); |
|
|
|
SKILLLIST.put("Basic Touch",new BasicTouch("Basic Touch",18,true,5)); |
|
|
|
} catch (AWTException e) { |
|
|
|
SKILLLIST.put("Hasty Touch",new HastyTouch("Hasty Touch",0,false,9)); |
|
|
|
e.printStackTrace(); |
|
|
|
SKILLLIST.put("Standard Touch",new StandardTouch("Standard Touch",32,true,18)); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SKILLLIST.put("Rapid Synthesis",new RapidSynthesis("Rapid Synthesis",0,false,9,KeyEvent.VK_SHIFT,KeyEvent.VK_4)); |
|
|
|
|
|
|
|
SKILLLIST.put("Basic Synthesis",new BasicSynthesis("Basic Synthesis",0,true,1,KeyEvent.VK_1)); |
|
|
|
|
|
|
|
SKILLLIST.put("Brand of the Elements",new BrandOfTheElements("Brand of the Elements",6,true,37,KeyEvent.VK_CONTROL,KeyEvent.VK_X)); |
|
|
|
|
|
|
|
SKILLLIST.put("Basic Touch",new BasicTouch("Basic Touch",18,true,5,KeyEvent.VK_2)); |
|
|
|
|
|
|
|
SKILLLIST.put("Hasty Touch",new HastyTouch("Hasty Touch",0,false,9,KeyEvent.VK_CONTROL,KeyEvent.VK_3)); |
|
|
|
|
|
|
|
SKILLLIST.put("Standard Touch",new StandardTouch("Standard Touch",32,true,18,KeyEvent.VK_SHIFT,KeyEvent.VK_2)); |
|
|
|
//SKILLLIST.add(new Skill("Byregot's Blessing",24,true,50)); //TODO We don't know how this works yet.
|
|
|
|
//SKILLLIST.add(new Skill("Byregot's Blessing",24,true,50)); //TODO We don't know how this works yet.
|
|
|
|
SKILLLIST.put("Tricks of the Trade",new TricksOfTheTrade("Tricks of the Trade",0,true,13)); |
|
|
|
SKILLLIST.put("Tricks of the Trade",new TricksOfTheTrade("Tricks of the Trade",0,true,13,KeyEvent.VK_CONTROL,KeyEvent.VK_2)); |
|
|
|
SKILLLIST.put("Master's Mend",new MastersMend("Master's Mend",88,true,7)); |
|
|
|
SKILLLIST.put("Master's Mend",new MastersMend("Master's Mend",88,true,7,KeyEvent.VK_3)); |
|
|
|
SKILLLIST.put("Waste Not",new WasteNot("Waste Not",56,true,15)); |
|
|
|
SKILLLIST.put("Waste Not",new WasteNot("Waste Not",56,true,15,KeyEvent.VK_CONTROL,KeyEvent.VK_1)); |
|
|
|
SKILLLIST.put("Waste Not II",new WasteNotII("Waste Not II",98,true,47)); |
|
|
|
SKILLLIST.put("Waste Not II",new WasteNotII("Waste Not II",98,true,47,KeyEvent.VK_CONTROL,KeyEvent.VK_4)); |
|
|
|
SKILLLIST.put("Inner Quiet",new InnerQuiet("Inner Quiet",18,true,11)); |
|
|
|
SKILLLIST.put("Inner Quiet",new InnerQuiet("Inner Quiet",18,true,11,KeyEvent.VK_5)); |
|
|
|
SKILLLIST.put("Veneration",new Veneration("Veneration",18,true,15)); |
|
|
|
SKILLLIST.put("Veneration",new Veneration("Veneration",18,true,15,KeyEvent.VK_SHIFT,KeyEvent.VK_1)); |
|
|
|
SKILLLIST.put("Great Strides",new GreatStrides("Great Strides",32,true,21)); |
|
|
|
SKILLLIST.put("Great Strides",new GreatStrides("Great Strides",32,true,21,KeyEvent.VK_CONTROL,KeyEvent.VK_5)); |
|
|
|
SKILLLIST.put("Innovation",new Innovation("Innovation",18,true,26)); |
|
|
|
SKILLLIST.put("Innovation",new Innovation("Innovation",18,true,26,KeyEvent.VK_4)); |
|
|
|
SKILLLIST.put("Name of the Elements",new NameOfTheElements("Name of the Elements",30,true,37)); |
|
|
|
SKILLLIST.put("Name of the Elements",new NameOfTheElements("Name of the Elements",30,true,37,KeyEvent.VK_CONTROL,KeyEvent.VK_Z)); |
|
|
|
SKILLLIST.put("Observe",new Observe("Observe",7,true,13)); |
|
|
|
SKILLLIST.put("Observe",new Observe("Observe",7,true,13,KeyEvent.VK_C)); |
|
|
|
|
|
|
|
SKILLLIST.put("Byregot's Blessing",new ByregotsBlessing("Byregot's Blessing",24,true,50,KeyEvent.VK_ALT,KeyEvent.VK_2)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BUFFLIST.put("Inner Quiet",new Buff("Inner Quiet",0)); |
|
|
|
BUFFLIST.put("Inner Quiet",new Buff("Inner Quiet",0)); |
|
|
|
BUFFLIST.put("Veneration",new Buff("Veneration",0)); |
|
|
|
BUFFLIST.put("Veneration",new Buff("Veneration",0)); |
|
|
@ -80,7 +105,125 @@ public class SigCraft { |
|
|
|
BUFFLIST.put("Inner Quiet",new Buff("Inner Quiet", 0)); |
|
|
|
BUFFLIST.put("Inner Quiet",new Buff("Inner Quiet", 0)); |
|
|
|
BUFFLIST.put("Waste Not",new Buff("Waste Not",0)); |
|
|
|
BUFFLIST.put("Waste Not",new Buff("Waste Not",0)); |
|
|
|
|
|
|
|
|
|
|
|
SetupCraft(); |
|
|
|
//SetupCraft();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//284,68 77,77,77
|
|
|
|
|
|
|
|
while (true) { |
|
|
|
|
|
|
|
r.delay(1000); |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
Color col=null; |
|
|
|
|
|
|
|
LookForScreenPixels(CRAFTING_WINDOW_PIXELS); |
|
|
|
|
|
|
|
System.out.println("Detected crafting window..."); |
|
|
|
|
|
|
|
PressKey(KeyEvent.VK_NUMPAD0);r.delay(300); |
|
|
|
|
|
|
|
PressKey(KeyEvent.VK_NUMPAD0);r.delay(300); |
|
|
|
|
|
|
|
PressKey(KeyEvent.VK_NUMPAD0);r.delay(300); |
|
|
|
|
|
|
|
PressKey(KeyEvent.VK_NUMPAD0);r.delay(300); |
|
|
|
|
|
|
|
//334,130 74,77,74
|
|
|
|
|
|
|
|
LookForScreenPixels(CRAFT_START_PIXELS); |
|
|
|
|
|
|
|
System.out.println("Craft started..."); |
|
|
|
|
|
|
|
//336,267 151,220,96
|
|
|
|
|
|
|
|
LookForScreenPixels(READY_FOR_ACTION_PIXELS); |
|
|
|
|
|
|
|
LoadRotation_40Durability_1700Quality_1Synth_280CP_LV47(); |
|
|
|
|
|
|
|
} catch (IOException | InterruptedException e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
//break;
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void LoadRotation_40Durability_1700Quality_1Synth_280CP_LV47() { |
|
|
|
|
|
|
|
PerformSkill("Inner Quiet"); |
|
|
|
|
|
|
|
PerformSkill("Innovation"); |
|
|
|
|
|
|
|
PerformSkill("Waste Not II"); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Standard Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Standard Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Innovation",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Standard Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Synthesis"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void LoadRotation_40Durability_1900Quality_1Synth_280CP_LV45() { |
|
|
|
|
|
|
|
PerformSkill("Inner Quiet"); |
|
|
|
|
|
|
|
PerformSkill("Waste Not"); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Standard Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Standard Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Innovation",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Standard Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Touch",true); |
|
|
|
|
|
|
|
PerformSkill("Basic Synthesis"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void GetCondition() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void PerformSkill(String string) { |
|
|
|
|
|
|
|
PerformSkill(string,false); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void PerformSkill(String string,boolean checkForMaxQuality) { |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
LookForScreenPixels(READY_FOR_ACTION_PIXELS); |
|
|
|
|
|
|
|
} catch (IOException | InterruptedException e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
r.delay(100); |
|
|
|
|
|
|
|
Skill s = SKILLLIST.get(string); |
|
|
|
|
|
|
|
if (s==null) { |
|
|
|
|
|
|
|
System.err.println("Could not find skill "+string+"!"); |
|
|
|
|
|
|
|
System.exit(1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (checkForMaxQuality&&MaxQuality()) {return;} |
|
|
|
|
|
|
|
if (s.modifier!=-1) { |
|
|
|
|
|
|
|
PressKeyWithModifier(s.modifier,s.key); |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
PressKey(s.key); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
r.delay(500); |
|
|
|
|
|
|
|
//1031,892 115,98,82 230,197,164
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static boolean MaxQuality() { |
|
|
|
|
|
|
|
Color col=null; |
|
|
|
|
|
|
|
try { |
|
|
|
|
|
|
|
col = new Color(CaptureScreen().getRGB(336, 267)); |
|
|
|
|
|
|
|
} catch (IOException e) { |
|
|
|
|
|
|
|
e.printStackTrace(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return col.getRed()==151&&col.getGreen()==220&&col.getBlue()==96; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void LookForScreenPixels(ColorPosition cp) throws IOException, InterruptedException { |
|
|
|
|
|
|
|
Color col; |
|
|
|
|
|
|
|
do { |
|
|
|
|
|
|
|
col = new Color(CaptureScreen().getRGB(cp.p.x, cp.p.y)); |
|
|
|
|
|
|
|
r.delay(100); |
|
|
|
|
|
|
|
} while (!cp.c.equals(col)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static BufferedImage CaptureScreen() throws IOException { |
|
|
|
|
|
|
|
BufferedImage screenshot = r.createScreenCapture(GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds()); |
|
|
|
|
|
|
|
//ImageIO.write(screenshot,"png",new File("screenshot.png"));
|
|
|
|
|
|
|
|
return screenshot; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void PressKey(int keycode) { |
|
|
|
|
|
|
|
r.keyPress(keycode); |
|
|
|
|
|
|
|
r.keyRelease(keycode); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void PressKeyWithModifier(int modifier,int keycode) { |
|
|
|
|
|
|
|
r.keyPress(modifier); |
|
|
|
|
|
|
|
r.keyPress(keycode); |
|
|
|
|
|
|
|
r.keyRelease(keycode);r.delay(100); |
|
|
|
|
|
|
|
r.keyRelease(modifier); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static boolean IsThereEnoughTurns(int durability,Map<String,Buff> bufflist,int turnsRequired) { |
|
|
|
public static boolean IsThereEnoughTurns(int durability,Map<String,Buff> bufflist,int turnsRequired) { |
|
|
@ -136,18 +279,24 @@ public class SigCraft { |
|
|
|
System.out.println("\tUsing standard rotation for Progress. Quality CP Available: "+qualityCPRemaining); |
|
|
|
System.out.println("\tUsing standard rotation for Progress. Quality CP Available: "+qualityCPRemaining); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//Can we just straight up craft?
|
|
|
|
RunCraftCheck(new String[]{},new String[]{"Basic Touch"},new String[]{}); |
|
|
|
List<Skill> quality_rotation1 = new ArrayList<Skill>(); |
|
|
|
|
|
|
|
Craft c3 = new Craft(CONTROL,LEVEL,CP,BASE_PROGRESS,PROGRESS_GOAL,QUALITY_GOAL,GUARANTEED,DURABILITY,CRAFT_PROGRESS,CRAFT_QUALITY,DURABILITY,qualityCPRemaining,1,1,1,RECIPE_LEVEL,Status.NORMAL,BUFFLIST); |
|
|
|
|
|
|
|
boolean combo=false; |
|
|
|
boolean combo=false; |
|
|
|
while (c3.craft_quality<c3.quality_goal && IsThereEnoughTurns(c3.craft_durability,c3.BuffList,PROGRESS_FINAL_STEPS)) { |
|
|
|
//Can we just straight up craft?
|
|
|
|
s = !combo?SKILLLIST.get("Basic Touch"):SKILLLIST.get("Standard Touch"); |
|
|
|
for (int i=0;i<2;i++) { |
|
|
|
s.useSkill(c3); |
|
|
|
List<Skill> quality_rotation1 = new ArrayList<Skill>(); |
|
|
|
quality_rotation1.add(s); |
|
|
|
Craft c3 = new Craft(CONTROL,LEVEL,CP,BASE_PROGRESS,PROGRESS_GOAL,QUALITY_GOAL,GUARANTEED,DURABILITY,CRAFT_PROGRESS,CRAFT_QUALITY,DURABILITY,qualityCPRemaining,1,1,1,RECIPE_LEVEL,Status.NORMAL,BUFFLIST); |
|
|
|
combo=!combo; |
|
|
|
combo=false; |
|
|
|
combo = AttemptMastersMend(PROGRESS_FINAL_STEPS, quality_rotation1, c3, combo); |
|
|
|
while (c3.craft_quality<c3.quality_goal && IsThereEnoughTurns(c3.craft_durability,c3.BuffList,PROGRESS_FINAL_STEPS)) { |
|
|
|
|
|
|
|
s = !combo?SKILLLIST.get("Basic Touch"):SKILLLIST.get("Standard Touch"); |
|
|
|
|
|
|
|
s.useSkill(c3); |
|
|
|
|
|
|
|
quality_rotation1.add(s); |
|
|
|
|
|
|
|
combo=!combo; |
|
|
|
|
|
|
|
if (i==1) {combo = AttemptMastersMend(PROGRESS_FINAL_STEPS, quality_rotation1, c3, combo);} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
System.out.println("Raw Quality Rotation leaves "+c3.craft_cp+" CP, "+c3.craft_durability+" durability, "+(c3.quality_goal-c3.craft_quality)+" quality from the goal."); |
|
|
|
|
|
|
|
if (i==0&&c3.craft_cp<=SKILLLIST.get("Master's Mend").CPCost) {break;} |
|
|
|
} |
|
|
|
} |
|
|
|
System.out.println("Raw Quality Rotation leaves "+c3.craft_cp+" CP, "+c3.craft_durability+" durability, "+(c3.quality_goal-c3.craft_quality)+" quality from the goal."); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//Add Inner Quiet
|
|
|
|
//Add Inner Quiet
|
|
|
|
List<Skill> quality_rotation2 = new ArrayList<Skill>(); |
|
|
|
List<Skill> quality_rotation2 = new ArrayList<Skill>(); |
|
|
@ -435,6 +584,25 @@ public class SigCraft { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static void RunCraftCheck(String[] preAbilities, String[] repeatAbilities, String[] reapplyBuffs, int qualityCPRemaining, int PROGRESS_FINAL_STEPS) { |
|
|
|
|
|
|
|
List<Skill> rotation = new ArrayList<Skill>(); |
|
|
|
|
|
|
|
Craft craft = new Craft(CONTROL,LEVEL,CP,BASE_PROGRESS,PROGRESS_GOAL,QUALITY_GOAL,GUARANTEED,DURABILITY,CRAFT_PROGRESS,CRAFT_QUALITY,DURABILITY,qualityCPRemaining,1,1,1,RECIPE_LEVEL,Status.NORMAL,BUFFLIST); |
|
|
|
|
|
|
|
for (String s : preAbilities) { |
|
|
|
|
|
|
|
Skill ss = SKILLLIST.get(s); |
|
|
|
|
|
|
|
ss.useSkill(craft); |
|
|
|
|
|
|
|
rotation.add(ss); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
while (craft.craft_quality<craft.quality_goal && IsThereEnoughTurns(craft.craft_durability,craft.BuffList,PROGRESS_FINAL_STEPS)) { |
|
|
|
|
|
|
|
for (String s : reapplyBuffs) { |
|
|
|
|
|
|
|
if (craft.BuffList.get(s.replaceAll(Pattern.quote("Waste Not II"),"Waste Not")).stackCount==0) { |
|
|
|
|
|
|
|
Skill ss = SKILLLIST.get(s); |
|
|
|
|
|
|
|
ss.useSkill(craft); |
|
|
|
|
|
|
|
rotation.add(ss); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static boolean AttemptMastersMend(int PROGRESS_FINAL_STEPS, List<Skill> quality_rotation1, Craft c3, |
|
|
|
private static boolean AttemptMastersMend(int PROGRESS_FINAL_STEPS, List<Skill> quality_rotation1, Craft c3, |
|
|
|
boolean combo) { |
|
|
|
boolean combo) { |
|
|
|
Skill s; |
|
|
|
Skill s; |
|
|
|