Rewrote pet management

Fixed being unable to remove pets
Removed redundant pet messaging
This commit is contained in:
Player Name
2023-10-04 23:19:57 +00:00
committed by Ryan
parent e5afeed6db
commit 7c38339e16
6 changed files with 175 additions and 114 deletions
@@ -4,6 +4,7 @@ import content.global.skill.summoning.pet.Pet;
import content.global.skill.summoning.pet.Pets;
import core.cache.def.impl.ItemDefinition;
import core.game.component.Component;
import core.game.container.Container;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import core.game.node.entity.skill.Skills;
@@ -27,6 +28,7 @@ import static core.api.ContentAPIKt.*;
/**
* Handles a player's familiar.
* @author Emperor
* @author Player Name
*/
public final class FamiliarManager {
@@ -74,25 +76,49 @@ public final class FamiliarManager {
}
public final void parse(JSONObject familiarData) {
int currentPet = -1;
if (familiarData.containsKey("currentPet")) {
currentPet = Integer.parseInt(familiarData.get("currentPet").toString());
}
JSONArray petDetails = (JSONArray) familiarData.get("petDetails");
for (int i = 0 ; i < petDetails.size(); i++) {
JSONObject detail = (JSONObject) petDetails.get(i);
PetDetails details = new PetDetails(0);
details.updateHunger(Double.parseDouble(detail.get("hunger").toString()));
details.updateGrowth(Double.parseDouble(detail.get("growth").toString()));
details.setStage(Integer.parseInt(detail.get("stage").toString()));
this.petDetails.put(Integer.parseInt(detail.get("petId").toString()),details);
int itemIdHash = Integer.parseInt(detail.get("petId").toString());
// The below is for migrating legacy saves, which stored baby item IDs + growth stages
if (detail.containsKey("stage")) {
// The "itemIdHash" is actually the baby item ID. The "stage" gives the actual pet stage we want.
int babyItemId = itemIdHash;
int itemId = babyItemId;
int stage = Integer.parseInt(detail.get("stage").toString());
if (stage > 0) {
Pets pets = Pets.forId(babyItemId);
itemId = pets.getNextStageItemId(itemId);
if (stage > 1) {
itemId = pets.getNextStageItemId(itemId);
}
}
Item item = new Item(itemId);
item.setCharge(1000); //this is the default value that will correspond to the player's item
itemIdHash = item.getIdHash();
if (currentPet != -1 && currentPet == babyItemId) {
currentPet = itemIdHash;
}
}
this.petDetails.put(itemIdHash, details);
}
if(familiarData.containsKey("currentPet")){
int currentPet = Integer.parseInt( familiarData.get("currentPet").toString());
if (currentPet != -1) {
PetDetails details = this.petDetails.get(currentPet);
Pets pets = Pets.forId(currentPet);
int itemId = currentPet >> 16 & 0xFFFF;
Pets pets = Pets.forId(itemId);
if (details == null) {
details = new PetDetails(pets.getGrowthRate() == 0.0 ? 100.0 : 0.0);
this.petDetails.put(currentPet, details);
}
familiar = new Pet(player, details, currentPet, pets.getNpcId(details.getStage()));
familiar = new Pet(player, details, itemId, pets.getNpcId(itemId));
} else if (familiarData.containsKey("familiar")) {
JSONObject currentFamiliar = (JSONObject) familiarData.get("familiar");
int familiarId = Integer.parseInt( currentFamiliar.get("originalId").toString());
@@ -156,7 +182,7 @@ public final class FamiliarManager {
final int npcId = pouch.getNpcId();
Familiar fam = !renew ? FAMILIARS.get(npcId) : familiar;
if (fam == null) {
player.getPacketDispatch().sendMessage("Invalid familiar " + npcId + " - report on 2009scape github");
player.getPacketDispatch().sendMessage("Invalid familiar " + npcId + " - report on 2009scape GitLab");
return;
}
if(!renew) {
@@ -219,6 +245,7 @@ public final class FamiliarManager {
*/
private boolean summonPet(final Item item, boolean deleteItem, boolean morph, Location location) {
final int itemId = item.getId();
int itemIdHash = item.getIdHash();
if (itemId > 8850 && itemId < 8900) {
return false;
}
@@ -230,18 +257,26 @@ public final class FamiliarManager {
player.getDialogueInterpreter().sendDialogue("You need a summoning level of " + pets.getSummoningLevel() + " to summon this.");
return false;
}
int baseItemId = pets.getBabyItemId();
PetDetails details = petDetails.get(baseItemId);
if (details == null) {
PetDetails details = petDetails.get(itemIdHash);
if (details == null) { //init new pet
details = new PetDetails(pets.getGrowthRate() == 0.0 ? 100.0 : 0.0);
petDetails.put(baseItemId, details);
// Find an available individual slot
ArrayList<Integer> taken = new ArrayList<Integer>();
Container[] searchSpace = {player.getInventory(), player.getBankPrimary(), player.getBankSecondary()};
for (Container container : searchSpace) {
for (Item i : container.getAll(item)) {
taken.add(i.getCharge());
}
int id = pets.getItemId(details.getStage());
if (itemId != id) {
player.getPacketDispatch().sendMessage("This is not the right pet, grow the pet correctly.");
return true;
}
int npcId = pets.getNpcId(details.getStage());
int individual;
for (individual = 0; taken.contains(individual) && individual < 0xFFFF; individual++) {}
details.setIndividual(individual);
item.setCharge(individual);
itemIdHash = item.getIdHash(); //updates the hashed item to include the new "charge" value
petDetails.put(itemIdHash, details);
}
int npcId = pets.getNpcId(itemId);
if (npcId > 0) {
familiar = new Pet(player, details, itemId, npcId);
if (deleteItem) {
@@ -314,7 +349,9 @@ public final class FamiliarManager {
}
Pet pet = ((Pet) familiar);
PetDetails details = pet.getDetails();
if (player.getInventory().add(new Item(pet.getPet().getItemId(details.getStage())))) {
Item petItem = new Item(pet.getItemId());
petItem.setCharge(details.getIndividual());
if (player.getInventory().add(petItem)) {
player.animate(Animation.create(827));
player.getFamiliarManager().dismiss();
}
@@ -365,7 +402,7 @@ public final class FamiliarManager {
*/
public void dismiss(boolean saveDetails) {
if (hasPet() && !saveDetails) {
removeDetails(((Pet) familiar).getItemId());
removeDetails(((Pet) familiar).getItemIdHash());
}
if (hasFamiliar()) {
familiar.dismiss();
@@ -4,6 +4,8 @@ import content.global.skill.skillcapeperks.SkillcapePerks;
import content.global.skill.summoning.familiar.Familiar;
import content.global.skill.summoning.familiar.FamiliarSpecial;
import core.game.node.entity.player.Player;
import core.game.node.item.Item;
import core.game.world.GameWorld;
import static core.api.ContentAPIKt.*;
@@ -66,10 +68,12 @@ public final class Pet extends Familiar {
public void handleTickActions() {
final PetDetails petDetails = details;
if (getPet().getFood().length > 0) {
if(SkillcapePerks.isActive(SkillcapePerks.PET_MASTERY, owner)) {
petDetails.updateHunger(0);
} else {
petDetails.updateHunger(petDetails.getStage() == 0 ? 0.025 : 0.018);
if(!SkillcapePerks.isActive(SkillcapePerks.PET_MASTERY, owner)) {
double amount = itemId == pet.getBabyItemId() ? 0.025 : 0.018;
if (GameWorld.getSettings().isDevMode()) {
amount *= 100;
}
petDetails.updateHunger(amount);
}
}
double hunger = petDetails.getHunger();
@@ -89,8 +93,12 @@ public final class Pet extends Familiar {
return;
}
double growth = petDetails.getGrowth();
if (pet.getGrowthRate() > 0.000) {
petDetails.updateGrowth(pet.getGrowthRate());
double growthrate = pet.getGrowthRate();
if (growthrate > 0.000) {
if (GameWorld.getSettings().isDevMode()) {
growthrate *= 100;
}
petDetails.updateGrowth(growthrate);
if (growth == 100.0) {
growNextStage();
}
@@ -108,25 +116,21 @@ public final class Pet extends Familiar {
/**
* Method used to grow the npc's next stage.
*/
public final void growNextStage() {
if (details.getStage() == 3) {
return;
}
public void growNextStage() {
if (pet == null) {
return;
}
int npcId = pet.getNpcId(details.getStage() + 1);
if (npcId < 1) {
int newItemId = pet.getNextStageItemId(itemId);
if (newItemId == -1) {
// then this pet is already overgrown
return;
}
details.setStage(details.getStage() + 1);
int itemId = pet.getItemId(details.getStage());
if (pet.getNpcId(details.getStage() + 1) > 0) {
int npcId = pet.getNpcId(newItemId);
details.updateGrowth(-100.0);
}
clear();
Pet newPet = new Pet(owner, details, itemId, npcId);
Pet newPet = new Pet(owner, details, newItemId, npcId);
newPet.growthRate = growthRate;
newPet.hasWarned = hasWarned;
owner.getFamiliarManager().dismiss(false);
owner.getFamiliarManager().setFamiliar(newPet);
owner.getPacketDispatch().sendMessage("<col=ff0000>Your pet has grown larger.</col>");
owner.getFamiliarManager().spawnFamiliar();
@@ -171,6 +175,16 @@ public final class Pet extends Familiar {
return itemId;
}
/**
* Gets the itemId with the individual hashed in.
* @return The itemIdHash.
*/
public int getItemIdHash() {
Item item = new Item(itemId);
item.setCharge(details.getIndividual());
return item.getIdHash();
}
/**
* Gets the details.
* @return The details.
@@ -2,11 +2,10 @@ package content.global.skill.summoning.pet;
import core.game.world.GameWorld;
/**
* A class containing pet details for a certain pet.
* @author Emperor
* @author Player Name
*/
public final class PetDetails {
@@ -21,9 +20,9 @@ public final class PetDetails {
private double growth = 0.0;
/**
* The current stage of the pet (0 - baby, 1 - grown, 2 - overgrown).
* The individual, an in principle arbitrary integer read off of the item's charge slot.
*/
private int stage;
private int individual;
/**
* Constructs a new {@code PetDetails} {@code Object}.
@@ -38,15 +37,9 @@ public final class PetDetails {
* @param amount The amount.
*/
public void updateHunger(double amount) {
if(GameWorld.getSettings().isDevMode()){
hunger += amount * 100;
} else {
hunger += amount;
}
if (hunger < 0.0) {
hunger = 0.0;
} else if (hunger > 100.0) {
hunger = 100.0;
}
}
@@ -80,19 +73,18 @@ public final class PetDetails {
}
/**
* Gets the stage.
* @return The stage.
* Sets the individual.
* @param individual The individual to set.
*/
public int getStage() {
return stage;
public void setIndividual(int individual) {
this.individual = individual;
}
/**
* Sets the stage.
* @param stage The stage to set.
* Gets the individual.
* @return The individual.
*/
public void setStage(int stage) {
this.stage = stage;
public int getIndividual() {
return individual;
}
}
@@ -1,13 +1,17 @@
package content.global.skill.summoning.pet;
import core.game.node.entity.player.Player;
import core.tools.Log;
import java.util.HashMap;
import java.util.Map;
import static core.api.ContentAPIKt.log;
/**
* An enum containing all the pets and their info.
* @author Emperor
* @author Player Name
*/
public enum Pets {
@@ -446,35 +450,35 @@ public enum Pets {
/**
* Gets the NPC id for this pet.
* @param stage The stage of the pet.
* @return The NPc id.
* @param itemId An int giving the ID of the item for which we want to know the corresponding NPC id.
* @return The NPC id.
*/
public int getNpcId(int stage) {
switch (stage) {
case 0:
public int getNpcId(int itemId) {
if (itemId == babyItemId) {
return babyNpcId;
case 1:
}
if (itemId == grownItemId) {
return grownNpcId;
case 2:
}
if (itemId == overgrownItemId) {
return overgrownNpcId;
}
return 0;
log(this.getClass(), Log.ERR, "Could not locate NPC ID for pet item " + itemId);
return -1;
}
/**
* Gets the item id for this pet.
* @param stage The stage of the pet.
* @return The item id.
* Gets the next growth stage's item ID for this pet.
* @param itemId An int giving the current pet's item ID.
* @return The item ID for the next growth stage, or -1 if there isn't any (i.e. pet is already overgrown).
*/
public int getItemId(int stage) {
switch (stage) {
case 0:
return babyItemId;
case 1:
public int getNextStageItemId(int itemId) {
if (itemId == babyItemId) {
return grownItemId;
case 2:
}
if (itemId == grownItemId) {
return overgrownItemId;
}
return 0;
return -1;
}
}
@@ -866,6 +866,21 @@ public class Container {
return null;
}
/**
* Gets all instances of an item, and returns them.
* @author Player Name
* @param item the item.
* @return a list of all items that were found (can be length 0).
*/
public ArrayList<Item> getAll(Item item){
ArrayList<Item> ret = new ArrayList<Item>();
for(Item i : items){
if(i == null) continue;
if(item.getId() == i.getId()) ret.add(i);
}
return ret;
}
/**
* Gets the next free slot.
*
@@ -279,12 +279,11 @@ class PlayerSaver (val player: Player){
detail.put("petId",it.key.toString())
detail.put("hunger",it.value.hunger.toString())
detail.put("growth",it.value.growth.toString())
detail.put("stage",it.value.stage.toString())
petDetails.add(detail)
}
familiarManager.put("petDetails",petDetails)
if(player.familiarManager.hasPet()){
familiarManager.put("currentPet",(player.familiarManager.familiar as Pet).pet.babyItemId.toString())
familiarManager.put("currentPet",(player.familiarManager.familiar as Pet).getItemIdHash().toString())
} else if (player.familiarManager.hasFamiliar()){
val familiar = JSONObject()
familiar.put("originalId",player.familiarManager.familiar.originalId.toString())