From fbb8331b15b2018dbf691b5f99f752c38fae6e1f Mon Sep 17 00:00:00 2001 From: dennise1975 Date: Mon, 26 Jun 2017 19:46:34 -0500 Subject: [PATCH] Added Standard Skillmod Functionality (Luck, Const, Stam...) --- .../object/ContainerTransferIntent.java | 14 +- .../player/CreatedCharacterIntent.java | 52 ++++ src/resources/objects/SWGObject.java | 2 +- .../objects/creature/CreatureObject.java | 4 + .../experience/ExperienceManager.java | 44 +-- src/services/galaxy/SkillModService.java | 280 +++++++++++++++++- .../player/CharacterCreationService.java | 5 +- .../awareness/TestObjectAwareness.java | 4 +- 8 files changed, 358 insertions(+), 47 deletions(-) create mode 100644 src/intents/player/CreatedCharacterIntent.java diff --git a/src/intents/object/ContainerTransferIntent.java b/src/intents/object/ContainerTransferIntent.java index c7dba0797..0f462ff1b 100644 --- a/src/intents/object/ContainerTransferIntent.java +++ b/src/intents/object/ContainerTransferIntent.java @@ -35,13 +35,15 @@ public class ContainerTransferIntent extends Intent { private SWGObject obj; private SWGObject container; + private SWGObject oldContainer; public ContainerTransferIntent() { - this(null, null); + this(null, null, null); } - public ContainerTransferIntent(SWGObject obj, SWGObject container) { + public ContainerTransferIntent(SWGObject obj, SWGObject oldContainer,SWGObject container) { setObject(obj); + setOldContainer(oldContainer); setContainer(container); } @@ -61,4 +63,12 @@ public class ContainerTransferIntent extends Intent { this.container = container; } + public SWGObject getOldContainer() { + return oldContainer; + } + + public void setOldContainer(SWGObject oldContainer) { + this.oldContainer = oldContainer; + } + } diff --git a/src/intents/player/CreatedCharacterIntent.java b/src/intents/player/CreatedCharacterIntent.java new file mode 100644 index 000000000..95448c62a --- /dev/null +++ b/src/intents/player/CreatedCharacterIntent.java @@ -0,0 +1,52 @@ +/*********************************************************************************** +* Copyright (c) 2015 /// Project SWG /// www.projectswg.com * +* * +* ProjectSWG is the first NGE emulator for Star Wars Galaxies founded on * +* July 7th, 2011 after SOE announced the official shutdown of Star Wars Galaxies. * +* Our goal is to create an emulator which will provide a server for players to * +* continue playing a game similar to the one they used to play. We are basing * +* it on the final publish of the game prior to end-game events. * +* * +* This file is part of Holocore. * +* * +* -------------------------------------------------------------------------------- * +* * +* Holocore is free software: you can redistribute it and/or modify * +* it under the terms of the GNU Affero General Public License as * +* published by the Free Software Foundation, either version 3 of the * +* License, or (at your option) any later version. * +* * +* Holocore 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 Affero General Public License for more details. * +* * +* You should have received a copy of the GNU Affero General Public License * +* along with Holocore. If not, see . * +* * +***********************************************************************************/ +package intents.player; + +import com.projectswg.common.control.Intent; + +import resources.objects.creature.CreatureObject; + +public class CreatedCharacterIntent extends Intent { + + private CreatureObject creatureObject; + + + public CreatedCharacterIntent(CreatureObject creatureObject) { + setCreatureObject(creatureObject); + } + + + public CreatureObject getCreatureObject(){ + return this.creatureObject; + } + + public void setCreatureObject(CreatureObject creatureObject){ + this.creatureObject = creatureObject; + } + +} diff --git a/src/resources/objects/SWGObject.java b/src/resources/objects/SWGObject.java index 35fe71e34..8bb33d16d 100644 --- a/src/resources/objects/SWGObject.java +++ b/src/resources/objects/SWGObject.java @@ -198,7 +198,7 @@ public abstract class SWGObject extends BaselineObject implements Comparable createObject(observer)); AwarenessUtilities.callForOldObserver(oldObservers, newObservers, (observer) -> destroyObject(observer)); if (parent != container) - new ContainerTransferIntent(this, container).broadcast(); + new ContainerTransferIntent(this, parent, container).broadcast(); return ContainerResult.SUCCESS; } diff --git a/src/resources/objects/creature/CreatureObject.java b/src/resources/objects/creature/CreatureObject.java index 3e41c74e7..70242f5fe 100644 --- a/src/resources/objects/creature/CreatureObject.java +++ b/src/resources/objects/creature/CreatureObject.java @@ -152,6 +152,10 @@ public class CreatureObject extends TangibleObject { return Collections.unmodifiableSet(skills); } + public void handleLevelSkillMods(String modName, int modValue){ + adjustSkillmod(modName, 0, modValue); + } + public int getCashBalance() { return cashBalance; } diff --git a/src/services/experience/ExperienceManager.java b/src/services/experience/ExperienceManager.java index 08568d04c..747b8f4f2 100644 --- a/src/services/experience/ExperienceManager.java +++ b/src/services/experience/ExperienceManager.java @@ -60,18 +60,17 @@ public final class ExperienceManager extends Manager { private final SkillTemplateService skillTemplateService; private final Map levelXpMap; private final double xpMultiplier; - + public ExperienceManager() { skillManager = new SkillManager(); skillTemplateService = new SkillTemplateService(); levelXpMap = new HashMap<>(); xpMultiplier = DataManager.getConfig(ConfigFile.FEATURES).getDouble("XP-MULTIPLIER", 1); - registerForIntent(ExperienceIntent.class, ei -> handleExperienceIntent(ei)); - addChildService(skillManager); addChildService(skillTemplateService); - } + +} @Override public boolean initialize() { @@ -84,12 +83,15 @@ public final class ExperienceManager extends Manager { levelXpMap.put((short) level, xpRequired); } + registerForIntent(ExperienceIntent.class, ei -> handleExperienceIntent(ei)); + return super.initialize(); } private void handleExperienceIntent(ExperienceIntent ei) { CreatureObject creatureObject = ei.getCreatureObject(); PlayerObject playerObject = creatureObject.getPlayerObject(); + if (playerObject != null) { int newXpTotal = awardExperience(creatureObject, playerObject, ei.getXpType(), ei.getExperienceGained()); @@ -98,10 +100,8 @@ public final class ExperienceManager extends Manager { short newLevel = attemptLevelUp(creatureObject.getLevel(), creatureObject, newXpTotal); if (oldLevel < newLevel) { // If we've leveled up at least once - new LevelChangedIntent(creatureObject, oldLevel, newLevel).broadcast(); creatureObject.setLevel(newLevel); - adjustHealth(creatureObject, newLevel); - adjustAction(creatureObject, newLevel); + new LevelChangedIntent(creatureObject, oldLevel, newLevel).broadcast(); // TODO NGE: system message health and action differences. @spam:level_up_stat_gain_# Log.i("%s leveled from %d to %d", creatureObject, oldLevel, newLevel); } @@ -147,37 +147,7 @@ public final class ExperienceManager extends Manager { return newXpTotal >= xpNextLevel ? attemptLevelUp(nextLevel, creatureObject, newXpTotal) : currentLevel; } - private void adjustHealth(CreatureObject creatureObject, short newLevel) { - int currentLevelHealthGranted = creatureObject.getLevelHealthGranted(); // The existing levelHealthGranted - int newLevelHealthGranted = 100 * newLevel; // new levelHealthGranted - int difference = newLevelHealthGranted - currentLevelHealthGranted; - // Set new levelHealthGranted - creatureObject.setLevelHealthGranted(newLevelHealthGranted); - - // Add the difference to their max health - int newMaxHealth = creatureObject.getMaxHealth() + difference; - creatureObject.setMaxHealth(newMaxHealth); - - // Give them full health - creatureObject.setBaseHealth(newMaxHealth); - creatureObject.setHealth(newMaxHealth); - } - - private void adjustAction(CreatureObject creatureObject, short newLevel) { - int currentMaxAction = creatureObject.getMaxAction(); - int newLevelActionGranted = 75 * newLevel; - int difference = newLevelActionGranted - currentMaxAction; - - // Add the difference to their max action - int newMaxAction = currentMaxAction + difference; - creatureObject.setMaxAction(newMaxAction); - - // Give them full action - creatureObject.setBaseAction(newMaxAction); - creatureObject.setAction(newMaxAction); - } - private int getMaxLevel() { return levelXpMap.size(); } diff --git a/src/services/galaxy/SkillModService.java b/src/services/galaxy/SkillModService.java index 1640bd946..3cf369fd9 100644 --- a/src/services/galaxy/SkillModService.java +++ b/src/services/galaxy/SkillModService.java @@ -27,24 +27,300 @@ ***********************************************************************************/ package services.galaxy; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + import com.projectswg.common.control.Service; +import com.projectswg.common.data.info.RelationalServerData; +import com.projectswg.common.data.info.RelationalServerFactory; +import com.projectswg.common.debug.Log; import intents.SkillModIntent; +import intents.player.CreatedCharacterIntent; +import intents.experience.LevelChangedIntent; +import intents.object.ContainerTransferIntent; import resources.objects.creature.CreatureObject; +import resources.objects.player.PlayerObject; +import resources.player.Player; +import utilities.IntentFactory; public class SkillModService extends Service { + + private static final String GET_PLAYER_LEVELS_SQL = "SELECT * FROM player_levels where combat_level = ?"; + private RelationalServerData playerLevelDatabase; + private PreparedStatement getPlayerLevelStatement; + + private static final String GET_RACIAL_STATS_SQL = "SELECT * FROM racial_stats where level = ?"; + private RelationalServerData racialStatsDatabase; + private PreparedStatement getRacialStatsStatement; + + private static int HEALTH_POINTS_PER_STAMINA = 2; + private static int HEALTH_POINTS_PER_CONSTITUTION = 8; + + private static int ACTION_POINTS_PER_STAMINA = 8; + private static int ACTION_POINTS_PER_CONSTITUTION = 2; public SkillModService() { + + playerLevelDatabase = RelationalServerFactory.getServerData("player/player_levels.db", "player_levels"); + if (playerLevelDatabase == null) + throw new main.ProjectSWG.CoreException("Unable to load player_levels.sdb file for SkillTemplateService"); + + getPlayerLevelStatement = playerLevelDatabase.prepareStatement(GET_PLAYER_LEVELS_SQL); + + racialStatsDatabase = RelationalServerFactory.getServerData("player/racial_stats.db", "racial_stats"); + if (racialStatsDatabase == null) + throw new main.ProjectSWG.CoreException("Unable to load racial_stats.sdb file for SkillTemplateService"); + + getRacialStatsStatement = racialStatsDatabase.prepareStatement(GET_RACIAL_STATS_SQL); + + registerForIntent(ContainerTransferIntent.class, cti -> handleContainerTransferIntent(cti)); + registerForIntent(LevelChangedIntent.class, lci -> handleLevelChangedIntent(lci)); + registerForIntent(CreatedCharacterIntent.class, cci -> handleCreatedCharacterIntent(cci)); registerForIntent(SkillModIntent.class, smi -> handleSkillModIntent(smi)); } + + private void handleContainerTransferIntent(ContainerTransferIntent cti){ + + if(cti.getObject().getOwner() != null){ + CreatureObject creature = cti.getObject().getOwner().getCreatureObject(); + String objAttributes = cti.getObject().getAttributes().toString(); + String[] modStrings = objAttributes.split(","); + + for(String modString : modStrings) { + String[] splitValues = modString.split("="); + String modName = splitValues[0]; + String modValue = splitValues[1].replace("}", ""); + + if(modName.endsWith("_modified")) { + String[] splitModName = modName.split(":"); + modName = splitModName[1]; + + if(cti.getContainer().getObjectId() == creature.getObjectId()){ + creature.adjustSkillmod(modName, 0, Integer.parseInt(modValue)); + updateSkillModHamValues(creature, modName,Integer.parseInt(modValue)); + }else if(cti.getOldContainer() != null){ + if(cti.getOldContainer().getObjectId() == creature.getObjectId()){ + creature.adjustSkillmod(modName, 0, -Integer.parseInt(modValue)); + updateSkillModHamValues(creature, modName, -Integer.parseInt(modValue)); + } + } + } + } + } + } + + private void handleCreatedCharacterIntent(CreatedCharacterIntent cci){ + CreatureObject creature = cci.getCreatureObject(); + PlayerObject playerObject = creature.getPlayerObject(); + String profession = playerObject.getProfession().substring(0, playerObject.getProfession().length()-3); + String race = creature.getRace().toString().substring(0, 3); + int newLevel = creature.getLevel(); + + updateLevelHAMValues(creature, newLevel, profession); + updateLevelSkillModValues(creature, newLevel, profession, race); + + } + + private void handleLevelChangedIntent(LevelChangedIntent lci){ + CreatureObject creature = lci.getCreatureObject(); + PlayerObject playerObject = creature.getPlayerObject(); + String profession = playerObject.getProfession().substring(0, playerObject.getProfession().length()-3); + String race = creature.getRace().toString().substring(0, 3); + int newLevel = lci.getNewLevel(); + + updateLevelHAMValues(creature, newLevel, profession); + updateLevelSkillModValues(creature, newLevel, profession, race); + + } private void handleSkillModIntent(SkillModIntent smi) { for (CreatureObject creature : smi.getAffectedCreatures()) { - int adjustBase = smi.getAdjustBase(); int adjustModifier = smi.getAdjustModifier(); String skillModName = smi.getSkillModName(); - creature.adjustSkillmod(skillModName, adjustBase, adjustModifier); + creature.handleLevelSkillMods(skillModName, adjustModifier); + updateSkillModHamValues(creature, skillModName,adjustModifier); } } + + private void updateLevelHAMValues(CreatureObject creature, int level, String profession){ + int intNewHealth = getLevelSkillModValue(level, profession + "_health", "") - creature.getBaseHealth(); + int intNewAction = getLevelSkillModValue(level, profession + "_action", "") - creature.getBaseAction(); + + creature.setMaxHealth(creature.getMaxHealth() + intNewHealth); + creature.setHealth(creature.getMaxHealth()); + creature.setBaseHealth(getLevelSkillModValue(level, profession + "_health", "")); + + creature.setMaxAction(creature.getMaxAction() + intNewAction); + creature.setAction(creature.getMaxAction()); + creature.setBaseAction(getLevelSkillModValue(level, profession + "_action", "")); + + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_6", "DI", intNewHealth); + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_7", "DI", intNewAction); + } + + private void updateSkillModHamValues(CreatureObject creature, String skillModName, int modifer){ + int intHealth = 0; + int intAction = 0; + + if(skillModName.equals("constitution_modified")){ + intHealth = HEALTH_POINTS_PER_CONSTITUTION * modifer; + }else if (skillModName.equals("stamina_modified")){ + intHealth = HEALTH_POINTS_PER_STAMINA * modifer; + } + + if(skillModName.equals("constitution_modified")){ + intAction = ACTION_POINTS_PER_CONSTITUTION * modifer; + }else if (skillModName.equals("stamina_modified")){ + intAction = ACTION_POINTS_PER_STAMINA * modifer; + } + + if (intHealth > 0){ + creature.setMaxHealth(creature.getMaxHealth() + intHealth); + creature.setHealth(creature.getMaxHealth()); + } + + if (intAction > 0){ + creature.setMaxAction(creature.getMaxAction() + intAction); + creature.setAction(creature.getMaxAction()); + } + + } + + private void updateLevelSkillModValues(CreatureObject creature, int level, String profession, String race){ + int oldSkillModValue = 0; + int skillModValue = 0; + + if (level < 1 || level > 90){ + return; + } + + skillModValue = getLevelSkillModValue(level, profession + "_luck", race + "_LCK"); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("luck_modified"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("luck_modified", -creature.getSkillModValue("luck_modified")); + creature.handleLevelSkillMods("luck_modified", skillModValue); + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_0", "DI", skillModValue - oldSkillModValue); + } + } + + skillModValue = getLevelSkillModValue(level, profession + "_precision", race + "_PRE"); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("precision_modified"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("precision_modified", -creature.getSkillModValue("precision_modified")); + creature.handleLevelSkillMods("precision_modified", skillModValue); + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_1", "DI", skillModValue - oldSkillModValue); + } + } + + skillModValue = getLevelSkillModValue(level, profession + "_strength", race + "_STR"); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("strength_modified"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("strength_modified", -creature.getSkillModValue("strength_modified")); + creature.handleLevelSkillMods("strength_modified", skillModValue); + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_2", "DI", skillModValue - oldSkillModValue); + } + } + + skillModValue = getLevelSkillModValue(level, profession + "_constitution", race + "_CON"); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("constitution_modified"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("constitution_modified", -creature.getSkillModValue("constitution_modified")); + creature.handleLevelSkillMods("constitution_modified", skillModValue); + updateSkillModHamValues(creature, "constitution_modified",skillModValue - oldSkillModValue); + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_3", "DI", skillModValue - oldSkillModValue); + } + } + + skillModValue = getLevelSkillModValue(level, profession + "_stamina", race + "_STA"); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("stamina_modified"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("stamina_modified", -creature.getSkillModValue("stamina_modified")); + creature.handleLevelSkillMods("stamina_modified", skillModValue); + updateSkillModHamValues(creature, "stamina_modified",skillModValue - oldSkillModValue); + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_4", "DI", skillModValue - oldSkillModValue); + } + } + + skillModValue = getLevelSkillModValue(level, profession + "_agility", race + "_AGI"); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("agility_modified"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("agility_modified", -creature.getSkillModValue("agility_modified")); + creature.handleLevelSkillMods("agility_modified", skillModValue); + sendSystemMessage(creature.getOwner(), "level_up_stat_gain_5", "DI", skillModValue - oldSkillModValue); + } + } + + skillModValue = getLevelSkillModValue(level, profession + "_health_regen", ""); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("health_regen"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("health_regen", -creature.getSkillModValue("health_regen")); + creature.handleLevelSkillMods("health_regen", skillModValue); + } + } + + skillModValue = getLevelSkillModValue(level, profession + "_action_regen", ""); + if (skillModValue > 0){ + oldSkillModValue = creature.getSkillModValue("action_regen"); + if (skillModValue > oldSkillModValue){ + creature.handleLevelSkillMods("action_regen", -creature.getSkillModValue("action_regen")); + creature.handleLevelSkillMods("action_regen", skillModValue); + } + } + + Log.i("Health Regen: %s Action Regen: %s", creature.getSkillModValue("health_regen"), creature.getSkillModValue("action_regen")); + + } + + private int getLevelSkillModValue(int level, String professionModName, String raceModName){ + int skillModValue = 0; + + if(!professionModName.isEmpty()){ + synchronized (getPlayerLevelStatement) { + try { + getPlayerLevelStatement.setString(1, String.valueOf(level)); + + try (ResultSet set = getPlayerLevelStatement.executeQuery()) { + if (set.next()) + skillModValue += set.getInt(professionModName); + } + } catch (SQLException e) { + Log.e(e); + } + } + } + + if(!raceModName.isEmpty()){ + synchronized (getRacialStatsStatement) { + try { + getRacialStatsStatement.setString(1, String.valueOf(level)); + + try (ResultSet set = getRacialStatsStatement.executeQuery()) { + if (set.next()) + skillModValue += set.getInt(raceModName); + } + } catch (SQLException e) { + Log.e(e); + } + } + } + + return skillModValue; + + } + + private void sendSystemMessage(Player target, String id, Object... objects) { + if (target != null){ + IntentFactory.sendSystemMessage(target, "@spam:" + id, objects); + } + } } \ No newline at end of file diff --git a/src/services/player/CharacterCreationService.java b/src/services/player/CharacterCreationService.java index 28f056850..e4d1c7ea2 100644 --- a/src/services/player/CharacterCreationService.java +++ b/src/services/player/CharacterCreationService.java @@ -45,8 +45,8 @@ import com.projectswg.common.debug.Assert; import com.projectswg.common.debug.Log; import intents.GalacticIntent; -import intents.PlayerEventIntent; import intents.object.DestroyObjectIntent; +import intents.player.CreatedCharacterIntent; import network.packets.Packet; import network.packets.swg.login.creation.ClientCreateCharacter; import network.packets.swg.login.creation.ClientVerifyAndLockNameRequest; @@ -62,7 +62,6 @@ import resources.config.ConfigFile; import resources.objects.creature.CreatureObject; import resources.player.AccessLevel; import resources.player.Player; -import resources.player.PlayerEvent; import resources.player.PlayerState; import resources.server_info.DataManager; import resources.zone.NameFilter; @@ -203,7 +202,7 @@ public class CharacterCreationService extends Service { Assert.test(creature.getObjectId() > 0); Log.i("%s created character %s from %s", player.getUsername(), create.getName(), create.getSocketAddress()); player.sendPacket(new CreateCharacterSuccess(creature.getObjectId())); - new PlayerEventIntent(player, PlayerEvent.PE_CREATE_CHARACTER).broadcast(); + new CreatedCharacterIntent(creature).broadcast(); //Replaced PlayerEventIntent(PE_CREATE_CHARACTER) } private CreatureObject tryCharacterCreation(ObjectManager objManager, Player player, ClientCreateCharacter create) { diff --git a/test/resources/objects/awareness/TestObjectAwareness.java b/test/resources/objects/awareness/TestObjectAwareness.java index 2a6c0369b..fdacf431d 100644 --- a/test/resources/objects/awareness/TestObjectAwareness.java +++ b/test/resources/objects/awareness/TestObjectAwareness.java @@ -176,7 +176,7 @@ public class TestObjectAwareness { Assert.assertNull("Player1 is in a parent!", player1.getParent()); // Mount - Assert.assertTrue(fireAndWait(100, new ContainerTransferIntent(player1, vehicle))); + Assert.assertTrue(fireAndWait(100, new ContainerTransferIntent(player1, vehicle,vehicle))); //Should Be (player, oldcontainer, newcontainer) player1.setStatesBitmask(CreatureState.RIDING_MOUNT); vehicle.setStatesBitmask(CreatureState.MOUNTED_CREATURE); vehicle.setPosture(Posture.DRIVING_VEHICLE); @@ -216,7 +216,7 @@ public class TestObjectAwareness { Assert.assertTrue(fireAndWait(100, new ObjectCreatedIntent(player2))); Assert.assertTrue(fireAndWait(100, new ObjectCreatedIntent(npc))); Assert.assertTrue(fireAndWait(100, new ObjectCreatedIntent(vehicle))); - Assert.assertTrue(fireAndWait(100, new ContainerTransferIntent(player1, vehicle))); + Assert.assertTrue(fireAndWait(100, new ContainerTransferIntent(player1, vehicle, vehicle))); //Should Be (player, oldcontainer, newcontainer) player1.setStatesBitmask(CreatureState.RIDING_MOUNT); vehicle.setStatesBitmask(CreatureState.MOUNTED_CREATURE); vehicle.setPosture(Posture.DRIVING_VEHICLE);