diff --git a/ngengine_public.jar b/ngengine_public.jar index c5451df1..beacd257 100644 Binary files a/ngengine_public.jar and b/ngengine_public.jar differ diff --git a/scripts/mobiles/tatooine/bantha.py b/scripts/mobiles/tatooine/bantha.py index 19ee591f..43e6dbf7 100644 --- a/scripts/mobiles/tatooine/bantha.py +++ b/scripts/mobiles/tatooine/bantha.py @@ -12,6 +12,14 @@ def addTemplate(core): mobileTemplate.setAttackRange(5) mobileTemplate.setWeaponType(6) mobileTemplate.setAttackSpeed(1.0) + mobileTemplate.setMilkType('Wild Milk') + mobileTemplate.setMilkAmount(250) + mobileTemplate.setHideType('Wooly Hide') + mobileTemplate.setHideAmount(325) + mobileTemplate.setMeatType('Herbivore Meat') + mobileTemplate.setMeatAmount(450) + mobileTemplate.setBoneType('Animal Bones') + mobileTemplate.setBoneAmount(250) templates = Vector() templates.add('object/mobile/shared_bantha_hue.iff') diff --git a/scripts/radial/npc/corpse.py b/scripts/radial/npc/corpse.py index dc93d74a..28a63986 100644 --- a/scripts/radial/npc/corpse.py +++ b/scripts/radial/npc/corpse.py @@ -4,10 +4,23 @@ import sys def createRadial(core, owner, target, radials): radials.clear() radials.add(RadialOptions(0, 36, 0, 'Loot')) - + if target.getAttachment('AI') and core.resourceService.canHarvest(owner, target): + radials.add(RadialOptions(0, 163, 3, '@sui:harvest_corpse')) + radials.add(RadialOptions(2, 164, 3, '@sui:harvest_meat')) + radials.add(RadialOptions(2, 165, 3, '@sui:harvest_hide')) + radials.add(RadialOptions(2, 166, 3, '@sui:harvest_bone')) + + return def handleSelection(core, owner, target, option): + + if option == 164 and target.getAttachment('AI') and core.resourceService.canHarvest(owner, target): + core.resourceService.doHarvest(owner, target, 'meat') + if option == 165 and target.getAttachment('AI') and core.resourceService.canHarvest(owner, target): + core.resourceService.doHarvest(owner, target, 'hide') + if option == 166 and target.getAttachment('AI') and core.resourceService.canHarvest(owner, target): + core.resourceService.doHarvest(owner, target, 'bone') if option == 36 and target: #core.lootService.handleLootRequest(owner,target) core.lootService.handleLootRequest(owner,target) diff --git a/scripts/radial/npc/mobile.py b/scripts/radial/npc/mobile.py new file mode 100644 index 00000000..decba1d8 --- /dev/null +++ b/scripts/radial/npc/mobile.py @@ -0,0 +1,16 @@ +from resources.common import RadialOptions +import sys + +def createRadial(core, owner, target, radials): + radials.clear() + if target.getAttachment('AI') and core.resourceService.canMilk(owner, target): + radials.add(RadialOptions(0, 167, 3, '@pet/pet_menu:milk_me')) + + return + +def handleSelection(core, owner, target, option): + + if option == 167 and target.getAttachment('AI') and core.resourceService.canMilk(owner, target): + core.resourceService.doMilk(owner, target) + return + \ No newline at end of file diff --git a/src/resources/datatables/MilkState.java b/src/resources/datatables/MilkState.java new file mode 100644 index 00000000..002b6e7c --- /dev/null +++ b/src/resources/datatables/MilkState.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2013 + * + * This File is part of NGECore2. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + * + * Using NGEngine to work with NGECore2 is making a combined work based on NGEngine. + * Therefore all terms and conditions of the GNU Lesser General Public License cover the combination. + ******************************************************************************/ +package resources.datatables; + +public class MilkState { + public static final byte NOTYETMILKED = 0; + public static final byte MILKINGINPROGRESS = 1; + public static final byte MILKED = 2; +} diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index d724e44b..38668e6b 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -185,7 +185,7 @@ public class CreatureObject extends TangibleObject implements Serializable { @NotPersistent private transient ConcurrentHashMap cooldowns = new ConcurrentHashMap(); @NotPersistent - private transient long tefTime = System.currentTimeMillis(); + private transient long tefTime = 0; @NotPersistent private transient SWGObject useTarget; @@ -213,7 +213,6 @@ public class CreatureObject extends TangibleObject implements Serializable { duelList = Collections.synchronizedList(new ArrayList()); cooldowns = new ConcurrentHashMap(); performanceAudience = new Vector(); - tefTime = System.currentTimeMillis(); messageBuilder = new CreatureMessageBuilder(this); } diff --git a/src/services/SurveyService.java b/src/services/SurveyService.java index 39b75519..a2e3cdb5 100644 --- a/src/services/SurveyService.java +++ b/src/services/SurveyService.java @@ -174,7 +174,7 @@ public class SurveyService implements INetworkDispatch { containerObject.initializeStats(sampleResource); containerObject.setProprietor(crafter); SWGObject crafterInventory = crafter.getSlottedObject("inventory"); - container.setStackCount(stackCount,crafter); + containerObject.setStackCount(stackCount,crafter); crafterInventory.add(containerObject); player.setRecentContainer(containerObject); } diff --git a/src/services/ai/AIActor.java b/src/services/ai/AIActor.java index 99363374..87745fe7 100644 --- a/src/services/ai/AIActor.java +++ b/src/services/ai/AIActor.java @@ -64,6 +64,8 @@ public class AIActor { private ScheduledFuture regenTask; private ScheduledFuture aggroCheckTask; private boolean isStalking = false; + private byte milkState = 0; + private boolean hasBeenHarvested = false; public AIActor(CreatureObject creature, Point3D spawnPosition, ScheduledExecutorService scheduler) { this.creature = creature; @@ -109,18 +111,25 @@ public class AIActor { public void setSpawnPosition(Point3D spawnPosition) { this.spawnPosition = spawnPosition; } - + public void addDefender(CreatureObject defender) { + addDefender(defender, false); + } + + + public void addDefender(CreatureObject defender, boolean isAssisting) { creature.addDefender(defender); if(followObject == null) setFollowObject(defender); setCurrentState(new AttackState()); - NGECore.getInstance().simulationService.get(creature.getPlanet(), creature.getWorldPosition().x, creature.getWorldPosition().z, 30).stream().filter((obj) -> - obj instanceof CreatureObject && - obj.getAttachment("AI") != null && - ((AIActor) obj.getAttachment("AI")).getMobileTemplate().getSocialGroup().equals(getMobileTemplate().getSocialGroup()) && - obj.inRange(creature.getWorldPosition(), ((AIActor) obj.getAttachment("AI")).getMobileTemplate().getAssistRange()) - ).forEach((obj) -> ((AIActor) obj.getAttachment("AI")).addDefender(defender)); + if(!isAssisting) { + NGECore.getInstance().simulationService.get(creature.getPlanet(), creature.getWorldPosition().x, creature.getWorldPosition().z, 30).stream().filter((obj) -> + obj instanceof CreatureObject && + obj.getAttachment("AI") != null && + ((AIActor) obj.getAttachment("AI")).getMobileTemplate().getSocialGroup().equals(getMobileTemplate().getSocialGroup()) && + obj.inRange(creature.getWorldPosition(), ((AIActor) obj.getAttachment("AI")).getMobileTemplate().getAssistRange()) + ).forEach((obj) -> ((AIActor) obj.getAttachment("AI")).addDefender(defender, true)); + } } public void removeDefender(CreatureObject defender) { @@ -284,6 +293,7 @@ public class AIActor { public void scheduleDespawn() { scheduler.schedule(() -> { + aggroCheckTask.cancel(true); regenTask.cancel(true); damageMap.clear(); followObject = null; @@ -308,5 +318,29 @@ public class AIActor { public void setStalking(boolean isStalking) { this.isStalking = isStalking; } + + public byte getMilkState() { + synchronized(creature.getMutex()) { + return milkState; + } + } + + public void setMilkState(byte milkState) { + synchronized(creature.getMutex()) { + this.milkState = milkState; + } + } + + public boolean hasBeenHarvested() { + synchronized(creature.getMutex()) { + return hasBeenHarvested; + } + } + + public void setHasBeenHarvested(boolean hasBeenHarvested) { + synchronized(creature.getMutex()) { + this.hasBeenHarvested = hasBeenHarvested; + } + } } diff --git a/src/services/resources/ResourceService.java b/src/services/resources/ResourceService.java index d6719c0b..09d9c9c5 100644 --- a/src/services/resources/ResourceService.java +++ b/src/services/resources/ResourceService.java @@ -28,6 +28,7 @@ import java.util.Random; import java.util.Vector; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; import com.sleepycat.persist.EntityCursor; @@ -40,11 +41,15 @@ import engine.resources.scene.Point3D; import engine.resources.scene.Quaternion; import engine.resources.service.INetworkDispatch; import engine.resources.service.INetworkRemoteEvent; +import resources.common.OutOfBand; +import resources.common.ProsePackage; +import resources.datatables.MilkState; import resources.objects.creature.CreatureObject; import resources.objects.harvester.HarvesterObject; import resources.objects.resource.GalacticResource; import resources.objects.resource.ResourceContainerObject; import resources.objects.resource.ResourceRoot; +import services.ai.AIActor; /** * @author Charon @@ -122,7 +127,8 @@ public class ResourceService implements INetworkDispatch { createCollections3(); } // } - + core.commandService.registerCommand("harvestcorpse"); + core.commandService.registerCommand("milkcreature"); core.commandService.registerCommand("resourcecontainersplit"); core.commandService.registerCommand("resourcecontainertransfer"); core.commandService.registerCommand("factorycratesplit"); @@ -7244,7 +7250,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_corellia"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Corellian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7260,7 +7266,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_dantooine"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Dantooine"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7275,7 +7281,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_dathomir"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Dathomirian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7290,7 +7296,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_endor"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Endorian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7305,7 +7311,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_lok"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Lokian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7320,7 +7326,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_naboo"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Nabooian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7335,7 +7341,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_rori"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Rori"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7350,7 +7356,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_talus"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Talusian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7365,7 +7371,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_tatooine"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Tatooinian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -7380,7 +7386,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_yavin4"); - resourceRoot.setResourceClass("Canivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Yavinian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -9324,7 +9330,7 @@ public class ResourceService implements INetworkDispatch { resourceRoot = new ResourceRoot(); resourceRoot.setResourceFileName("meat_carnivore_kashyyyk"); - resourceRoot.setResourceClass("Herbivore Meat"); + resourceRoot.setResourceClass("Carnivore Meat"); resourceRoot.setResourceType("Kashyyykian"); resourceRoot.setgeneralType((byte) GalacticResource.GENERAL_MEAT); resourceRoot.setContainerType((byte) ResourceRoot.CONTAINER_TYPE_ORGANIC_FOOD); @@ -11429,28 +11435,216 @@ public class ResourceService implements INetworkDispatch { } // Utility method to quickly spawn resource containers into the inventory - public ResourceContainerObject spawnSpecificResourceContainer(String spawnType, CreatureObject crafter,int stackCount){ - ResourceContainerObject containerObject = null; - for (GalacticResource sampleResource : allSpawnedResources){ - if (sampleResource.getResourceRoot().getResourceClass().contains(spawnType)){ - String resourceContainerIFF = ResourceRoot.CONTAINER_TYPE_IFF_SIGNIFIER[sampleResource.getResourceRoot().getContainerType()]; - containerObject = (ResourceContainerObject) core.objectService.createObject(resourceContainerIFF, crafter.getPlanet()); - containerObject.setProprietor(crafter); - containerObject.setStackCount(stackCount,false); - //int stackCount = core.resourceService.getResourceSampleQuantity(crafter, sampleResource); - containerObject.initializeStats(sampleResource); - int resCRC = CRC.StringtoCRC(resourceContainerIFF); - containerObject.setIffFileName(resourceContainerIFF); - long objectId = containerObject.getObjectID(); - SWGObject crafterInventory = crafter.getSlottedObject("inventory"); - crafterInventory.add(containerObject); - return containerObject; - } + public ResourceContainerObject spawnSpecificResourceContainer(String spawnType, CreatureObject crafter,int stackCount){ + ResourceContainerObject containerObject = null; + for (GalacticResource sampleResource : allSpawnedResources){ + if (sampleResource.getResourceRoot().getResourceClass().contains(spawnType)){ + String resourceContainerIFF = ResourceRoot.CONTAINER_TYPE_IFF_SIGNIFIER[sampleResource.getResourceRoot().getContainerType()]; + containerObject = (ResourceContainerObject) core.objectService.createObject(resourceContainerIFF, crafter.getPlanet()); + containerObject.setProprietor(crafter); + containerObject.setStackCount(stackCount,false); + //int stackCount = core.resourceService.getResourceSampleQuantity(crafter, sampleResource); + containerObject.initializeStats(sampleResource); + int resCRC = CRC.StringtoCRC(resourceContainerIFF); + containerObject.setIffFileName(resourceContainerIFF); + long objectId = containerObject.getObjectID(); + SWGObject crafterInventory = crafter.getSlottedObject("inventory"); + crafterInventory.add(containerObject); + return containerObject; } - return containerObject; + } + return containerObject; + } + + public void giveResource(CreatureObject actor, GalacticResource res, int amount) { + + ResourceContainerObject foundContainer = core.surveyService.findResourceContainerInInventory(actor, res); + + if(foundContainer != null && amount < ResourceContainerObject.maximalStackCapacity - foundContainer.getStackCount()) { + foundContainer.setStackCount(foundContainer.getStackCount() + amount, actor); + } else { + SWGObject inventory = actor.getSlottedObject("inventory"); + String resourceContainerIFF = ResourceRoot.CONTAINER_TYPE_IFF_SIGNIFIER[res.getResourceRoot().getContainerType()]; + ResourceContainerObject containerObject = (ResourceContainerObject) core.objectService.createObject(resourceContainerIFF, actor.getPlanet()); + containerObject.initializeStats(res); + containerObject.setProprietor(actor); + containerObject.setStackCount(amount, actor); + inventory.add(containerObject); } - public Vector getCompleteResourceNameHistory() { - return completeResourceNameHistory; + } + + public boolean canMilk(CreatureObject actor, CreatureObject target) { + + if(target.getPosture() == 14 || !actor.inRange(target.getWorldPosition(), 5) || actor.getCombatFlag() == 1 || target.getCombatFlag() == 1) + return false; + + AIActor ai = (AIActor) target.getAttachment("AI"); + + if(ai.getMobileTemplate().getMilkAmount() <= 0 || ai.getMobileTemplate().getMilkType() == null || ai.getMilkState() == MilkState.MILKED || ai.getMilkState() == MilkState.MILKINGINPROGRESS) + return false; + + return true; + + } + + public boolean canHarvest(CreatureObject actor, CreatureObject target) { + + if(target.getPosture() != 14) + return false; + + AIActor ai = (AIActor) target.getAttachment("AI"); + + if(ai.getMobileTemplate().getMeatAmount() <= 0 && ai.getMobileTemplate().getBoneAmount() <= 0 && ai.getMobileTemplate().getHideAmount() <= 0) + return false; + + if(target.getKiller() != actor && !(actor.getGroupId() == target.getGroupId() && actor.getGroupId() != 0)) + return false; + + return true; + + } + + public void doHarvest(CreatureObject actor, CreatureObject target, String type) { + + AIActor ai = (AIActor) target.getAttachment("AI"); + + if(!actor.inRange(target.getWorldPosition(), 7)) { + actor.sendSystemMessage("You are too far away to harvest the creature.", (byte) 0); + return; } + + if(ai.hasBeenHarvested()) { + actor.sendSystemMessage("@skl_use:nothing_to_harvest", (byte) 0); + return; + } + + ai.setHasBeenHarvested(true); + + String resType = ""; + int resAmount = 0; + + switch(type) { + + case "hide": + resType = ai.getMobileTemplate().getHideType(); + resAmount = ai.getMobileTemplate().getHideAmount(); + break; + case "meat": + resType = ai.getMobileTemplate().getMeatType(); + resAmount = ai.getMobileTemplate().getMeatAmount(); + break; + case "bone": + resType = ai.getMobileTemplate().getBoneType(); + resAmount = ai.getMobileTemplate().getBoneAmount(); + break; + + } + + resAmount += (resAmount * (actor.getSkillModBase("creature_harvesting") / 100)); + GalacticResource res = grabResourceByClass(resType, target.getPlanetId()); + + if(res == null) { + actor.sendSystemMessage("@skl_use:nothing_to_harvest", (byte) 0); + ai.setHasBeenHarvested(false); + return; + } + + float density = res.deliverConcentrationForSurvey(target.getPlanetId(), target.getWorldPosition().x, target.getWorldPosition().z); + + if(density >= 0.8f) { + resAmount *= 1.25f; + } else if(density >= 0.6f) { + resAmount *= 1.f; + } else if(density >= 0.4f) { + resAmount *= 0.75f; + } else { + resAmount *= 0.5f; + } + + giveResource(actor, res, resAmount); + actor.sendSystemMessage("@skl_use:corpse_harvest_success", (byte) 0); + + } + + public void doMilk(CreatureObject actor, CreatureObject target) { + + AIActor ai = (AIActor) target.getAttachment("AI"); + ai.setMilkState(MilkState.MILKINGINPROGRESS); + actor.sendSystemMessage("@skl_use:milk_begin", (byte) 0); + + scheduler.schedule(() -> { + + if(actor.getInventoryItemCount() >= 80) { + actor.sendSystemMessage("@skl_use:milk_inventory_full", (byte) 0); + ai.setMilkState(MilkState.NOTYETMILKED); + return; + } + + if(target.getPosture() == 14) { + actor.sendSystemMessage("@skl_use:milk_cant_milk_the_dead", (byte) 0); + ai.setMilkState(MilkState.NOTYETMILKED); + return; + } + + if(!actor.inRange(target.getWorldPosition(), 5)) { + actor.sendSystemMessage("@skl_use:milk_too_far", (byte) 0); + ai.setMilkState(MilkState.NOTYETMILKED); + return; + } + + if(actor.getCombatFlag() == 1) { + actor.sendSystemMessage("@skl_use:milk_combat", (byte) 0); + ai.setMilkState(MilkState.NOTYETMILKED); + return; + } + + if(new Random().nextFloat() <= 0.05f) { + actor.sendSystemMessage("@skl_use:milk_not_hidden", (byte) 0); + ai.setMilkState(MilkState.NOTYETMILKED); + ai.addDefender(actor); + return; + } + + giveMilk(actor, target); + + }, 10000, TimeUnit.MILLISECONDS); + + } + + public void giveMilk(CreatureObject actor, CreatureObject target) { + + AIActor ai = (AIActor) target.getAttachment("AI"); + String milkType = ai.getMobileTemplate().getMilkType(); + int milkAmount = ai.getMobileTemplate().getMilkAmount(); + + GalacticResource res = grabResourceByClass(milkType, target.getPlanetId()); + + if(res == null) { + actor.sendSystemMessage("Can't find milk resource.", (byte) 0); + ai.setMilkState(MilkState.NOTYETMILKED); + return; + } + + float density = res.deliverConcentrationForSurvey(target.getPlanetId(), target.getWorldPosition().x, target.getWorldPosition().z); + + if(density >= 0.8f) { + milkAmount *= 1.25f; + } else if(density >= 0.6f) { + milkAmount *= 1.f; + } else if(density >= 0.4f) { + milkAmount *= 0.75f; + } else { + milkAmount *= 0.5f; + } + + giveResource(actor, res, milkAmount); + ai.setMilkState(MilkState.MILKED); + actor.sendSystemMessage("@skl_use:milk_success", (byte) 0); + + } + + public Vector getCompleteResourceNameHistory() { + return completeResourceNameHistory; + } } diff --git a/src/services/spawn/MobileTemplate.java b/src/services/spawn/MobileTemplate.java index 61098040..564a2be4 100644 --- a/src/services/spawn/MobileTemplate.java +++ b/src/services/spawn/MobileTemplate.java @@ -51,9 +51,11 @@ public class MobileTemplate { private int minSpawnDistance = 0; private int maxSpawnDistance = 0; private boolean deathblow = false; - private String socialGroup; // see prima guide + private String socialGroup = ""; // see prima guide private int assistRange; // use prima guide for ranges private boolean isStalker = false; + private String meatType, milkType, boneType, hideType; + private int meatAmount, milkAmount, boneAmount, hideAmount; public Vector getTemplates() { return templates; @@ -262,4 +264,68 @@ public class MobileTemplate { public void setStalker(boolean isStalker) { this.isStalker = isStalker; } + + public String getMeatType() { + return meatType; + } + + public void setMeatType(String meatType) { + this.meatType = meatType; + } + + public String getMilkType() { + return milkType; + } + + public void setMilkType(String milkType) { + this.milkType = milkType; + } + + public String getBoneType() { + return boneType; + } + + public void setBoneType(String boneType) { + this.boneType = boneType; + } + + public String getHideType() { + return hideType; + } + + public void setHideType(String hideType) { + this.hideType = hideType; + } + + public int getMeatAmount() { + return meatAmount; + } + + public void setMeatAmount(int meatAmount) { + this.meatAmount = meatAmount; + } + + public int getMilkAmount() { + return milkAmount; + } + + public void setMilkAmount(int milkAmount) { + this.milkAmount = milkAmount; + } + + public int getBoneAmount() { + return boneAmount; + } + + public void setBoneAmount(int boneAmount) { + this.boneAmount = boneAmount; + } + + public int getHideAmount() { + return hideAmount; + } + + public void setHideAmount(int hideAmount) { + this.hideAmount = hideAmount; + } } diff --git a/src/services/spawn/SpawnService.java b/src/services/spawn/SpawnService.java index 4008156d..26336387 100644 --- a/src/services/spawn/SpawnService.java +++ b/src/services/spawn/SpawnService.java @@ -197,6 +197,7 @@ public class SpawnService { AIActor actor = new AIActor(creature, creature.getPosition(), scheduler); creature.setAttachment("AI", actor); + creature.setAttachment("radial_filename", "npc/mobile"); actor.setMobileTemplate(mobileTemplate);