Merge branch 'newBranch' into 'master'

Draft: Fixed butler issues

Closes #1280, #2604, and #2615

See merge request 2009scape/2009scape!2355
This commit is contained in:
Player Name 2026-08-01 19:55:33 +00:00
commit fa2237f3d1
2 changed files with 111 additions and 62 deletions

View file

@ -16,6 +16,7 @@ import core.game.node.item.Item;
import core.game.system.task.Pulse;
import core.game.world.GameWorld;
import core.game.world.map.Location;
import core.game.world.map.Region;
import core.game.world.map.path.Pathfinder;
import content.global.handlers.iface.SawmillPlankInterface.Plank;
import org.rs09.consts.Items;
@ -27,16 +28,20 @@ import org.rs09.consts.Items;
* @version 0.98 (TODO: Missing a few dialogues)
*/
public class HouseServantDialogue extends DialoguePlugin {
/**
* If going outside to run logs by the sawmill or unnote planks at the bank.
*/
private boolean fetchRun;
/**
* If using the sawmill.
* If making planks.
*/
private boolean sawmill;
/**
* The logs
* The logs or noted planks.
*/
private Item logs;
private Item fetchItem;
/**
* Constructs a new {@code ServantDialogue} {@code Object}.
@ -66,8 +71,9 @@ public class HouseServantDialogue extends DialoguePlugin {
HouseManager manager = player.getHouseManager();
boolean inHouse = manager.isInHouse(player);
if (args.length > 1) { //Parse options from our "use-with" handler
sawmill = (boolean) args[1];
logs = (Item) args[2];
fetchRun = (boolean) args[1];
fetchItem = (Item) args[2];
sawmill = fetchRun && !fetchItem.getDefinition().isUnnoted();
}
if (player.getIronmanManager().checkRestriction(IronmanMode.ULTIMATE)) {
player.sendMessage("Ultimate Ironmen cannot hire butlers.");
@ -99,7 +105,12 @@ public class HouseServantDialogue extends DialoguePlugin {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "Very well, I will take these logs to the mill and", "have them converted into planks.");
stage = 110;
return true;
}
}
if (fetchRun) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "Shall I redeem that certificate for " + (player.isMale() ? "sir" : "madam"));
stage = 200;
return true;
}
if (servant.getItem().getAmount() > 0) {
if(player.getInventory().freeSlots() < 1){
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "I have returned with what you asked me to", "retrieve. As I see your inventory is full, I shall wait", "with these " + servant.getItem().getAmount()+" items until you are ready.");
@ -197,7 +208,7 @@ public class HouseServantDialogue extends DialoguePlugin {
return true;
}
end();
sawmillRun(player, (Item) servant.getAttribute("con:lastfetch"));
fetchRun(player, (Item) servant.getAttribute("con:lastfetch"));
}
break;
case 2:
@ -381,7 +392,7 @@ public class HouseServantDialogue extends DialoguePlugin {
break;
case 110:
end();
sawmillRun(player, logs);
fetchRun(player, fetchItem);
break;
case 150:
if (servant.getItem()== null) {
@ -404,11 +415,26 @@ public class HouseServantDialogue extends DialoguePlugin {
if (flag) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "I still have " + servant.getItem().getAmount() + " left for you to take from me.");
stage = 100;
} else{
} else {
end();
}
break;
case 200:
options("Yes", "No, just take it to the bank", "No, never mind");
stage++;
break;
case 201:
switch (buttonId) {
case 1:
// Enter amount
case 2:
case 3:
break;
}
break;
}
case 202:
// I regret that I am only able to carry 20 items, sir
return true;
}
@ -423,10 +449,10 @@ public class HouseServantDialogue extends DialoguePlugin {
* @param item
* @return true or false if they have the requirements to use the servant.
*/
private boolean prereqs(final Player player, final Item item, boolean sawmill) {
private boolean prereqs(final Player player, final Item item, boolean fetchRun) {
HouseManager manager = player.getHouseManager();
Servant servant = manager.getServant();
if (!sawmill && player.getInventory().freeSlots() < 1) {
if (!fetchRun && player.getInventory().freeSlots() < 1) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "You don't have any space in your inventory.");
stage = 100;
return false;
@ -449,54 +475,73 @@ public class HouseServantDialogue extends DialoguePlugin {
}
/**
* Goes to the sawmill.
* Goes to the sawmill or bank.
* @param player
* @param item
*/
private void sawmillRun(final Player player, final Item item) {
private void fetchRun(final Player player, final Item item) {
HouseManager manager = player.getHouseManager();
final Servant servant = manager.getServant();
final ServantType type = manager.getServant().getType();
if (servant == null || item == null || !prereqs(player, item, true)) {
if (!prereqs(player, item, true)) {
return;
}
if (type == ServantType.MAID || type == ServantType.RICK) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "I am unable to take planks to the sawmill.");
return;
}
int amt = player.getInventory().getAmount(item);
if (amt < 1) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "You don't have any more of that type of log.");
return;
}
for (Plank plank : Plank.values()) {
if (plank.getLog().getId() == item.getId()) {
if (amt > type.getCapacity()) {
amt = type.getCapacity();
if (sawmill) {
if (type == ServantType.MAID || type == ServantType.RICK) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "I am unable to take logs to the sawmill.");
return;
}
int amt = Math.min(player.getInventory().getAmount(item), type.getCapacity());
if (amt < 1) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "You don't have any more of that type of log.");
return;
}
for (Plank plank : Plank.values()) {
if (plank.getLog().getId() == item.getId()) {
if (!player.getInventory().contains(995, plank.getPrice() * amt)) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "You don't have enough coins for me to do that.", "I can hold " + type.getCapacity() + " logs and each of this type of log", "costs " + plank.getPrice() + " coins each to convert into plank form.");
return;
}
end();
if (player.getInventory().remove(new Item(item.getId(), amt)) && player.getInventory().remove(new Item(Items.COINS_995, amt * plank.getPrice()))) {
servant.setInvisible(true);
servant.getLocks().lockMovement(100);
GameWorld.getPulser().submit(new Pulse((int) (type.getTimer() / 0.6)){
@Override
public boolean pulse() {
servant.setInvisible(false);
servant.getLocks().unlockMovement();
manager.getServant().setItem(new Item(plank.getPlank().getId(), amt));
interpreter.open(servant.getId(), servant);
servant.setAttribute("con:lastfetch", new Item(item.getId(), 1));
servant.setAttribute("con:lastfetchtype", "sawmill");
manager.getServant().setUses(manager.getServant().getUses() + 1);
follow(player, servant);
return true;
}
});
}
break;
}
if (!player.getInventory().contains(995, plank.getPrice() * amt)) {
interpreter.sendDialogues(servant, servant.getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "You don't have enough coins for me to do that.", "I can hold " + type.getCapacity() + " logs and each of this type of log", "costs " + plank.getPrice() + " coins each to convert into plank form.");
return;
}
end();
if (player.getInventory().remove(new Item(item.getId(), amt)) && player.getInventory().remove(new Item(Items.COINS_995, amt * plank.getPrice()))) {
manager.getServant().setItem(new Item(plank.getPlank().getId(), amt));
servant.setInvisible(true);
servant.getLocks().lockMovement(100);
GameWorld.getPulser().submit(new Pulse((int) (type.getTimer() / 0.6)){
@Override
public boolean pulse() {
servant.setInvisible(false);
servant.getLocks().unlockMovement();
servant.setAttribute("con:lastfetch", new Item(item.getId(), 1));
servant.setAttribute("con:lastfetchtype", "sawmill");
interpreter.open(servant.getId(), servant);
return true;
}
});
}
break;
}
} else { //just unnote
int amt = Math.min(item.getAmount(), type.getCapacity());
if (player.getInventory().remove(new Item(item.getId(), amt))) {
servant.setInvisible(true);
servant.getLocks().lockMovement(100);
GameWorld.getPulser().submit(new Pulse((int) (type.getTimer() / 0.6)){
@Override
public boolean pulse() {
servant.setInvisible(false);
servant.getLocks().unlockMovement();
manager.getServant().setItem(new Item(item.getId()-1, amt));
interpreter.open(servant.getId(), servant);
// Purposefully not setting last fetch
manager.getServant().setUses(manager.getServant().getUses() + 1);
follow(player, servant);
return true;
}
});
}
}
}
@ -522,10 +567,12 @@ public class HouseServantDialogue extends DialoguePlugin {
servant.setInvisible(true);
servant.getLocks().lockMovement(100);
GameWorld.getPulser().submit(new Pulse((int) (type.getTimer() / 0.6)) {
@Override
public boolean pulse() {
if (player == null || player.getHouseManager().getHouseRegion() != player.getViewport().getRegion()) { //TODO: Check if in dungeon?
Region pr = player.getViewport().getRegion();
Region hr = player.getHouseManager().getHouseRegion();
Region dr = player.getHouseManager().getDungeonRegion();
if (pr != hr && pr != dr) {
return true;
}
int amt = player.getBank().getAmount(item.getId());
@ -548,7 +595,6 @@ public class HouseServantDialogue extends DialoguePlugin {
follow(player, servant);
return true;
}
});
}

View file

@ -6,6 +6,8 @@ import core.game.interaction.UseWithHandler;
import core.plugin.Initializable;
import core.plugin.Plugin;
import core.plugin.ClassScanner;
import org.rs09.consts.Items;
import org.rs09.consts.NPCs;
/**
* Handles interaction with the house servant.
@ -19,11 +21,13 @@ import core.plugin.ClassScanner;
*/
@Initializable
public class HouseServantPlugin extends UseWithHandler {
/**
* The item IDS to use.
*/
final static int[] IDS = { 1511, 1521, 6333, 6332 };
final static int[] IDS = {
Items.LOGS_1511, Items.OAK_LOGS_1521, Items.TEAK_LOGS_6333, Items.MAHOGANY_LOGS_6332,
Items.PLANK_961, Items.OAK_PLANK_8779, Items.TEAK_PLANK_8781, Items.MAHOGANY_PLANK_8783 //noted planks
};
/**
* Constructs a new {@code HouseServantPlugin} {@code Object}.
@ -34,11 +38,11 @@ public class HouseServantPlugin extends UseWithHandler {
@Override
public Plugin<Object> newInstance(Object arg) throws Throwable {
addHandler(4235, NPC_TYPE, this);
addHandler(4237, NPC_TYPE, this);
addHandler(4239, NPC_TYPE, this);
addHandler(4241, NPC_TYPE, this);
addHandler(4243, NPC_TYPE, this);
addHandler(NPCs.RICK_4235, NPC_TYPE, this);
addHandler(NPCs.MAID_4237, NPC_TYPE, this);
addHandler(NPCs.COOK_4239, NPC_TYPE, this);
addHandler(NPCs.BUTLER_4241, NPC_TYPE, this);
addHandler(NPCs.DEMON_BUTLER_4243, NPC_TYPE, this);
ClassScanner.definePlugin(new HouseServantDialogue());
return this;
}
@ -51,5 +55,4 @@ public class HouseServantPlugin extends UseWithHandler {
event.getPlayer().getDialogueInterpreter().open(event.getUsedWith().asNpc().getId(), event.getUsedWith().asNpc(), true, event.getUsedItem());
return true;
}
}
}