Merge pull request #1313 from madsboddum/combat_experience_service_data_loader

[Misc] CombatExperienceService uses the NpcStat DataLoader instead of…
This commit is contained in:
Josh
2023-04-30 11:10:02 -05:00
committed by GitHub
@@ -26,71 +26,39 @@
***********************************************************************************/
package com.projectswg.holocore.services.gameplay.combat;
import com.projectswg.common.data.info.RelationalDatabase;
import com.projectswg.common.data.info.RelationalServerFactory;
import com.projectswg.common.data.objects.GameObjectType;
import com.projectswg.holocore.intents.gameplay.combat.CreatureKilledIntent;
import com.projectswg.holocore.intents.gameplay.player.experience.ExperienceIntent;
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader;
import com.projectswg.holocore.resources.support.data.server_info.loader.npc.NpcStatLoader;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureDifficulty;
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
import com.projectswg.holocore.resources.support.objects.swg.group.GroupObject;
import com.projectswg.holocore.resources.support.data.server_info.StandardLog;
import com.projectswg.holocore.resources.support.objects.swg.weapon.WeaponType;
import com.projectswg.holocore.services.support.objects.ObjectStorageService;
import me.joshlarson.jlcommon.control.IntentHandler;
import me.joshlarson.jlcommon.control.Service;
import me.joshlarson.jlcommon.log.Log;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
public class CombatExperienceService extends Service {
private final Map<Short, XpData> xpData;
public CombatExperienceService() {
xpData = new HashMap<>();
}
@Override
public boolean initialize() {
loadXpData();
return true;
}
private void loadXpData() {
long startTime = StandardLog.onStartLoad("combat XP rates");
try (RelationalDatabase npcStats = RelationalServerFactory.getServerData("npc/npc_stats.db", "npc_stats")) {
try (ResultSet set = npcStats.executeQuery("SELECT * FROM npc_stats")) {
while (set.next()) {
xpData.put(set.getShort("Level"), new XpData(set.getInt("XP"), set.getInt("Elite_XP"), set.getInt("Boss_XP")));
}
} catch (SQLException e) {
Log.e(e);
}
}
StandardLog.onEndLoad(xpData.size(), "combat XP rates", startTime);
}
@IntentHandler
private void handleCreatureKilledIntent(CreatureKilledIntent i) {
CreatureObject corpse = i.getCorpse();
if(corpseIsNpc(corpse)) {
if (corpseIsNpc(corpse)) {
CreatureObject killer = i.getKiller();
GroupObject group = getGroupThatKillerIsIn(killer);
short killerLevel = getKillerLevel(killer, group);
int experienceGained = calculateXpGain(killer, corpse, killerLevel);
if (experienceGained <= 0) {
return;
}
boolean killerIsGrouped = group != null;
if (killerIsGrouped) {
grantXpToGroup(corpse, group, experienceGained);
} else {
@@ -98,7 +66,7 @@ public class CombatExperienceService extends Service {
}
}
}
private GroupObject getGroupThatKillerIsIn(CreatureObject killer) {
long groupId = killer.getGroupId();
if (groupId > 0) {
@@ -107,18 +75,19 @@ public class CombatExperienceService extends Service {
return null;
}
}
private void grantXpToGroup(CreatureObject corpse, GroupObject group, int experienceGained) {
group.getGroupMemberObjects().stream()
group.getGroupMemberObjects()
.stream()
.filter(groupMember -> isMemberNearby(corpse, groupMember))
.filter(groupMember -> didMemberParticipateInCombat(corpse, groupMember))
.forEach(eligibleMember -> grantXpToKiller(eligibleMember, corpse, experienceGained));
}
private boolean didMemberParticipateInCombat(CreatureObject corpse, CreatureObject groupMember) {
return corpse.getHateMap().containsKey(groupMember);
}
private short getKillerLevel(CreatureObject killer, GroupObject group) {
if (group != null) {
return group.getLevel();
@@ -126,53 +95,53 @@ public class CombatExperienceService extends Service {
return killer.getLevel();
}
}
private boolean corpseIsNpc(CreatureObject corpse) {
return !corpse.isPlayer();
}
private void grantXpToKiller(CreatureObject killer, CreatureObject corpse, int experienceGained) {
boolean xpMultiply = experienceGained > 1;
grantWeaponTypeXp(killer, corpse, experienceGained, xpMultiply);
if (scoutKilledCreature(killer, corpse)) {
grantTrappingXp(killer, experienceGained);
}
grantCombatXp(killer, corpse, experienceGained, xpMultiply);
}
private void grantTrappingXp(CreatureObject receiver, int experienceGained) {
new ExperienceIntent(receiver, "trapping", (int) Math.ceil(experienceGained / 10f)).broadcast();
}
private boolean scoutKilledCreature(CreatureObject killer, CreatureObject corpse) {
return isKillerScout(killer) && isCorpseCreature(corpse);
}
private boolean isCorpseCreature(CreatureObject corpse) {
return corpse.getGameObjectType() == GameObjectType.GOT_CREATURE;
}
private boolean isKillerScout(CreatureObject killer) {
return killer.hasSkill("outdoors_scout_novice");
}
private void grantCombatXp(CreatureObject receiver, CreatureObject corpse, int experienceGained, boolean xpMultiply) {
new ExperienceIntent(receiver, corpse, "combat_general", (int) Math.ceil(experienceGained / 10f), xpMultiply).broadcast();
}
private void grantWeaponTypeXp(CreatureObject receiver, CreatureObject corpse, int experienceGained, boolean xpMultiply) {
WeaponType weaponType = receiver.getEquippedWeapon().getType();
String xpType = xpTypeForWeaponType(weaponType);
if (xpType == null) {
Log.w("%s did not receive %d xp because the used weapon %s had unrecognized type", receiver, experienceGained, weaponType);
}
new ExperienceIntent(receiver, corpse, xpType, experienceGained, xpMultiply).broadcast();
}
private String xpTypeForWeaponType(WeaponType weaponType) {
return switch (weaponType) {
case UNARMED -> "combat_meleespecialize_unarmed";
@@ -187,16 +156,16 @@ public class CombatExperienceService extends Service {
default -> null;
};
}
private int calculateXpGain(CreatureObject killer, CreatureObject corpse, short killerLevel) {
short corpseLevel = corpse.getLevel();
if (killerLevel - corpseLevel >= 5) {
return 1;
} else {
XpData xpForLevel = this.xpData.get(corpseLevel);
NpcStatLoader.NpcStatInfo npcStats = DataLoader.Companion.npcStats().getNpcStats(corpseLevel);
if (xpForLevel == null) {
if (npcStats == null) {
Log.e("%s received no XP: No XP data was found for level %d!", killer, corpseLevel);
return 0;
}
@@ -204,15 +173,15 @@ public class CombatExperienceService extends Service {
CreatureDifficulty creatureDifficulty = corpse.getDifficulty();
return switch (creatureDifficulty) {
case BOSS -> xpForLevel.bossXp();
case ELITE -> xpForLevel.eliteXp();
case NORMAL -> xpForLevel.xp();
case BOSS -> npcStats.getBossDetailStat().getXp();
case ELITE -> npcStats.getEliteDetailStat().getXp();
case NORMAL -> npcStats.getNormalDetailStat().getXp();
};
}
}
/**
* @param corpse of the NPC that was killed
* @param corpse of the NPC that was killed
* @param groupMember of the group that killed the NPC
* @return true if {@code groupMember} is close enough to the corpse to gain XP
*/
@@ -220,8 +189,4 @@ public class CombatExperienceService extends Service {
return corpse.distanceTo(groupMember) <= 128;
}
private record XpData(int xp, int eliteXp, int bossXp) {
}
}