mirror of
https://github.com/ProjectSWGCore/Holocore.git
synced 2026-09-21 06:13:49 -04:00
Removed some NGE combat logic that would sometimes cause server errors when rolled (dodge, parry...)
This commit is contained in:
@@ -1,2 +0,0 @@
|
||||
line comment cooldown damage critical action_cost freeshot swift
|
||||
TEXT TEXT TEXT TEXT TEXT TEXT TEXT TEXT
|
||||
-1
@@ -71,7 +71,6 @@ abstract class DataLoader {
|
||||
fun zoneInsertions(): TerrainZoneInsertionLoader = ServerData.zoneInsertions
|
||||
fun travelCosts(): TravelCostLoader = ServerData.travelCosts
|
||||
fun vehicles(): VehicleLoader = ServerData.vehicles
|
||||
fun specialLines(): SpecialLineLoader = ServerData.specialLines
|
||||
fun staticPvpZones(): StaticPvpZoneLoader = ServerData.staticPvpZones
|
||||
fun dynamicSpawns(): DynamicSpawnLoader = ServerData.dynamicSpawns
|
||||
fun terrainLevels(): TerrainLevelLoader = ServerData.terrainLevels
|
||||
|
||||
-1
@@ -43,7 +43,6 @@ object ServerData {
|
||||
* Combat
|
||||
*/
|
||||
val buffs by SoftDataLoaderDelegate(::BuffLoader)
|
||||
val specialLines by SoftDataLoaderDelegate(::SpecialLineLoader)
|
||||
val factions by SoftDataLoaderDelegate(::FactionLoader)
|
||||
|
||||
/*
|
||||
|
||||
-82
@@ -1,82 +0,0 @@
|
||||
package com.projectswg.holocore.resources.support.data.server_info.loader;
|
||||
|
||||
import com.projectswg.holocore.resources.support.data.server_info.SdbLoader;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SpecialLineLoader extends DataLoader {
|
||||
|
||||
private final Map<String, SpecialLineInfo> specialLineMap;
|
||||
|
||||
SpecialLineLoader() {
|
||||
specialLineMap = new HashMap<>();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public SpecialLineInfo getSpecialLine(String name) {
|
||||
return specialLineMap.get(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load() throws IOException {
|
||||
try (SdbLoader.SdbResultSet set = SdbLoader.load(new File("serverdata/command/special_lines.sdb"))) {
|
||||
while (set.next()) {
|
||||
SpecialLineInfo specialLineInfo = new SpecialLineInfo(set);
|
||||
|
||||
specialLineMap.put(specialLineInfo.getSpecialLineName(), specialLineInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class SpecialLineInfo {
|
||||
private final String specialLineName;
|
||||
private final String cooldownModName;
|
||||
private final String addedDamageModName; // Added damage is also used for healing abilities
|
||||
private final String criticalChanceModName;
|
||||
private final String actionCostModName;
|
||||
private final String freeshotModName;
|
||||
private final String swiftModName;
|
||||
|
||||
SpecialLineInfo(SdbLoader.SdbResultSet set) {
|
||||
specialLineName = set.getText("line");
|
||||
cooldownModName = set.getText("cooldown");
|
||||
addedDamageModName = set.getText("damage");
|
||||
criticalChanceModName = set.getText("critical");
|
||||
actionCostModName = set.getText("action_cost");
|
||||
freeshotModName = set.getText("freeshot");
|
||||
swiftModName = set.getText("swift");
|
||||
}
|
||||
|
||||
public String getSpecialLineName() {
|
||||
return specialLineName;
|
||||
}
|
||||
|
||||
public String getCooldownModName() {
|
||||
return cooldownModName;
|
||||
}
|
||||
|
||||
public String getAddedDamageModName() {
|
||||
return addedDamageModName;
|
||||
}
|
||||
|
||||
public String getCriticalChanceModName() {
|
||||
return criticalChanceModName;
|
||||
}
|
||||
|
||||
public String getActionCostModName() {
|
||||
return actionCostModName;
|
||||
}
|
||||
|
||||
public String getFreeshotModName() {
|
||||
return freeshotModName;
|
||||
}
|
||||
|
||||
public String getSwiftModName() {
|
||||
return swiftModName;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-102
@@ -31,7 +31,6 @@ import com.projectswg.common.data.RGB;
|
||||
import com.projectswg.common.data.combat.*;
|
||||
import com.projectswg.common.data.encodables.oob.StringId;
|
||||
import com.projectswg.common.data.location.Location;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.Animation;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.ShowFlyText;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.combat.CombatAction;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.combat.CombatAction.Defender;
|
||||
@@ -41,12 +40,10 @@ import com.projectswg.holocore.resources.support.global.commands.CombatCommand;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.weapon.WeaponObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.weapon.WeaponType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.projectswg.holocore.services.gameplay.combat.command.CombatCommandCommon.*;
|
||||
@@ -145,22 +142,6 @@ enum CombatCommandAttack implements CombatCommandHitType {
|
||||
CreatureObject creatureTarget = (CreatureObject) target;
|
||||
|
||||
targets.add(creatureTarget);
|
||||
|
||||
// Let the defender roll single target defences against the attack of the attacker
|
||||
if (isAttackParried(source, creatureTarget, weapon)) {
|
||||
info.setParry(true);
|
||||
info.setSuccess(false);
|
||||
} else if (isAttackDodged(source, creatureTarget)) {
|
||||
// The defender dodged the attack from the target
|
||||
info.setDodge(true);
|
||||
info.setSuccess(false); // This means that the attack did no damage to the target at all
|
||||
long targetObjectId = target.getObjectId();
|
||||
|
||||
// Play dodge animation on the creature that's dodging for everyone that can see the creature
|
||||
target.sendObservers(new Animation(targetObjectId, "dodge"));
|
||||
} else if (isAttackGlanced(source, creatureTarget)) {
|
||||
info.setGlancing(true);
|
||||
}
|
||||
}
|
||||
|
||||
doCombat(source, targets, weapon, info, command);
|
||||
@@ -171,9 +152,6 @@ enum CombatCommandAttack implements CombatCommandHitType {
|
||||
SWGObject originParent = origin.getParent();
|
||||
Collection<SWGObject> objectsToCheck = originParent == null ? origin.getObjectsAware() : originParent.getContainedObjects();
|
||||
|
||||
// TODO block
|
||||
// TODO evasion if no block
|
||||
|
||||
Set<CreatureObject> targets = objectsToCheck.stream()
|
||||
.filter(CreatureObject.class::isInstance)
|
||||
.map(CreatureObject.class::cast)
|
||||
@@ -193,26 +171,9 @@ enum CombatCommandAttack implements CombatCommandHitType {
|
||||
source.updateLastCombatTime();
|
||||
|
||||
CombatAction action = createCombatAction(source, weapon, TrailLocation.WEAPON, command);
|
||||
boolean devastating = isAttackDevastating(source, command);
|
||||
double weaponDamageBoost = 1.0; // Damage increase of the weapon
|
||||
double addedDamageBoost = 1.0; // Damage increase of the command
|
||||
|
||||
if (devastating) {
|
||||
// Show Devastation flytext above the source for every target
|
||||
ShowFlyText devastationFlyText = new ShowFlyText(source.getObjectId(), new StringId("combat_effects", "devastation"), ShowFlyText.Scale.MEDIUM, new RGB(255, 255, 255));
|
||||
|
||||
source.sendSelf(devastationFlyText);
|
||||
|
||||
for (CreatureObject target : targets) {
|
||||
target.sendSelf(devastationFlyText);
|
||||
}
|
||||
|
||||
weaponDamageBoost += 0.5; // 50% damage boost from devastation
|
||||
}
|
||||
|
||||
// Apply special line damage boost
|
||||
addedDamageBoost += CombatCommandCommon.getAddedDamageBoost(source, command);
|
||||
|
||||
for (CreatureObject target : targets) {
|
||||
target.updateLastCombatTime();
|
||||
|
||||
@@ -342,67 +303,5 @@ enum CombatCommandAttack implements CombatCommandHitType {
|
||||
return mitigation / 100;
|
||||
|
||||
}
|
||||
|
||||
private static boolean isAttackParried(CreatureObject source, CreatureObject target, WeaponObject attackerWeapon) {
|
||||
WeaponObject defenderWeapon = target.getEquippedWeapon();
|
||||
WeaponType defenderWeaponType = defenderWeapon.getType();
|
||||
WeaponType attackerWeaponType = attackerWeapon.getType();
|
||||
|
||||
// If the defender is wielding a lightsaber, parry can always be rolled, regardless of what the attacker is wielding
|
||||
// If both attacker and defender are wielding melee weapons, parry can be rolled
|
||||
if (defenderWeaponType.isLightsaber() || (defenderWeaponType.isMelee() && attackerWeaponType.isMelee())) {
|
||||
double parryChance = (target.getSkillModValue("display_only_parry") - source.getSkillModValue("display_only_parry_reduction")) / 100d;
|
||||
double roll = ThreadLocalRandom.current().nextDouble(100); // Generate number between 0 and 100
|
||||
|
||||
return roll <= parryChance; // If parry chance is 25%, then the roll should be between 0 and 25 (both inclusive)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isAttackDodged(CreatureObject source, CreatureObject target) {
|
||||
double dodgeChance = (target.getSkillModValue("display_only_dodge") - source.getSkillModValue("display_only_opp_dodge_reduction")) / 100d;
|
||||
double roll = ThreadLocalRandom.current().nextDouble(100); // Generate number between 0 and 100
|
||||
|
||||
return roll <= dodgeChance; // If dodge chance is 25%, then the roll should be between 0 and 25 (both inclusive)
|
||||
}
|
||||
|
||||
private static boolean isAttackGlanced(CreatureObject source, CreatureObject target) {
|
||||
double glanceChance = target.getSkillModValue("display_only_glancing_blow") / 100d;
|
||||
WeaponObject sourceEquippedWeapon = source.getEquippedWeapon();
|
||||
WeaponType weaponType = sourceEquippedWeapon.getType();
|
||||
|
||||
if (weaponType.isMelee()) {
|
||||
glanceChance += target.getSkillModValue("expertise_glancing_blow_melee");
|
||||
}
|
||||
|
||||
if (weaponType.isRanged()) {
|
||||
glanceChance += target.getSkillModValue("expertise_glancing_blow_ranged");
|
||||
}
|
||||
|
||||
double roll = ThreadLocalRandom.current().nextDouble(100); // Generate number between 0 and 100
|
||||
|
||||
return roll <= glanceChance; // If glance chance is 25%, then the roll should be between 0 and 25 (both inclusive)
|
||||
}
|
||||
|
||||
private static boolean isAttackDevastating(CreatureObject source, CombatCommand command) {
|
||||
if (command.getPercentAddFromWeapon() == 0) {
|
||||
// If this ability doesn't use weapon damage it does not qualify for a devastation roll
|
||||
return false;
|
||||
}
|
||||
|
||||
WeaponObject weapon = source.getEquippedWeapon();
|
||||
WeaponType type = weapon.getType();
|
||||
|
||||
if (!WeaponType.HEAVY_WEAPON.equals(type) && !WeaponType.DIRECTIONAL_TARGET_WEAPON.equals(type)) {
|
||||
// If the weapon type isn't a heavy weapon and isn't a flamethrower, then the weapon cannot roll a devastation
|
||||
return false;
|
||||
}
|
||||
|
||||
double devastationChance = source.getSkillModValue("expertise_devastation_bonus") / 10d;
|
||||
double roll = ThreadLocalRandom.current().nextDouble(100); // Generate number between 0 and 100
|
||||
|
||||
return roll <= devastationChance; // If devastation chance is 20%, then the roll should be between 0 and 20 (both inclusive)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+3
-16
@@ -29,24 +29,21 @@ package com.projectswg.holocore.services.gameplay.combat.command;
|
||||
|
||||
import com.projectswg.common.data.CRC;
|
||||
import com.projectswg.common.data.RGB;
|
||||
import com.projectswg.common.data.combat.*;
|
||||
import com.projectswg.common.data.encodables.oob.OutOfBandPackage;
|
||||
import com.projectswg.common.data.encodables.oob.ProsePackage;
|
||||
import com.projectswg.common.data.combat.AttackInfo;
|
||||
import com.projectswg.common.data.combat.CombatStatus;
|
||||
import com.projectswg.common.data.combat.TrailLocation;
|
||||
import com.projectswg.common.data.encodables.oob.StringId;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.ShowFlyText;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.ShowFlyText.Scale;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.combat.CombatAction;
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.combat.CombatSpam;
|
||||
import com.projectswg.holocore.intents.gameplay.combat.buffs.BuffIntent;
|
||||
import com.projectswg.holocore.resources.support.data.server_info.loader.ServerData;
|
||||
import com.projectswg.holocore.resources.support.data.server_info.loader.SpecialLineLoader;
|
||||
import com.projectswg.holocore.resources.support.global.commands.CombatCommand;
|
||||
import com.projectswg.holocore.resources.support.global.commands.Command;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.SWGObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.tangible.TangibleObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.weapon.WeaponObject;
|
||||
import com.projectswg.holocore.resources.support.objects.swg.weapon.WeaponType;
|
||||
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@@ -183,14 +180,4 @@ public class CombatCommandCommon {
|
||||
obj.sendSelf(new ShowFlyText(obj.getObjectId(), text, scale, c, flags));
|
||||
}
|
||||
|
||||
static double getAddedDamageBoost(CreatureObject source, CombatCommand command) {
|
||||
SpecialLineLoader.SpecialLineInfo specialLine = ServerData.INSTANCE.getSpecialLines().getSpecialLine(command.getSpecialLine());
|
||||
if (specialLine != null) {
|
||||
String damageModName = specialLine.getAddedDamageModName();
|
||||
return source.getSkillModValue(damageModName) / 100d;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-3
@@ -63,9 +63,6 @@ enum CombatCommandHeal implements CombatCommandHitType {
|
||||
healAmount *= healingPotency;
|
||||
}
|
||||
|
||||
// Apply special line heal boost
|
||||
healAmount += CombatCommandCommon.getAddedDamageBoost(source, combatCommand);
|
||||
|
||||
switch (combatCommand.getAttackType()) {
|
||||
case SINGLE_TARGET: {
|
||||
switch (combatCommand.getTargetType()) {
|
||||
|
||||
+5
-42
@@ -27,24 +27,14 @@
|
||||
|
||||
package com.projectswg.holocore.services.gameplay.combat.command
|
||||
|
||||
import com.projectswg.common.data.RGB
|
||||
import com.projectswg.common.data.combat.CombatStatus
|
||||
import com.projectswg.common.data.combat.HitType
|
||||
import com.projectswg.common.data.encodables.oob.StringId
|
||||
import com.projectswg.common.network.packets.swg.zone.object_controller.ShowFlyText
|
||||
import com.projectswg.holocore.intents.support.global.command.ExecuteCommandIntent
|
||||
import com.projectswg.holocore.resources.support.data.server_info.loader.DataLoader
|
||||
import com.projectswg.holocore.resources.support.data.server_info.loader.SpecialLineLoader.SpecialLineInfo
|
||||
import com.projectswg.holocore.resources.support.global.commands.CombatCommand
|
||||
import com.projectswg.holocore.resources.support.objects.swg.creature.CreatureObject
|
||||
import com.projectswg.holocore.services.gameplay.combat.command.CombatCommandCommon.handleStatus
|
||||
import me.joshlarson.jlcommon.control.IntentHandler
|
||||
import me.joshlarson.jlcommon.control.Service
|
||||
import me.joshlarson.jlcommon.log.Log
|
||||
|
||||
import java.util.EnumMap
|
||||
import java.util.concurrent.ThreadLocalRandom
|
||||
|
||||
import com.projectswg.holocore.services.gameplay.combat.command.CombatCommandCommon.handleStatus
|
||||
import java.util.*
|
||||
|
||||
class CombatCommandService : Service() {
|
||||
|
||||
@@ -80,38 +70,11 @@ class CombatCommandService : Service() {
|
||||
val command = eci.command as CombatCommand
|
||||
|
||||
val source = eci.source
|
||||
val specialLine = DataLoader.specialLines().getSpecialLine(command.specialLine)
|
||||
var actionCost = command.actionCost * command.attackRolls
|
||||
|
||||
// TODO future: reduce actionCost with general ACR, weapon ACR and ability ACR
|
||||
|
||||
if (specialLine != null && source.getSkillModValue(specialLine.freeshotModName) > ThreadLocalRandom.current().nextInt(0, 100)) {
|
||||
source.sendSelf(ShowFlyText(source.objectId, StringId("spam", "freeshot"), ShowFlyText.Scale.MEDIUM, RGB(255, 255, 255), ShowFlyText.Flag.IS_FREESHOT))
|
||||
} else {
|
||||
if (specialLine != null)
|
||||
actionCost = reduceActionCost(source, actionCost, specialLine.actionCostModName)
|
||||
if (actionCost > source.action)
|
||||
return
|
||||
|
||||
source.modifyAction(-command.actionCost.toInt())
|
||||
}
|
||||
|
||||
source.modifyAction((-command.actionCost).toInt())
|
||||
|
||||
val hitType = hitTypeMap[command.hitType]
|
||||
hitType?.handle(source, eci.target, command, eci.arguments) ?: handleStatus(source, CombatStatus.UNKNOWN)
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a new action cost based on the given action cost and a skill mod name.
|
||||
* @param source to read the skillmod value from
|
||||
* @param actionCost that has been calculated so far
|
||||
* @param skillModName name of the skillmod to read from `source`
|
||||
* @return new action cost that has been increased or reduced, depending on whether the skillmod value is
|
||||
* positive or negative
|
||||
*/
|
||||
private fun reduceActionCost(source: CreatureObject, actionCost: Double, skillModName: String): Double {
|
||||
val actionCostModValue = source.getSkillModValue(skillModName)
|
||||
|
||||
return actionCost + actionCost * actionCostModValue / 100
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user