Compare commits

...

140 Commits

Author SHA1 Message Date
FatBoy 5142a87b60 direct damage handler - power damage modifiers 2025-03-02 16:09:56 -06:00
FatBoy 9b7568b576 direct damage handler - cleanup 2025-03-02 16:00:48 -06:00
FatBoy 7bec57e77d direct damage handler - fixed double values 2025-03-02 16:00:17 -06:00
FatBoy 28bccdd3d8 direct damage handler - percent damages 2025-03-02 15:51:14 -06:00
FatBoy cca342e99d direct damage behaviour handler -fix max damage pull 2025-03-02 15:38:16 -06:00
FatBoy e41c79e6d7 direct damage behaviour handler 2025-03-02 15:37:45 -06:00
MagicBot 7dfb0da862 NoMod work. 2025-03-02 13:57:27 -05:00
MagicBot c2d4e0c1dd NoMod work. 2025-03-02 13:54:25 -05:00
MagicBot 512621981a NoMod work. 2025-03-02 12:58:48 -05:00
MagicBot 81c9a84edf NoMod work. 2025-03-02 12:42:46 -05:00
MagicBot c099444464 NoMod work. 2025-03-02 12:41:08 -05:00
MagicBot 94afb7f40f Ternary restored 2025-03-01 17:13:58 -05:00
MagicBot d43f87b295 Arguments fixed in enum 2025-03-01 17:10:27 -05:00
MagicBot d5b787430e Method inlined 2025-03-01 16:52:25 -05:00
MagicBot 3af6cab92e Bugfix in enum usage 2025-02-26 14:12:04 -05:00
MagicBot 106e7be1ac Enum equals faster than string contains 2025-02-26 12:22:42 -05:00
MagicBot 0d8f1f7252 Field added to enumeration 2025-02-26 12:20:37 -05:00
MagicBot 330344f55b Comment update 2025-02-26 12:11:04 -05:00
MagicBot 7a5f138c78 Comment update 2025-02-26 12:10:28 -05:00
MagicBot 6a9ca26d81 No need to process zero values 2025-02-26 12:09:13 -05:00
MagicBot 32c28e8f54 Rename of helper method 2025-02-26 12:06:23 -05:00
MagicBot 99dcfbb4a2 Update to helper method 2025-02-26 12:05:18 -05:00
MagicBot 16dffee0e3 Update to helper method 2025-02-26 12:04:07 -05:00
MagicBot a5cb785587 Update to helper method 2025-02-26 11:56:43 -05:00
MagicBot 7bcd75719c Update to helper method 2025-02-26 11:43:46 -05:00
MagicBot d96993576a Update to helper method 2025-02-25 14:44:51 -05:00
MagicBot 17afaf6720 Behaviour is unused. Stilled mechanic? 2025-02-25 13:37:09 -05:00
MagicBot 3e9f38c857 Behaviour work 2025-02-25 13:35:06 -05:00
MagicBot a36dbc6539 Method rename for clarity 2025-02-24 14:47:34 -05:00
MagicBot 7d3ff49796 Comment touch-up 2025-02-24 14:43:30 -05:00
MagicBot d2ac62e320 Removed variable as scope changed 2025-02-24 14:39:51 -05:00
MagicBot 4b83311a89 Comment update 2025-02-24 14:35:34 -05:00
MagicBot 7fd55bb6f3 Rework of helper method 2025-02-24 14:33:40 -05:00
MagicBot a40025bca1 Rework of helper method 2025-02-24 14:26:43 -05:00
MagicBot d58ba67cc2 Comment added 2025-02-24 13:55:04 -05:00
MagicBot 3d4a9e18d0 Tweak to modifierentry 2025-02-24 08:46:31 -05:00
MagicBot 7e5fe56bc0 Enum set for category 2025-02-23 16:15:25 -05:00
MagicBot 4cf3b0929f Commented out stun check for now. 2025-02-23 16:11:56 -05:00
MagicBot 98a6d268d0 Behaviour work. 2025-02-23 15:48:00 -05:00
MagicBot a9a4b36121 Behaviour work. 2025-02-23 15:47:33 -05:00
MagicBot 75a4a69036 Behaviour work. 2025-02-23 15:27:50 -05:00
MagicBot 982a35bb4f Behaviour work. 2025-02-23 15:25:28 -05:00
MagicBot 27c3fe515c Behaviour work. 2025-02-23 14:56:02 -05:00
MagicBot 29d82d9e81 Behaviour returns enumeration 2025-02-23 14:48:39 -05:00
MagicBot 81427e6911 FPSubTypeAttr uses min. 2025-02-23 14:37:43 -05:00
MagicBot 296a7012b0 old method removed 2025-02-23 14:07:49 -05:00
MagicBot b9b88449ed Variable rename 2025-02-22 15:37:38 -05:00
MagicBot 6585248eb8 Variable rename 2025-02-22 15:34:28 -05:00
MagicBot feebddd495 Variable rename 2025-02-22 15:33:59 -05:00
MagicBot 3e510a487c Variable rename 2025-02-22 15:25:36 -05:00
MagicBot 5277fbbe56 More generalized curve helper 2025-02-22 15:23:15 -05:00
MagicBot 1a64272801 Unified signature: caster/power/rank/target 2025-02-22 13:10:30 -05:00
MagicBot fc7b7eb915 Unified signature: caster/power/rank/target 2025-02-22 13:03:39 -05:00
MagicBot 1e3249561c Project headers added 2025-02-22 12:53:26 -05:00
MagicBot 1ac76ae4d3 Less methods = smaller object. 2025-02-22 12:52:22 -05:00
MagicBot 56cea25e06 final field 2025-02-22 12:48:02 -05:00
MagicBot 2c33ff5a2a Both actions use same behaviour 2025-02-22 12:46:22 -05:00
MagicBot 3cdf848e33 Method rename for clarity 2025-02-22 08:10:08 -05:00
MagicBot 7ed291860f Refactor manager for action support 2025-02-22 07:57:38 -05:00
MagicBot e3e8fae90c Comment updated 2025-02-22 07:55:59 -05:00
MagicBot 0a2e487a76 Signature updated for actions 2025-02-22 07:54:49 -05:00
MagicBot 6018be3c72 Actions use same signature as modifiers 2025-02-22 07:24:47 -05:00
FatBoy 486141ce0b Behaviour FPSubTypeDmg 2025-02-21 16:34:35 -06:00
FatBoy cc96d68974 Behaviour FPSubTypeDmg 2025-02-21 16:33:17 -06:00
FatBoy 6740896244 Behaviour SubTypeSkill 2025-02-21 16:17:48 -06:00
FatBoy 811eb42e47 Behaviour SubTypePowerType 2025-02-21 16:12:09 -06:00
MagicBot 1633b5d0dd Shallow copy 2025-02-21 16:13:54 -05:00
MagicBot 808eb989ea Related enums moved close in file 2025-02-21 15:16:01 -05:00
MagicBot 6879a8dccf Comment added 2025-02-21 15:13:11 -05:00
MagicBot 8cf17e3abd Comment added 2025-02-21 15:12:47 -05:00
MagicBot 0711c8f05b More behaviour work. 2025-02-21 14:32:45 -05:00
MagicBot b0ad37dbf8 Refactor for poweraction implementation 2025-02-21 14:13:29 -05:00
MagicBot 2c3d5a3fcf Less boilerplate using functional interface 2025-02-21 13:49:09 -05:00
MagicBot 78e8aab808 parser now uses poweractiontype 2025-02-21 13:15:01 -05:00
MagicBot 2bc033170f Devcmd removed for refactor work. 2025-02-21 12:58:41 -05:00
MagicBot 556eb30ab0 Comment added 2025-02-20 15:21:47 -05:00
MagicBot 4f74d43081 Error log for invalid effect 2025-02-20 15:12:25 -05:00
MagicBot 80c4dcc082 More behaviour work 2025-02-20 14:31:09 -05:00
MagicBot 9cd30d5299 Lookup table uses hash value 2025-02-20 14:22:53 -05:00
MagicBot b148ea5f6e Comment updated 2025-02-20 14:19:59 -05:00
MagicBot 3612232788 PowerAction not ActionEntry 2025-02-20 14:19:10 -05:00
MagicBot 99acc4736f Iterate through all effects for action 2025-02-20 14:13:13 -05:00
MagicBot fac426a09c bugfix in parser 2025-02-20 14:02:28 -05:00
MagicBot c75a153c92 more behaviour work 2025-02-20 13:59:21 -05:00
MagicBot ce5611aafd Scaling method updated 2025-02-20 13:28:19 -05:00
MagicBot 9e6b50d264 argument rename for clarity 2025-02-20 07:58:51 -05:00
MagicBot f5801e0837 Static method to apply curves 2025-02-20 07:54:41 -05:00
MagicBot 79864713b5 More behaviour work 2025-02-20 07:37:22 -05:00
MagicBot 42daf1c049 Comment updated 2025-02-20 07:26:51 -05:00
MagicBot 1784ac1e5d Comment updated 2025-02-19 14:13:56 -05:00
MagicBot 137a547d3d Minor formatting touchup. 2025-02-19 14:04:42 -05:00
MagicBot d9738c39a5 Effects stored in new collection 2025-02-19 13:59:44 -05:00
MagicBot 45bd3159ce Pojo created to store mods 2025-02-19 13:41:16 -05:00
MagicBot acd1246a87 Unnecessary initialization 2025-02-19 12:51:09 -05:00
MagicBot 1e64108b56 Unnecessary cast 2025-02-19 12:49:32 -05:00
MagicBot 1481cc7ac0 Methods made static and moved to manager 2025-02-19 12:43:58 -05:00
MagicBot c0b75564c2 equals and hash defined for wpak pojos 2025-02-19 12:37:04 -05:00
MagicBot 4958165603 Standard behaviour completed. 2025-02-18 15:16:27 -05:00
MagicBot 35258f6ab5 Curve is a float.
Begin filling out first behaviour
2025-02-18 15:07:41 -05:00
MagicBot 3913201eed Arguments filtered down to implementation methods. 2025-02-18 14:42:40 -05:00
MagicBot 37bedcf919 Behaviours return a java Object 2025-02-18 13:20:28 -05:00
MagicBot 11e40d7e57 File reformat 2025-02-18 13:11:56 -05:00
MagicBot 0cdd8a75dc Caster added to signature.
Proper wpak class used for actions.
2025-02-18 13:09:40 -05:00
MagicBot 2e45d8548f Arguments added to signature 2025-02-18 12:55:38 -05:00
MagicBot 61f8c210ae Project headers added 2025-02-17 05:00:33 -05:00
MagicBot acc5c04810 Behaviour method overrides 2025-02-17 04:59:00 -05:00
MagicBot 8030ecb800 Behaviour class defined 2025-02-17 04:45:38 -05:00
MagicBot 12b350580a Token is primary key 2025-02-16 17:27:33 -05:00
MagicBot 78dd409fa8 Only type is needed for key 2025-02-16 17:24:10 -05:00
MagicBot 0727175cb2 new collection populated 2025-02-16 16:44:20 -05:00
MagicBot 7c3a3fb84c new collection for new manager 2025-02-16 16:36:47 -05:00
MagicBot 5781737afc rank added to signature. New package created. 2025-02-16 16:29:14 -05:00
MagicBot 75e1dddd08 ModBehaviour defined 2025-02-15 12:55:06 -05:00
MagicBot 1e78442910 ModBehaviour defined 2025-02-15 12:37:06 -05:00
FatBoy de6158842d loop all effects in power actions 2025-02-01 15:28:09 -06:00
MagicBot 0c07586927 Debug code removed 2025-01-20 16:48:11 -05:00
MagicBot cfca585ab5 Trailing bow can sometimes be missing the bool. 2025-01-20 16:46:51 -05:00
MagicBot db2a168229 Debug code added 2025-01-20 16:32:48 -05:00
MagicBot 040121f7cd Debug code added 2025-01-20 16:24:27 -05:00
MagicBot 570a22f0cb Debug code removed 2025-01-20 16:20:34 -05:00
MagicBot 1ebc5d5e00 Debug code removed 2025-01-20 16:18:18 -05:00
MagicBot 4b1d7ea718 Debug code added 2025-01-20 16:12:43 -05:00
MagicBot 402f608f7a Variable renamed 2025-01-20 16:10:36 -05:00
FatBoy b9b6b37505 use new power manager 2025-01-19 15:26:32 -06:00
FatBoy 3be5236ba8 use new power manager 2025-01-19 15:23:39 -06:00
FatBoy 4cbe9fc236 effect parsing 2025-01-19 15:16:54 -06:00
FatBoy 6ac05d3db2 added missing source types 2025-01-19 15:14:27 -06:00
FatBoy 2531041d7c added missing source types 2025-01-19 15:10:34 -06:00
FatBoy 77e5866351 added missing source types 2025-01-19 15:07:44 -06:00
FatBoy 22e80e1ef4 added missing source types 2025-01-19 15:05:23 -06:00
FatBoy a86e07a89f added missing source types 2025-01-19 15:03:46 -06:00
FatBoy 5f277c3cff added missing source types 2025-01-19 15:00:13 -06:00
FatBoy ef234beeb7 added missing source types 2025-01-19 14:59:05 -06:00
FatBoy 69c5c5da92 added missing source types 2025-01-19 14:52:33 -06:00
FatBoy 7ed5431c99 Logging point - TEMP 2025-01-19 14:49:04 -06:00
FatBoy 627255ce3d Logging point - TEMP 2025-01-19 14:45:03 -06:00
FatBoy 0d1c9e8b8b Logging point - TEMP 2025-01-19 14:43:14 -06:00
MagicBot 5fa79fbac6 Parsing update for eqreqs 2025-01-19 12:01:53 -05:00
FatBoy 45b4ae9e3e TransferStatPowerAction java 2025-01-19 10:22:59 -06:00
MagicBot f410fc5482 Set curve names properly 2024-11-30 09:57:04 -05:00
32 changed files with 1769 additions and 1303 deletions
-156
View File
@@ -1,156 +0,0 @@
// • ▌ ▄ ·. ▄▄▄· ▄▄ • ▪ ▄▄· ▄▄▄▄· ▄▄▄· ▐▄▄▄ ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀ █▪▀▀▀ ▀ ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀ ▀ ▀ ▀▀ █▪ ▀▀▀
// Magicbane Emulator Project © 2013 - 2022
// www.magicbane.com
package engine.devcmd.cmds;
import engine.devcmd.AbstractDevCmd;
import engine.gameManager.ChatManager;
import engine.gameManager.PowersManager;
import engine.mbEnums.PowerActionType;
import engine.objects.AbstractGameObject;
import engine.objects.PlayerCharacter;
import engine.powers.ActionsBase;
import engine.powers.PowersBase;
import engine.powers.effectmodifiers.AbstractEffectModifier;
import engine.util.ThreadUtils;
import org.pmw.tinylog.Logger;
import java.util.HashMap;
import java.util.HashSet;
public class ApplyBonusCmd extends AbstractDevCmd {
public ApplyBonusCmd() {
super("applybonus");
}
@Override
protected void _doCmd(PlayerCharacter pcSender, String[] words,
AbstractGameObject target) {
String action = words[0];
PowerActionType actionType = null;
HashMap<String, HashSet<String>> appliedMods = new HashMap<>();
try {
if (action.equals("all") == false)
for (PowerActionType powerActionType : PowerActionType.values()) {
if (powerActionType.name().equalsIgnoreCase(action) == false)
continue;
actionType = powerActionType;
break;
}
} catch (Exception e) {
this.throwbackError(pcSender, "Invalid power Action type for " + action);
this.throwbackInfo(pcSender, "Valid Types : " + this.getActionTypes());
return;
}
if (action.equals("all") == false)
if (actionType == null) {
this.throwbackError(pcSender, "Invalid power Action type for " + action);
this.throwbackInfo(pcSender, "Valid Types : " + this.getActionTypes());
return;
}
for (PowersBase pb : PowersManager.powersBaseByIDString.values()) {
if (pb.getActions() == null || pb.getActions().isEmpty())
continue;
for (ActionsBase ab : pb.getActions()) {
if (ab.getPowerAction() == null)
continue;
if (action.equals("all") == false)
if (ab.getPowerAction().getType().equalsIgnoreCase(action) == false)
continue;
String effect1 = "";
String effect2 = "";
ChatManager.chatSystemInfo(pcSender, "Applying Power " + pb.getName() + " : " + pb.getDescription());
if (ab.getPowerAction().getEffectsBase() == null) {
try {
PowersManager.runPowerAction(pcSender, pcSender, pcSender.getLoc(), ab, 1, pb);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
ThreadUtils.sleep(500);
continue;
}
if (ab.getPowerAction().getEffectsBase().getModifiers() == null || ab.getPowerAction().getEffectsBase().getModifiers().isEmpty()) {
try {
PowersManager.runPowerAction(pcSender, pcSender, pcSender.getLoc(), ab, 1, pb);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
continue;
}
boolean run = true;
for (AbstractEffectModifier mod : ab.getPowerAction().getEffectsBase().getModifiers()) {
if (appliedMods.containsKey(mod.modType.name()) == false) {
appliedMods.put(mod.modType.name(), new HashSet<>());
}
// if (appliedMods.get(mod.modType.name()).contains(mod.sourceType.name())){
// continue;
// }
appliedMods.get(mod.modType.name()).add(mod.sourceType.name());
try {
try {
PowersManager.runPowerAction(pcSender, pcSender, pcSender.getLoc(), ab, 1, pb);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (Exception e) {
Logger.error(e);
}
break;
}
}
}
}
@Override
protected String _getUsageString() {
return "' /bounds'";
}
@Override
protected String _getHelpString() {
return "Audits all the mobs in a zone.";
}
private String getActionTypes() {
String output = "";
for (PowerActionType actionType : PowerActionType.values()) {
output += actionType.name() + " | ";
}
return output.substring(0, output.length() - 3);
}
}
@@ -122,7 +122,6 @@ public enum DevCmdManager {
DevCmdManager.registerDevCmd(new SetNpcNameCmd());
DevCmdManager.registerDevCmd(new BoundsCmd());
DevCmdManager.registerDevCmd(new RegionCmd());
DevCmdManager.registerDevCmd(new ApplyBonusCmd());
DevCmdManager.registerDevCmd(new SlotTestCmd());
}
+37 -47
View File
@@ -32,9 +32,9 @@ import engine.server.MBServerStatics;
import engine.wpak.EffectsParser;
import engine.wpak.PowerActionParser;
import engine.wpak.PowersParser;
import engine.wpak.WpakPowerManager;
import engine.wpak.data.Effect;
import engine.wpak.data.PowerAction;
import engine.wpakpowers.WpakPowerManager;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
@@ -64,10 +64,12 @@ public enum PowersManager {
public static void initPowersManager(boolean fullPowersLoad) {
if (fullPowersLoad)
PowersManager.InitializePowers();
else
if (fullPowersLoad) {
//PowersManager.InitializePowers();
WpakPowerManager.init();
}else {
PowersManager.InitializeLoginPowers();
}
PowersManager.js = JobScheduler.getInstance();
@@ -119,7 +121,7 @@ public enum PowersManager {
// Add EffectsBase
ArrayList<EffectsBase> effectList = new ArrayList<>();
for (Effect entry : WpakPowerManager.effect_data.values()) {
for (Effect entry : WpakPowerManager._effectsLookup.values()) {
EffectsBase effectBase = new EffectsBase(entry);
effectList.add(effectBase);
PowersManager.effectsBaseByToken.put(effectBase.getToken(), effectBase);
@@ -134,9 +136,9 @@ public enum PowersManager {
HashMap<String, EffectsBase> effects = PowersManager.effectsBaseByIDString;
for (PowerAction powerAction : WpakPowerManager.power_actions.values()) {
for (PowerAction powerAction : WpakPowerManager._powerActionLookup.values()) {
AbstractPowerAction apa;
String type = powerAction.action_type;
PowerActionType type = powerAction.action_type;
String IDString = powerAction.action_id;
int token = DbManager.hasher.SBStringHash(IDString);
//cache token, used for applying effects.
@@ -146,102 +148,90 @@ public enum PowersManager {
default:
Logger.error("valid type not found for poweraction of ID" + IDString);
break;
case "ApplyEffect":
case ApplyEffect:
apa = new ApplyEffectPowerAction(powerAction, effects);
break;
case "ApplyEffects":
case ApplyEffects:
apa = new ApplyEffectsPowerAction(powerAction, effects);
break;
case "DeferredPower":
case DeferredPower:
apa = new DeferredPowerPowerAction(powerAction, effects);
break;
case "DamageOverTime":
case DamageOverTime:
apa = new DamageOverTimePowerAction(powerAction, effects);
break;
case "Peek":
case Peek:
apa = new PeekPowerAction(powerAction);
break;
case "Charm":
case Charm:
apa = new CharmPowerAction(powerAction);
break;
case "Fear":
apa = new FearPowerAction(powerAction);
break;
case "Confusion":
apa = new ConfusionPowerAction(powerAction);
break;
case "RemoveEffect":
case RemoveEffect:
apa = new RemoveEffectPowerAction(powerAction);
break;
case "Track":
case Track:
apa = new TrackPowerAction(powerAction, effects);
break;
case "DirectDamage":
case DirectDamage:
apa = new DirectDamagePowerAction(powerAction, effects);
break;
case "Transform":
case Transform:
apa = new TransformPowerAction(powerAction, effects);
break;
case "CreateMob":
case CreateMob:
apa = new CreateMobPowerAction(powerAction);
break;
case "Invis":
case Invis:
apa = new InvisPowerAction(powerAction, effects);
break;
case "ClearNearbyAggro":
case ClearNearbyAggro:
apa = new ClearNearbyAggroPowerAction(powerAction);
break;
case "MobRecall":
case MobRecall:
apa = new MobRecallPowerAction(powerAction);
break;
case "SetItemFlag":
case SetItemFlag:
apa = new SetItemFlagPowerAction(powerAction);
break;
case "SimpleDamage":
case SimpleDamage:
apa = new SimpleDamagePowerAction(powerAction);
break;
case "TransferStatOT":
case TransferStatOT:
apa = new TransferStatOTPowerAction(powerAction, effects);
break;
case "TransferStat":
case TransferStat:
apa = new TransferStatPowerAction(powerAction, effects);
break;
case "Teleport":
case Teleport:
apa = new TeleportPowerAction(powerAction);
break;
case "TreeChoke":
case TreeChoke:
apa = new TreeChokePowerAction(powerAction);
break;
case "Block":
case Block:
apa = new BlockPowerAction(powerAction);
break;
case "Resurrect":
case Resurrect:
apa = new ResurrectPowerAction(powerAction);
break;
case "ClearAggro":
apa = new ClearAggroPowerAction(powerAction);
break;
case "ClaimMine":
case ClaimMine:
apa = new ClaimMinePowerAction(powerAction);
break;
case "Recall":
case Recall:
apa = new RecallPowerAction(powerAction);
break;
case "SpireDisable":
case SpireDisable:
apa = new SpireDisablePowerAction(powerAction);
break;
case "Steal":
case Steal:
apa = new StealPowerAction(powerAction);
break;
case "Summon":
case Summon:
apa = new SummonPowerAction(powerAction);
break;
case "RunegateTeleport":
case RunegateTeleport:
apa = new RunegateTeleportPowerAction(powerAction);
break;
case "OpenGate":
apa = new OpenGatePowerAction(powerAction);
break;
}
PowersManager.powerActionsByIDString.put(IDString, apa);
}
+1 -3
View File
@@ -14,9 +14,7 @@ import engine.job.AbstractScheduleJob;
import engine.net.client.msg.PerformActionMsg;
import engine.objects.AbstractWorldObject;
import engine.objects.PlayerCharacter;
import engine.powers.PowersBase;
import engine.wpak.WpakPowerManager;
import engine.wpak.data.Power;
import engine.wpakpowers.WpakPowerManager;
public class WpakUsePowerJob extends AbstractScheduleJob {
+535 -452
View File
File diff suppressed because it is too large Load Diff
@@ -8,10 +8,10 @@
package engine.net.client.handlers;
import engine.gameManager.PowersManager;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ClientNetMsg;
import engine.net.client.msg.PerformActionMsg;
import engine.wpakpowers.WpakPowerManager;
public class PerformActionMsgHandler extends AbstractClientMsgHandler {
@@ -23,7 +23,8 @@ public class PerformActionMsgHandler extends AbstractClientMsgHandler {
protected boolean _handleNetMsg(ClientNetMsg baseMsg, ClientConnection origin) {
PerformActionMsg msg = (PerformActionMsg) baseMsg;
PowersManager.usePower(msg, origin, false); // Wtf ?
//PowersManager.beginCast(msg, origin, false); // Wtf ?
WpakPowerManager.beginCast(msg, origin, false);
return true;
}
@@ -17,8 +17,10 @@ import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.SendSummonsMsg;
import engine.objects.PlayerCharacter;
import engine.server.MBServerStatics;
import engine.wpakpowers.WpakPowerManager;
import static engine.gameManager.PowersManager.*;
import static engine.gameManager.PowersManager.sendPowerMsg;
import static engine.gameManager.PowersManager.sendRecyclePower;
public class SendSummonsMsgHandler extends AbstractClientMsgHandler {
@@ -81,7 +83,8 @@ public class SendSummonsMsgHandler extends AbstractClientMsgHandler {
// Client removes 200 mana on summon use.. so don't send message to self
target.addSummoner(playerCharacter.getObjectUUID(), System.currentTimeMillis() + MBServerStatics.FOURTYFIVE_SECONDS);
usePower(pam, origin, false);
//beginCast(pam, origin, false);
WpakPowerManager.beginCast(pam, origin, false);
return true;
}
@@ -29,6 +29,7 @@ import engine.net.client.ClientConnection;
import engine.net.client.msg.UpdateEffectsMsg;
import engine.powers.EffectsBase;
import engine.server.MBServerStatics;
import engine.wpakpowers.AppliedEffect;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
@@ -60,6 +61,10 @@ public abstract class AbstractWorldObject extends AbstractGameObject {
private int objectTypeMask = 0;
private Bounds bounds;
// Effects collection for wpak power manager
public ConcurrentHashMap<engine.wpak.data.Effect, AppliedEffect> _effects = new ConcurrentHashMap<>();
/**
* No Id Constructor
*/
+7 -3
View File
@@ -23,7 +23,10 @@ import engine.mbEnums.PowerFailCondition;
import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ApplyEffectMsg;
import engine.objects.*;
import engine.objects.AbstractCharacter;
import engine.objects.AbstractWorldObject;
import engine.objects.Item;
import engine.objects.PlayerCharacter;
import engine.powers.effectmodifiers.*;
import engine.server.MBServerStatics;
import engine.util.Hasher;
@@ -31,6 +34,7 @@ import engine.wpak.data.ConditionEntry;
import engine.wpak.data.Effect;
import engine.wpak.data.ModifierEntry;
import org.pmw.tinylog.Logger;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashSet;
@@ -148,8 +152,8 @@ public class EffectsBase {
eb.amount = entry.arg;
eb.amountRamp = (float) entry.curveType.getValue();
eb.useRampAdd = (float) entry.curveType.getValue() != 0;
eb.amountRamp = (float) entry.curveType.value;
eb.useRampAdd = (float) entry.curveType.value != 0;
break;
case Attack:
eb.cancelOnAttack = true;
@@ -20,7 +20,6 @@ import engine.powers.EffectsBase;
import engine.wpak.data.ModifierEntry;
import java.sql.ResultSet;
import java.sql.SQLException;
public abstract class AbstractEffectModifier {
@@ -52,9 +51,9 @@ public abstract class AbstractEffectModifier {
this.sourceType = SourceType.GetSourceType(this.type.replace(" ", "").replace("-", ""));
this.minMod = mod.min;
this.maxMod = mod.max;
this.percentMod = mod.value;
this.ramp = (float)mod.compoundCurveType.getValue();
this.useRampAdd = (float)mod.compoundCurveType.getValue() != 0;
this.percentMod = mod.percentage;
this.ramp = (float) mod.compoundCurveType.value;
this.useRampAdd = (float) mod.compoundCurveType.value != 0;
this.string1 = mod.arg1;
this.string2 = mod.arg2;
@@ -42,7 +42,7 @@ public class BlockedPowerTypeEffectModifier extends AbstractEffectModifier {
for (String effect : ac.getEffects().keySet()) {
Effect eff = ac.getEffects().get(effect);
ModType toBlock = ModType.None;
ModType toBlock = null;
switch (this.sourceType) {
case Invisible:
@@ -50,6 +50,10 @@ public class BlockedPowerTypeEffectModifier extends AbstractEffectModifier {
break;
}
if (toBlock == null)
return;
;
HashSet<AbstractEffectModifier> aemList = eff.getEffectModifiers();
for (AbstractEffectModifier aem : aemList) {
if (aem.modType.equals(toBlock)) {
@@ -10,6 +10,7 @@
package engine.powers.poweractions;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import engine.objects.AbstractCharacter;
import engine.objects.AbstractWorldObject;
import engine.objects.Item;
@@ -24,7 +25,7 @@ public abstract class AbstractPowerAction {
protected PowersBase parent;
protected int UUID;
protected String IDString;
protected String type;
protected mbEnums.PowerActionType type;
protected boolean isAggressive;
protected long validItemFlags;
@@ -46,7 +47,7 @@ public abstract class AbstractPowerAction {
this.isAggressive = powerAction.isAggressive;
}
public AbstractPowerAction(int uUID, String iDString, String type, boolean isAggressive,
public AbstractPowerAction(int uUID, String iDString, mbEnums.PowerActionType type, boolean isAggressive,
long validItemFlags) {
super();
UUID = uUID;
@@ -130,7 +131,7 @@ public abstract class AbstractPowerAction {
return this.validItemFlags;
}
public String getType() {
public mbEnums.PowerActionType getType() {
return type;
}
@@ -29,7 +29,7 @@ public class CharmPowerAction extends AbstractPowerAction {
public CharmPowerAction(PowerAction powerAction) {
super(powerAction);
this.levelCap = powerAction.levelCap;
this.levelCapRamp = powerAction.levelCurve.ordinal();
this.levelCapRamp = powerAction.levelCapCurve.ordinal();
}
@Override
@@ -30,7 +30,7 @@ public class FearPowerAction extends AbstractPowerAction {
public FearPowerAction(PowerAction powerAction) {
super(powerAction);
this.levelCap = powerAction.levelCap;
this.levelCapRamp = powerAction.levelCurve.ordinal();
this.levelCapRamp = powerAction.levelCapCurve.ordinal();
}
@Override
@@ -30,7 +30,7 @@ public class OpenGatePowerAction extends AbstractPowerAction {
super(powerAction);
}
public OpenGatePowerAction(int uUID, String iDString, String type, boolean isAggressive, long validItemFlags) {
public OpenGatePowerAction(int uUID, String iDString, mbEnums.PowerActionType type, boolean isAggressive, long validItemFlags) {
super(uUID, iDString, type, isAggressive, validItemFlags);
// TODO Auto-generated constructor stub
}
@@ -44,17 +44,13 @@ public class TransferStatPowerAction extends AbstractPowerAction {
this.powerAction = powerAction;
this.effectID = powerAction.effects.get(0).effect_id;
int flags = powerAction.getInt("flags");
this.transferRampAdd = ((flags & 4096) != 0) ? true : false;
this.transferEfficiencyRampAdd = ((flags & 8192) != 0) ? true : false;
this.targetToCaster = ((flags & 16384) != 0) ? true : false;
//int flags = powerAction.getInt("flags");
this.transferRampAdd = powerAction.statTransfer.rampCurve != null;
this.transferEfficiencyRampAdd = powerAction.statTransfer.rampCurve != null;
this.targetToCaster = powerAction.statTransfer.isDrain;
this.effect = effects.get(this.effectID);
try {
String damageString = powerAction.getString("damageType");
// Damage type can sometimes be null in the DB.
if (damageString.isEmpty() == false)
this.damageType = mbEnums.DamageType.getDamageType(damageString);
this.damageType = powerAction.damageType;
} catch (Exception e) {
this.damageType = null;
}
@@ -71,13 +67,13 @@ public class TransferStatPowerAction extends AbstractPowerAction {
public float getTransferAmount(float trains) {
// if (this.transferRampAdd)
return this.powerAction.statTransfer.fromStatValue + (this.transferRamp * trains);
return (float) (this.powerAction.statTransfer.ramp + (this.powerAction.statTransfer.rampCurve.value * trains));
// else
// return this.transferAmount * (1 + (this.transferRamp * trains));
}
public float getTransferEfficiency(float trains) {
return this.transferEfficiency + (this.transferEfficiencyRamp * trains);
return (float) (this.powerAction.statTransfer.efficiency + (this.powerAction.statTransfer.efficiencyCurve.value * trains));
}
public boolean targetToCaster() {
+24
View File
@@ -0,0 +1,24 @@
// ·. · · · · .
// · ·
// · ·
//
// · · ·
// Magicbane Emulator Project © 2013 - 2024
// www.magicbane.com
package engine.util;
public class Pair<A, B> {
public A first;
public B second;
public Pair(A first, B second) {
this.first = first;
this.second = second;
}
@Override
public String toString() {
return "Pair{" + "first=" + first + ", second=" + second + '}';
}
}
+13 -5
View File
@@ -13,12 +13,16 @@ import engine.mbEnums;
import engine.wpak.data.ConditionEntry;
import engine.wpak.data.Effect;
import engine.wpak.data.ModifierEntry;
import engine.wpakpowers.WpakPowerManager;
import org.pmw.tinylog.Logger;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -50,8 +54,12 @@ public class EffectsParser {
Matcher matcher = EFFECT_REGEX.matcher(fileContents);
while (matcher.find()) {
Effect effect = parseEffectEntry(matcher.group());
WpakPowerManager.effect_data.put(effect.effect_id, effect);
try {
Effect effect = parseEffectEntry(matcher.group());
WpakPowerManager._effectsLookup.put(effect.effect_id, effect);
}catch(Exception e){
Logger.error("EFFECT PARSE FAILED: " + e);
}
}
}
@@ -173,8 +181,8 @@ public class EffectsParser {
case Stamina:
modifierEntry.min = Float.parseFloat(modValues.get(1).trim());
modifierEntry.max = Float.parseFloat(modValues.get(2).trim());
modifierEntry.value = Float.parseFloat(modValues.get(3).trim());
// Parameter 4 is always 0.
modifierEntry.percentage = Float.parseFloat(modValues.get(3).trim());
modifierEntry.value = Float.parseFloat(modValues.get(4).trim()); // Always zero
modifierEntry.compoundCurveType = mbEnums.CompoundCurveType.valueOf(modValues.get(5).trim());
modifierEntry.arg1 = modValues.get(6).trim();
break;
+43 -42
View File
@@ -15,6 +15,7 @@ import engine.wpak.data.Effect;
import engine.wpak.data.PowerAction;
import engine.wpak.data.StatTransfer;
import engine.wpak.data.TrackEntry;
import engine.wpakpowers.WpakPowerManager;
import org.pmw.tinylog.Logger;
import java.io.IOException;
@@ -53,7 +54,7 @@ public class PowerActionParser {
while (matcher.find()) {
PowerAction powerAction = parsePowerActionEntry(matcher.group().trim());
WpakPowerManager.power_actions.put(Hasher.SBStringHash(powerAction.action_id),powerAction);
WpakPowerManager._powerActionLookup.put(Hasher.SBStringHash(powerAction.action_id), powerAction);
}
}
@@ -83,26 +84,26 @@ public class PowerActionParser {
Iterator<String> headerIterator = headerData.iterator();
powerAction.action_id = headerIterator.next();
powerAction.action_type = headerIterator.next();
powerAction.action_type = mbEnums.PowerActionType.valueOf(headerIterator.next());
switch (powerAction.action_type) {
case "RemoveEffect":
case RemoveEffect:
effect = new Effect();
effect.effect_id = headerIterator.next();
powerAction.effects.add(effect);
break;
case "CreateMob":
case CreateMob:
powerAction.petRace = Integer.parseInt(headerIterator.next());
powerAction.petLevel = Integer.parseInt(headerIterator.next());
break;
case "DamageOverTime":
case DamageOverTime:
effect = new Effect();
effect.effect_id = headerIterator.next();
effect.cycleDuration = Integer.parseInt(headerIterator.next());
effect.cycleDelay = Integer.parseInt(headerIterator.next());
powerAction.effects.add(effect);
break;
case "ApplyEffects":
case ApplyEffects:
int level = Integer.parseInt(headerIterator.next());
while (headerIterator.hasNext()) {
@@ -112,12 +113,12 @@ public class PowerActionParser {
powerAction.effects.add(effect);
}
break;
case "Transform":
case "Invis":
case "ApplyEffect":
case "DeferredPower":
case "DirectDamage":
case "SpireDisable":
case Transform:
case Invis:
case ApplyEffect:
case DeferredPower:
case DirectDamage:
case SpireDisable:
while (headerIterator.hasNext()) {
effect = new Effect();
effect.effect_id = headerIterator.next();
@@ -130,52 +131,52 @@ public class PowerActionParser {
powerAction.effects.add(effect);
}
break;
case "TransferStat":
case TransferStat:
statTransfer = new StatTransfer();
statTransfer.fromStat = mbEnums.CostType.valueOf(headerIterator.next());
statTransfer.toStat = mbEnums.CostType.valueOf(headerIterator.next());
statTransfer.fromStatValue = Float.parseFloat(headerIterator.next());
statTransfer.fromCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.toStatValue = Float.parseFloat(headerIterator.next());
statTransfer.toCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.ramp = Float.parseFloat(headerIterator.next());
statTransfer.rampCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.efficiency = Float.parseFloat(headerIterator.next());
statTransfer.efficiencyCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.fromStatBool = Boolean.parseBoolean(headerIterator.next());
statTransfer.toStatBool = Boolean.parseBoolean(headerIterator.next());
statTransfer.isDrain = Boolean.parseBoolean(headerIterator.next());
powerAction.statTransfer = statTransfer;
break;
case "TransferStatOT":
case TransferStatOT:
statTransfer = new StatTransfer();
statTransfer.fromStat = mbEnums.CostType.valueOf(headerIterator.next());
statTransfer.toStat = mbEnums.CostType.valueOf(headerIterator.next());
statTransfer.fromStatValue = Float.parseFloat(headerIterator.next());
statTransfer.fromCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.toStatValue = Float.parseFloat(headerIterator.next());
statTransfer.toCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.ramp = Float.parseFloat(headerIterator.next());
statTransfer.rampCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.efficiency = Float.parseFloat(headerIterator.next());
statTransfer.efficiencyCurve = mbEnums.CompoundCurveType.valueOf(headerIterator.next());
statTransfer.fromStatBool = Boolean.parseBoolean(headerIterator.next());
statTransfer.toStatBool = Boolean.parseBoolean(headerIterator.next());
statTransfer.isDrain = Boolean.parseBoolean(headerIterator.next());
statTransfer.transfer_action = headerIterator.next();
statTransfer.transfer_ticks = Integer.parseInt(headerIterator.next());
powerAction.statTransfer = statTransfer;
break;
case "Charm":
case Charm:
effect = new Effect();
effect.effect_id = headerIterator.next();
effect.level = Integer.parseInt(headerIterator.next());
effect.type = headerIterator.next();
powerAction.effects.add(effect);
break;
case "Block":
case Block:
effect = new Effect();
effect.effect_id = headerIterator.next();
effect.level = Integer.parseInt(headerIterator.next());
powerAction.effects.add(effect);
break;
case "Resurrect":
case Resurrect:
powerAction.levelCap = Integer.parseInt(headerIterator.next());
break;
case "SetItemFlag":
case SetItemFlag:
powerAction.itemFlag = mbEnums.ItemFlags.valueOf(headerIterator.next());
break;
case "Track":
case Track:
trackEntry = new TrackEntry();
trackEntry.action_id = headerIterator.next();
trackEntry.trackPlayer = Boolean.parseBoolean(headerIterator.next());
@@ -185,21 +186,21 @@ public class PowerActionParser {
trackEntry.max = Integer.parseInt(headerIterator.next());
powerAction.trackEntry = trackEntry;
break;
case "Teleport":
case Teleport:
if (headerIterator.hasNext())
powerAction.ignoreNoTeleSpire = Boolean.parseBoolean(headerIterator.next());
break;
case "Recall": // No arguments for these tags or not parsed
case "Summon":
case "TreeChoke":
case "SimpleDamage":
case "MobRecall": // One argument always zero
case "ClearAggro":
case "ClearNearbyAggro":
case "Peek":
case "ClaimMine":
case "RunegateTeleport":
case "Steal":
case Recall: // No arguments for these tags or not parsed
case Summon:
case TreeChoke:
case SimpleDamage:
case MobRecall: // One argument always zero
case ClearAggro:
case ClearNearbyAggro:
case Peek:
case ClaimMine:
case RunegateTeleport:
case Steal:
break;
default:
Logger.error("Unhandled type " + powerAction.action_type + " for Pow4erAction: " + powerAction.action_id);
@@ -273,7 +274,7 @@ public class PowerActionParser {
powerAction.levelCap = Integer.parseInt(arguments.get(0));
if (arguments.size() > 1) // Not all level caps have a curve
powerAction.levelCurve = mbEnums.CompoundCurveType.valueOf(arguments.get(1));
powerAction.levelCapCurve = mbEnums.CompoundCurveType.valueOf(arguments.get(1));
break;
case "CLEARAGGRO":
powerAction.clearAggro = Boolean.parseBoolean(lineValues.get(1).trim());
+143 -137
View File
@@ -12,6 +12,7 @@ import engine.gameManager.ConfigManager;
import engine.mbEnums;
import engine.util.Hasher;
import engine.wpak.data.*;
import engine.wpakpowers.WpakPowerManager;
import org.pmw.tinylog.Logger;
import java.io.IOException;
@@ -51,7 +52,7 @@ public class PowersParser {
while (matcher.find()) {
Power power = parsePowerEntry(matcher.group().trim());
WpakPowerManager.powers.put(Hasher.SBStringHash(power.power_id),power);
WpakPowerManager._powersLookup.put(Hasher.SBStringHash(power.power_id), power);
}
}
@@ -105,7 +106,7 @@ public class PowersParser {
PowerEntry power = new PowerEntry();
power.power_type = mbEnums.PowerType.valueOf(iterator.next());
power.icon = Integer.parseInt(iterator.next());
power.powerBase = iterator.next().replaceAll("\"", "");
power.focusLine = iterator.next().replaceAll("\"", "");
powerEntry.powers.add(power);
String nextValue = iterator.next();
@@ -116,7 +117,7 @@ public class PowersParser {
power = new PowerEntry();
power.power_type = mbEnums.PowerType.valueOf(nextValue);
power.icon = Integer.parseInt(iterator.next());
power.powerBase = iterator.next().replaceAll("\"", "");
power.focusLine = iterator.next().replaceAll("\"", "");
powerEntry.powers.add(power);
powerEntry.target_type = mbEnums.PowerTargetType.valueOf(iterator.next());
} else
@@ -154,147 +155,152 @@ public class PowersParser {
List<String> arguments;
Matcher argumentMatcher;
switch (key) {
case "ACTION":
actionEntry = new ActionEntry();
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
actionEntry.effect_id = arguments.get(0);
actionEntry.minTrains = Integer.parseInt(arguments.get(1));
actionEntry.maxTrains = Integer.parseInt(arguments.get(2));
actionEntry.duration = Float.parseFloat(arguments.get(3));
actionEntry.curve = mbEnums.CompoundCurveType.valueOf(arguments.get(4));
actionEntry.stackingCategory = arguments.get(5);
actionEntry.stackingPriority = Integer.parseInt(arguments.get(6));
actionEntry.categoryToPower = mbEnums.CategoryToPowerType.valueOf(arguments.get(7));
powerEntry.actionEntries.add(actionEntry);
break;
case "MaxLevel":
powerEntry.maxLevel = Integer.parseInt(lineValues.get(1).trim());
break;
case "HateValue":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
powerEntry.hateValue = Integer.parseInt(arguments.get(0));
switch (key) {
case "ACTION":
actionEntry = new ActionEntry();
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
actionEntry.action_id = arguments.get(0);
actionEntry.minTrains = Integer.parseInt(arguments.get(1));
actionEntry.maxTrains = Integer.parseInt(arguments.get(2));
actionEntry.duration = Float.parseFloat(arguments.get(3));
actionEntry.curve = mbEnums.CompoundCurveType.valueOf(arguments.get(4));
actionEntry.stackingCategory = arguments.get(5);
actionEntry.stackingPriority = Integer.parseInt(arguments.get(6));
actionEntry.categoryToPower = mbEnums.CategoryToPowerType.valueOf(arguments.get(7));
powerEntry.actionEntries.add(actionEntry);
break;
case "MaxLevel":
powerEntry.maxLevel = Integer.parseInt(lineValues.get(1).trim());
break;
case "HateValue":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
powerEntry.hateValue = Integer.parseInt(arguments.get(0));
// Not all entries have a curve. Defaults to DefaultFlat;
// Not all entries have a curve. Defaults to DefaultFlat;
if (arguments.size() > 1)
powerEntry.hateCurve = mbEnums.CompoundCurveType.valueOf(arguments.get(1));
break;
case "LOOPANIMID":
powerEntry.loopAnimID = Integer.parseInt(lineValues.get(1).trim());
break;
case "GRANTOVERRIDEVAR":
powerEntry.grantOverrideVar = lineValues.get(1).trim();
break;
case "DESCRIPTION":
powerEntry.description.add(lineValues.get(1).trim());
break;
case "CATEGORY":
powerEntry.category = lineValues.get(1).trim();
break;
case "CURVE":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
powerEntry.curves.put(arguments.get(0), mbEnums.CompoundCurveType.valueOf(arguments.get(1)));
break;
case "EQPREREQ":
argumentMatcher = STRSPLIT_REGEX.matcher(lineValues.get(1).trim());
arguments = new ArrayList<>();
if (arguments.size() > 1)
powerEntry.hateCurve = mbEnums.CompoundCurveType.valueOf(arguments.get(1));
break;
case "LOOPANIMID":
powerEntry.loopAnimID = Integer.parseInt(lineValues.get(1).trim());
break;
case "GRANTOVERRIDEVAR":
powerEntry.grantOverrideVar = lineValues.get(1).trim();
break;
case "DESCRIPTION":
powerEntry.description.add(lineValues.get(1).trim());
break;
case "CATEGORY":
powerEntry.category = mbEnums.PowerCategoryType.valueOf(lineValues.get(1).trim());
break;
case "CURVE":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
powerEntry.curves.put(arguments.get(0), mbEnums.CompoundCurveType.valueOf(arguments.get(1)));
break;
case "EQPREREQ":
argumentMatcher = STRSPLIT_REGEX.matcher(lineValues.get(1).trim());
arguments = new ArrayList<>();
while (argumentMatcher.find())
arguments.add(argumentMatcher.group().trim());
while (argumentMatcher.find())
arguments.add(argumentMatcher.group().trim());
argumentIterator = arguments.iterator();
argumentIterator = arguments.iterator();
while (argumentIterator.hasNext()) {
EquipmentPreReq equipmentPreReq = new EquipmentPreReq();
equipmentPreReq.slot = mbEnums.EquipSlotType.valueOf(arguments.get(0));
equipmentPreReq.skill = arguments.get(1).replaceAll("\"", "");
equipmentPreReq.required = Integer.parseInt(arguments.get(2));
powerEntry.equipmentPreReq.add(equipmentPreReq);
}
break;
case "CANCASTWHILEMOVING":
powerEntry.canCastWhileMoving = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "CANCASTWHILEFLYING":
powerEntry.canCastWhileFlying = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "BLADETRAILS":
powerEntry.bladeTrails = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "EFFECTPREREQ":
Effect effectPreReq = new Effect();
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
effectPreReq.effect_id = arguments.get(9);
effectPreReq.level = Integer.parseInt(arguments.get(1));
effectPreReq.message = arguments.get(2);
powerEntry.effectPreReqs.add(effectPreReq);
break;
case "MONSTERTYPERESTRICTS":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
while (argumentIterator.hasNext()) {
EquipmentPreReq equipmentPreReq = new EquipmentPreReq();
equipmentPreReq.slot = mbEnums.EquipSlotType.valueOf(argumentIterator.next());
equipmentPreReq.skill = argumentIterator.next().replaceAll("\"", "");
for (String restriction : arguments)
powerEntry.monsterRestricts.add(mbEnums.MonsterType.valueOf(restriction.trim()));
break;
case "MONSTERTYPEPREREQS":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
if (argumentIterator.hasNext())
equipmentPreReq.required = Integer.parseInt(argumentIterator.next());
else
equipmentPreReq.required = 0;
for (String restriction : arguments)
powerEntry.monsterPrereqs.add(mbEnums.MonsterType.valueOf(restriction.trim()));
break;
case "SHOULDCHECKPATH":
powerEntry.shouldCheckPath = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "STICKY":
powerEntry.sticky = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "PULSEINFO":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
powerEntry.pulseCycle = Integer.parseInt(arguments.get(0));
powerEntry.pulseDuration = Integer.parseInt(arguments.get(1));
break;
case "MAXNUMMOBTARGETS":
powerEntry.maxMobTargets = Integer.parseInt(lineValues.get(1).trim());
break;
case "MAXNUMPLAYERTARGETS":
powerEntry.maxPlayerTargets = Integer.parseInt(lineValues.get(1).trim());
break;
case "ISADMINPOWER":
powerEntry.isAdminPower = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "ISPROJECTILE":
powerEntry.isProjectile = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "CASTERSPULSEPARTICLE":
powerEntry.casterPulseParticle = Integer.parseInt(lineValues.get(1).trim());
break;
case "TARGETEFFECTPREREQS_ORED":
Effect preReq = new Effect();
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
preReq.effect_id = arguments.get(0);
preReq.level = Integer.parseInt(arguments.get(1));
powerEntry.targetEffectPrereqs.add(preReq);
break;
case "SOUNDS": // Values not parsed
case "APPLYDAMAGESELF":
case "APPLYDAMAGECASTER":
case "APPLYDAMAGEOTHER":
case "APPLYDAMAGETARGET":
case "APPLYEFFECTSELF":
case "APPLYEFFECTOTHER":
case "APPLYEFFECTCASTER":
case "APPLYEFFECTTARGET":
case "FIZZLEOTHER":
case "FIZZLESELF":
case "INITSTRING":
case "SUCCESSOTHER":
case "SUCCESSSELF":
case "WEAROFFEFFECTOTHER":
case "WEAROFFEFFECTSELF":
break;
default:
Logger.error("Unhandled variable type:" + key + " for power: " + powerEntry.power_id);
}
powerEntry.equipmentPreReq.add(equipmentPreReq);
}
break;
case "CANCASTWHILEMOVING":
powerEntry.canCastWhileMoving = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "CANCASTWHILEFLYING":
powerEntry.canCastWhileFlying = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "BLADETRAILS":
powerEntry.bladeTrails = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "EFFECTPREREQ":
Effect effectPreReq = new Effect();
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
effectPreReq.effect_id = arguments.get(9);
effectPreReq.level = Integer.parseInt(arguments.get(1));
effectPreReq.message = arguments.get(2);
powerEntry.effectPreReqs.add(effectPreReq);
break;
case "MONSTERTYPERESTRICTS":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
for (String restriction : arguments)
powerEntry.monsterRestricts.add(mbEnums.MonsterType.valueOf(restriction.trim()));
break;
case "MONSTERTYPEPREREQS":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
for (String restriction : arguments)
powerEntry.monsterPrereqs.add(mbEnums.MonsterType.valueOf(restriction.trim()));
break;
case "SHOULDCHECKPATH":
powerEntry.shouldCheckPath = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "STICKY":
powerEntry.sticky = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "PULSEINFO":
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
powerEntry.pulseCycle = Integer.parseInt(arguments.get(0));
powerEntry.pulseDuration = Integer.parseInt(arguments.get(1));
break;
case "MAXNUMMOBTARGETS":
powerEntry.maxMobTargets = Integer.parseInt(lineValues.get(1).trim());
break;
case "MAXNUMPLAYERTARGETS":
powerEntry.maxPlayerTargets = Integer.parseInt(lineValues.get(1).trim());
break;
case "ISADMINPOWER":
powerEntry.isAdminPower = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "ISPROJECTILE":
powerEntry.isProjectile = Boolean.parseBoolean(lineValues.get(1).trim());
break;
case "CASTERSPULSEPARTICLE":
powerEntry.casterPulseParticle = Integer.parseInt(lineValues.get(1).trim());
break;
case "TARGETEFFECTPREREQS_ORED":
Effect preReq = new Effect();
arguments = Arrays.asList(lineValues.get(1).trim().split("\\s+"));
preReq.effect_id = arguments.get(0);
preReq.level = Integer.parseInt(arguments.get(1));
powerEntry.targetEffectPrereqs.add(preReq);
break;
case "SOUNDS": // Values not parsed
case "APPLYDAMAGESELF":
case "APPLYDAMAGECASTER":
case "APPLYDAMAGEOTHER":
case "APPLYDAMAGETARGET":
case "APPLYEFFECTSELF":
case "APPLYEFFECTOTHER":
case "APPLYEFFECTCASTER":
case "APPLYEFFECTTARGET":
case "FIZZLEOTHER":
case "FIZZLESELF":
case "INITSTRING":
case "SUCCESSOTHER":
case "SUCCESSSELF":
case "WEAROFFEFFECTOTHER":
case "WEAROFFEFFECTSELF":
break;
default:
Logger.error("Unhandled variable type:" + key + " for power: " + powerEntry.power_id);
}
}
// Parse power conditions
-376
View File
@@ -1,376 +0,0 @@
package engine.wpak;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.*;
import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.FinishRecycleTimeJob;
import engine.jobs.UsePowerJob;
import engine.jobs.WpakUsePowerJob;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ModifyHealthMsg;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.RecyclePowerMsg;
import engine.net.client.msg.UpdateStateMsg;
import engine.objects.*;
import engine.powers.PowersBase;
import engine.server.MBServerStatics;
import engine.util.Hasher;
import engine.wpak.data.*;
import engine.wpak.data.Effect;
import org.pmw.tinylog.Logger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import static engine.math.FastMath.sqr;
public class WpakPowerManager {
public static HashMap<String, Effect> effect_data = new HashMap<>();
public static HashMap<Integer, PowerAction> power_actions= new HashMap<>();
public static HashMap<Integer, Power> powers= new HashMap<>();
private static JobScheduler js;
public static void usePower(final PerformActionMsg msg, ClientConnection origin, boolean sendCastToSelf) {
if (ConfigManager.MB_RULESET.getValue().equals("LORE")) {
PowersBase pb = PowersManager.powersBaseByToken.get(msg.getPowerUsedID());
PlayerCharacter caster = origin.getPlayerCharacter();
PlayerCharacter target = PlayerCharacter.getFromCache(msg.getTargetID());
if (pb != null && pb.enforceLore()) {
//if (caster.guild.equals(Guild.getErrantGuild()))
// return;
if (target != null && caster.guild.getGuildType().equals(target.guild.getGuildType()) == false && target.getObjectType().equals(mbEnums.GameObjectType.Building) == false) {
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), recyclePowerMsg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
// Send Fail to cast message
PlayerCharacter pc = SessionManager
.getPlayerCharacter(origin);
if (pc != null) {
sendPowerMsg(pc, 2, msg);
if (pc.isCasting()) {
pc.update();
}
pc.setIsCasting(false);
}
return;
}
}
}
if (castPower(msg, origin, sendCastToSelf)) {
// Cast failed for some reason, reset timer
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), recyclePowerMsg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
// Send Fail to cast message
PlayerCharacter pc = SessionManager
.getPlayerCharacter(origin);
if (pc != null) {
sendPowerMsg(pc, 2, msg);
if (pc.isCasting()) {
pc.update();
}
pc.setIsCasting(false);
}
}
}
private static boolean castPower(final PerformActionMsg msg, ClientConnection origin, boolean sendCastToSelf) {
//check to see if the caster is valid
PlayerCharacter playerCharacter = SessionManager.getPlayerCharacter(origin);
if (playerCharacter == null)
return false;
//make sure player is still alive
if (!playerCharacter.isAlive() && msg.getPowerUsedID() != 428589216) { //succor
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(playerCharacter, recyclePowerMsg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
return false;
}
//make sure the recycle timer has actually elapsed
if (playerCharacter.getRecycleTimers().containsKey(msg.getPowerUsedID())) {
Logger.warn("usePowerA(): Cheat attempted? '" + msg.getPowerUsedID() + "' recycle timer not finished " + playerCharacter.getName());
return false;
}
//lookup the power that was cast
Power powerCast = powers.get(msg.getPowerUsedID());
if (powerCast == null) {
ChatManager.chatSayInfo(playerCharacter, "This power is not implemented yet.");
return true;
}
if (playerCharacter.getLastPower() != null)
return true;
// get numTrains for power
int trains = msg.getNumTrains();
if (trains > powerCast.maxLevel) {
trains = powerCast.maxLevel;
msg.setNumTrains(trains);
}
//sanity check for amount of trains in spell cast
if (playerCharacter.getPowers() != null && playerCharacter.getPowers().containsKey(msg.getPowerUsedID())) {
CharacterPower cp = playerCharacter.getPowers().get(msg.getPowerUsedID());
if (cp != null) {
int tot = cp.getTotalTrains();
if (tot == 0)
return false;
if (trains != tot) {
trains = tot;
msg.setNumTrains(trains);
}
}
}
//get casting time
int time = powerCast.getRecycleTime(trains);
//combat mode sanity check
if (playerCharacter.isCombat()) {
if (!powerCast.allowedInCombat())
return true;
} else if (!powerCast.allowedOutOfCombat())
return true;
//stunned check
PlayerBonuses bonus = playerCharacter.getBonuses();
mbEnums.SourceType sourceType = mbEnums.SourceType.GetSourceType(powerCast.category);
if (bonus != null && (bonus.getBool(mbEnums.ModType.Stunned, mbEnums.SourceType.None) || bonus.getBool(mbEnums.ModType.CannotCast, mbEnums.SourceType.None) || bonus.getBool(mbEnums.ModType.BlockedPowerType, sourceType)))
return true;
//sanity check for casting while moving
Vector3fImmutable endLoc = playerCharacter.getEndLoc();
if (!powerCast.canCastWhileMoving)
if (playerCharacter.isMoving()) {
float distanceLeftSquared = endLoc.distanceSquared2D(playerCharacter.getLoc());
if (distanceLeftSquared > sqr(playerCharacter.getSpeed()))
return true;
}
//get the actual target form the message
int type = msg.getTargetType();
int UUID = msg.getTargetID();
if (type == -1 || type == 0 || UUID == -1 || UUID == 0)
return true;
AbstractWorldObject target = (AbstractWorldObject) DbManager.getObject(mbEnums.GameObjectType.values()[type], UUID);
//check to make sure power can be cast on building if target is a building
if (target != null && target.getObjectType() == mbEnums.GameObjectType.Building && !powerCast.target_type.equals(mbEnums.PowerTargetType.BUILDING)) {
PowersManager.sendPowerMsg(playerCharacter, 9, new PerformActionMsg(msg));
return true;
}
//validate casting range
if (playerCharacter.getLoc().distanceSquared2D(msg.getTargetLoc()) > (powerCast.range * powerCast.range))
return true;
//validate prereqs for power cast
//equipment prereqs
if (!powerCast.equipmentPreReq.isEmpty()) {
for (EquipmentPreReq prereq : powerCast.equipmentPreReq) {
String requiredSkill = prereq.skill;
if (playerCharacter.charItemManager.equipped.get(prereq.slot) != null) {
Item equippedItem = playerCharacter.charItemManager.equipped.get(prereq.slot);
if (!equippedItem.template.item_skill_mastery_used.equals(requiredSkill) && !equippedItem.template.item_skill_used.equals(requiredSkill))
return true;
} else {
return true;
}
}
}
//effect prereqs
if (!powerCast.effectPreReqs.isEmpty()) {
for (Effect prereq : powerCast.effectPreReqs) {
if (!playerCharacter.effects.contains(prereq.effect_id) && !playerCharacter.effects.contains(prereq.effect_name))
return true;
}
}
float cost = powerCast.getCost(trains);
if (bonus != null)
cost *= (1 + bonus.getFloatPercentAll(mbEnums.ModType.PowerCost, mbEnums.SourceType.None));
if (playerCharacter.getAltitude() > 0)
cost *= 1.5f;
if (cost > 0)
if ((playerCharacter.getObjectTypeMask() & MBServerStatics.MASK_UNDEAD) != 0)
if (playerCharacter.getHealth() <= cost)
return true;
else {
playerCharacter.modifyHealth(-cost, playerCharacter, true);
ModifyHealthMsg mhm = new ModifyHealthMsg(playerCharacter, playerCharacter, -cost,
0f, 0f, 0, null,
9999, 0);
mhm.setOmitFromChat(1);
DispatchManager.dispatchMsgToInterestArea(playerCharacter, mhm, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
}
else if (powerCast.costType.name().equals("MANA"))
if (playerCharacter.getMana() < cost)
return true;
else
playerCharacter.modifyMana(-cost, playerCharacter, true);
else if (powerCast.costType.name().equals("STAMINA"))
if (playerCharacter.getStamina() < cost)
return true;
else
playerCharacter.modifyStamina(-cost, playerCharacter, true);
else if (playerCharacter.getHealth() <= cost)
return true;
else
playerCharacter.modifyHealth(-cost, playerCharacter, true);
if (time > 0) {
FinishRecycleTimeJob frtj = new FinishRecycleTimeJob(playerCharacter, msg);
playerCharacter.getRecycleTimers().put(msg.getPowerUsedID(), js.scheduleJob(frtj, time));
} else {
// else send recycle message to unlock power
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(playerCharacter, recyclePowerMsg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
}
int tr = msg.getNumTrains();
DispatchManager.dispatchMsgToInterestArea(playerCharacter, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, sendCastToSelf, false);
//Make new msg..
PerformActionMsg copyMsg = new PerformActionMsg(msg);
copyMsg.setNumTrains(tr);
// make person casting stand up if spell (unless they're casting a chant which does not make them stand up)
if (powerCast.isSpell() && !powerCast.isChant() && playerCharacter.isSit()) {
playerCharacter.update();
playerCharacter.setSit(false);
UpdateStateMsg updateStateMsg = new UpdateStateMsg(playerCharacter);
DispatchManager.dispatchMsgToInterestArea(playerCharacter, updateStateMsg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
}
// update cast (use skill) fail condition
playerCharacter.cancelOnCast();
// update castSpell (use spell) fail condition if spell
if (powerCast.isSpell())
playerCharacter.cancelOnSpell();
// get cast time in ms.
time = powerCast.getCastTime(trains);
// set player is casting for regens
if (time > 100) {
playerCharacter.update();
playerCharacter.setIsCasting(true);
}
playerCharacter.setLastMovementState(playerCharacter.getMovementState());
// run timer job to end cast
if (time < 1) // run immediately
finishUsePower(copyMsg, playerCharacter, target);
else {
WpakUsePowerJob upj = new WpakUsePowerJob(playerCharacter, copyMsg, target);
JobContainer jc = js.scheduleJob(upj, time);
// make lastPower
playerCharacter.setLastPower(jc);
}
return false;
}
public static void finishUsePower(PerformActionMsg msg, PlayerCharacter caster, AbstractWorldObject target){
Power powerUsed = powers.get(msg.getPowerUsedID());
if(powerUsed == null)
return;
if(powerUsed.maxMobTargets > 1 || powerUsed.maxPlayerTargets > 1){
AoeHandler(caster, target, powerUsed);
}else{
applyAllPowerEffects(powerUsed, target);
}
}
private static void AoeHandler(PlayerCharacter caster, AbstractWorldObject target, Power powerUsed){
HashSet<AbstractWorldObject> mobTargets = new HashSet<>();
HashSet<AbstractWorldObject> pcTargets = new HashSet<>();
if(powerUsed.maxMobTargets > 0)
mobTargets = WorldGrid.getObjectsInRangePartial(target.loc,powerUsed.areaRange, MBServerStatics.MASK_MOB);
if(powerUsed.maxPlayerTargets > 0)
pcTargets = WorldGrid.getObjectsInRangePartial(target.loc,powerUsed.areaRange, MBServerStatics.MASK_PLAYER);
int count = 1;
for(AbstractWorldObject mob : mobTargets){
if(count < powerUsed.maxMobTargets + 1){
applyAllPowerEffects(powerUsed,mob);
count ++;
}else{
break;
}
}
count = 1;
for(AbstractWorldObject pc : pcTargets){
if(count < powerUsed.maxPlayerTargets + 1){
applyAllPowerEffects(powerUsed,pc);
count ++;
}else{
break;
}
}
}
public static void applyAllPowerEffects(Power power, AbstractWorldObject target){
for(ActionEntry powerAction: power.actionEntries){
Effect eff = effect_data.get(Hasher.SBStringHash(powerAction.effect_id));
if(eff == null)
continue;
//TODO add in effect application
}
}
public static void sendPowerMsg(PlayerCharacter playerCharacter, int type, PerformActionMsg msg) {
if (playerCharacter == null)
return;
msg.setUnknown05(type);
switch (type) {
case 3:
case 4:
msg.setUnknown04(2);
DispatchManager.dispatchMsgToInterestArea(playerCharacter, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
break;
default:
msg.setUnknown04(1);
Dispatch dispatch = Dispatch.borrow(playerCharacter, msg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ import engine.mbEnums;
public class ActionEntry {
public String effect_id;
public String action_id;
public int minTrains;
public int maxTrains;
public float duration;
+16 -2
View File
@@ -8,10 +8,9 @@
package engine.wpak.data;
import engine.powers.effectmodifiers.AbstractEffectModifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Objects;
public class Effect {
public String effect_id;
@@ -34,4 +33,19 @@ public class Effect {
public String message;
public int cycleDuration;
public int cycleDelay;
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Effect effect = (Effect) o;
return Objects.equals(effect_id, effect.effect_id);
}
@Override
public int hashCode() {
return effect_id.hashCode(); // Use only the id field for hashCode
}
}
+1
View File
@@ -14,6 +14,7 @@ public class ModifierEntry {
public mbEnums.ModType type;
public float min;
public float max;
public float percentage;
public float value;
public mbEnums.CompoundCurveType compoundCurveType;
public String arg1; // ItemName "Masterwork" ""
+17 -44
View File
@@ -9,11 +9,11 @@
package engine.wpak.data;
import engine.mbEnums;
import engine.objects.AbstractWorldObject;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Objects;
public class Power {
public String power_id;
@@ -47,7 +47,7 @@ public class Power {
public String grantOverrideVar;
public ArrayList<String> description = new ArrayList<>();
public HashMap<String, mbEnums.CompoundCurveType> curves = new HashMap<>();
public String category;
public mbEnums.PowerCategoryType category;
public boolean canCastWhileMoving = false;
public boolean bladeTrails = false;
public ArrayList<Effect> effectPreReqs = new ArrayList<>();
@@ -67,55 +67,28 @@ public class Power {
public boolean isProjectile = false;
public HashMap<String, Float> conditions = new HashMap<>();
public int getRecycleTime(int trains) { // returns cast time in ms
if (this.curves.get("RECYCLETIME") != null)
return (int) (((this.recycle_time + (this.curves.get("RECYCLETIME").getValue() * trains)) * 1000) + getCastTime(trains));
else
return (int) (((this.recycle_time * (1 + (this.curves.get("RECYCLETIME").getValue() * trains))) * 1000) + getCastTime(trains));
}
public int getCastTime(int trains) { // returns cast time in ms
if (this.curves.get("INITTIME") != null)
return (int) ((this.init_time + (this.curves.get("INITTIME").getValue() * trains)) * 1000);
else
return (int) ((this.init_time * (1 + (this.curves.get("INITTIME").getValue() * trains))) * 1000);
}
public boolean allowedInCombat() {
switch(castingMode.name()){
case "NONE":
case "BOTH":
case "COMBAT":
return true;
}
return false;
}
public boolean allowedOutOfCombat() {
switch(castingMode.name()){
case "NONE":
case "BOTH":
case "NONCOMBAT":
return true;
}
return false;
}
public float getCost(int trains) {
if (this.curves.get("COSTAMT") != null)
return this.cost + (float)(this.curves.get("COSTAMT").getValue() * trains);
else
return this.cost * (1 + (float)(this.curves.get("COSTAMT").getValue() * trains));
}
public boolean isSpell(){
return true;
}
public boolean isSkill(){
return true;
}
public boolean isChant(){
return true;
}
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Power power = (Power) o;
return Objects.equals(power_id, power.power_id);
}
@Override
public int hashCode() {
return power_id.hashCode(); // Use only the id field for hashCode
}
}
+16 -2
View File
@@ -11,19 +11,20 @@ package engine.wpak.data;
import engine.mbEnums;
import java.util.ArrayList;
import java.util.Objects;
public class PowerAction {
// Header values
public String action_id;
public String action_type;
public mbEnums.PowerActionType action_type;
public ArrayList<Effect> effects = new ArrayList<>();
public int petLevel;
public int petRace;
public StatTransfer statTransfer;
public int levelCap;
public mbEnums.CompoundCurveType levelCurve;
public mbEnums.CompoundCurveType levelCapCurve;
public TrackEntry trackEntry;
// Additional variables after header go here.
@@ -50,5 +51,18 @@ public class PowerAction {
public int splashDamageMax;
public boolean ignoreNoTeleSpire = false;
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
PowerAction powerAction = (PowerAction) o;
return Objects.equals(action_id, powerAction.action_id);
}
@Override
public int hashCode() {
return action_id.hashCode(); // Use only the id field for hashCode
}
}
+1 -1
View File
@@ -13,5 +13,5 @@ import engine.mbEnums;
public class PowerEntry {
public mbEnums.PowerType power_type;
public int icon;
public String powerBase;
public String focusLine;
}
+5 -5
View File
@@ -12,13 +12,13 @@ import engine.mbEnums;
public class StatTransfer {
public mbEnums.CostType fromStat;
public float fromStatValue;
public mbEnums.CompoundCurveType fromCurve;
public float ramp;
public mbEnums.CompoundCurveType rampCurve;
public mbEnums.CostType toStat;
public float toStatValue;
public mbEnums.CompoundCurveType toCurve;
public float efficiency;
public mbEnums.CompoundCurveType efficiencyCurve;
public boolean fromStatBool;
public boolean toStatBool;
public boolean isDrain;
public String transfer_action;
public int transfer_ticks;
}
+190
View File
@@ -0,0 +1,190 @@
// ·. · · · · .
// · ·
// · ·
//
// · · ·
// Magicbane Emulator Project © 2013 - 2024
// www.magicbane.com
package engine.wpakpowers;
import engine.objects.AbstractCharacter;
import engine.objects.AbstractWorldObject;
import engine.wpak.data.Effect;
import engine.wpak.data.ModifierEntry;
import engine.wpak.data.Power;
import engine.wpak.data.PowerAction;
public class Actions {
public static void ApplyEffects(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
// Iterate effects for this powerAction and apply
for (Effect effect : powerAction.effects) {
// Create pojo to hold effect/modifiers stored in AWO
AppliedEffect appliedEffect = new AppliedEffect();
appliedEffect.effect = effect;
appliedEffect.rank = rank;
// Add modifier objects from behaviours to pojo.
// Anything from a float to an array can be returned
// based on the needs of the behaviour.
for (ModifierEntry modifierEntry : effect.mods) {
Object modifier = modifierEntry.type.behaviorType.apply(caster, power, rank, target,
powerAction, effect, modifierEntry);
appliedEffect.modifiers.put(modifierEntry.type, modifier);
}
// Add this power effect to the target
// or overwrite the old value
target._effects.put(effect, appliedEffect);
}
// target.updateBonuses() here?
}
public static void Block(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Charm(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void ClaimMine(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void ClearAggro(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void ClearNearbyAggro(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Confusion(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void CreateMob(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void DamageOverTime(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void DeferredPower(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void DirectDamage(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Invis(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void MobRecall(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Peek(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Recall(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void RemoveEffect(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Resurrect(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void RunegateTeleport(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void SetItemFlag(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void SimpleDamage(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void SpireDisable(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Steal(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Summon(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Teleport(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Track(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void TransferStat(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void TransferStatOT(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void Transform(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
public static void TreeChoke(AbstractCharacter caster, Power power,
Integer rank, AbstractWorldObject target, PowerAction powerAction) {
System.out.println("PowerAction method called");
}
}
+22
View File
@@ -0,0 +1,22 @@
// ·. · · · · .
// · ·
// · ·
//
// · · ·
// Magicbane Emulator Project © 2013 - 2024
// www.magicbane.com
package engine.wpakpowers;
import engine.mbEnums;
import engine.wpak.data.Effect;
import java.util.concurrent.ConcurrentHashMap;
public class AppliedEffect {
public Effect effect;
public int rank;
public ConcurrentHashMap<mbEnums.ModType, Object> modifiers = new ConcurrentHashMap<>();
}
+125
View File
@@ -0,0 +1,125 @@
// ·. · · · · .
// · ·
// · ·
//
// · · ·
// Magicbane Emulator Project © 2013 - 2024
// www.magicbane.com
package engine.wpakpowers;
import engine.mbEnums;
import engine.objects.AbstractCharacter;
import engine.objects.AbstractWorldObject;
import engine.util.Pair;
import engine.wpak.data.Effect;
import engine.wpak.data.ModifierEntry;
import engine.wpak.data.Power;
import engine.wpak.data.PowerAction;
import java.util.ArrayList;
public class Behaviours {
public static Object Flag(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return true;
}
public static Object MapIntToInts(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return powerAction.attackAnimations.clone();
}
public static Object Standard(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return WpakPowerManager.getModifierValues(modifierEntry, rank).first;
}
public static Object FPSubTypeAttr(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return WpakPowerManager.getModifierValues(modifierEntry, rank).first;
}
public static Object SubTypeSourceType(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return mbEnums.SourceType.valueOf(modifierEntry.arg1);
}
public static Object SubTypePowerType(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return modifierEntry.arg1;
}
public static Object SubTypeSkill(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return null; // Unused in data
}
public static Object FPSubTypeDmg(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
String key = modifierEntry.arg1;
float modifierValue = WpakPowerManager.getModifierValues(modifierEntry, rank).first;
return new Pair<>(key, modifierValue);
}
public static Object DD(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
WpakPowerManager.DirectDamageHandler(caster,target,power,rank,modifierEntry);
return null;
}
public static Object StringBehaviour(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return new Pair<>(modifierEntry.arg1, modifierEntry.arg2); // We should filter this. No purpose.
}
public static Object SubTypeMod(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
mbEnums.ModType noMod = mbEnums.ModType.valueOf(modifierEntry.arg1);
ArrayList<Effect> removeList = new ArrayList<>();
// Iterate through effects on target slating to remove
// all which match the intended modType
for (AppliedEffect appliedEffect : target._effects.values())
if (appliedEffect.modifiers.containsKey(noMod))
removeList.add(appliedEffect.effect);
for (Effect effectEntry : removeList)
target._effects.remove(effectEntry); // wpakPowerManager.removeEffect() instead?
// target.updateBonuses?
return noMod;
}
public static Object SubTypePower(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return power.category;
}
public static Object SubTypeDmg(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return power.category;
}
public static Object FPSubTypeSkill(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
return WpakPowerManager.getModifierValues(modifierEntry, rank);
}
public static Object FPSubTypeMonster(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
System.out.println("Behavior method called");
return null;
}
public static Object ProcInfo(AbstractCharacter caster, Power power, Integer rank, AbstractWorldObject target,
PowerAction powerAction, Effect effect, ModifierEntry modifierEntry) {
System.out.println("Behavior method called");
return null;
}
}
+537
View File
@@ -0,0 +1,537 @@
// ·. · · · · .
// · ·
// · ·
//
// · · ·
// Magicbane Emulator Project © 2013 - 2024
// www.magicbane.com
package engine.wpakpowers;
import engine.InterestManagement.WorldGrid;
import engine.gameManager.ChatManager;
import engine.gameManager.DbManager;
import engine.gameManager.DispatchManager;
import engine.gameManager.SessionManager;
import engine.job.JobContainer;
import engine.job.JobScheduler;
import engine.jobs.FinishRecycleTimeJob;
import engine.jobs.WpakUsePowerJob;
import engine.math.Vector3fImmutable;
import engine.mbEnums;
import engine.net.Dispatch;
import engine.net.client.ClientConnection;
import engine.net.client.msg.ModifyHealthMsg;
import engine.net.client.msg.PerformActionMsg;
import engine.net.client.msg.RecyclePowerMsg;
import engine.net.client.msg.UpdateStateMsg;
import engine.objects.*;
import engine.server.MBServerStatics;
import engine.util.Hasher;
import engine.util.Pair;
import engine.wpak.EffectsParser;
import engine.wpak.PowerActionParser;
import engine.wpak.PowersParser;
import engine.wpak.data.Effect;
import engine.wpak.data.*;
import org.pmw.tinylog.Logger;
import java.util.HashMap;
import java.util.HashSet;
import java.util.concurrent.ThreadLocalRandom;
import static engine.math.FastMath.sqr;
public class WpakPowerManager {
public static HashMap<String, Effect> _effectsLookup = new HashMap<>();
public static HashMap<Integer, PowerAction> _powerActionLookup = new HashMap<>();
public static HashMap<Integer, Power> _powersLookup = new HashMap<>();
private static JobScheduler js;
public static void init() {
EffectsParser.parseWpakFile();
PowersParser.parseWpakFile();
PowerActionParser.parseWpakFile();
}
public static void beginCast(final PerformActionMsg msg, ClientConnection origin, boolean sendCastToSelf) {
if (executePower(msg, origin, sendCastToSelf)) {
// Cast failed for some reason, reset timer
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(origin.getPlayerCharacter(), recyclePowerMsg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
// Send Fail to cast message
PlayerCharacter pc = SessionManager.getPlayerCharacter(origin);
if (pc != null) {
sendPowerMsg(pc, 2, msg);
if (pc.isCasting()) {
pc.update();
}
pc.setIsCasting(false);
}
}
}
private static boolean executePower(final PerformActionMsg msg, ClientConnection origin, boolean sendCastToSelf) {
//check to see if the caster is valid
PlayerCharacter playerCharacter = SessionManager.getPlayerCharacter(origin);
if (playerCharacter == null)
return false;
//make sure player is still alive
if (!playerCharacter.isAlive() && msg.getPowerUsedID() != 428589216) { //succor
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(playerCharacter, recyclePowerMsg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
return false;
}
//make sure the recycle timer has actually elapsed
if (playerCharacter.getRecycleTimers().containsKey(msg.getPowerUsedID())) {
Logger.warn("usePowerA(): Cheat attempted? '" + msg.getPowerUsedID() + "' recycle timer not finished " + playerCharacter.getName());
return false;
}
//lookup the power that was cast
Power powerCast = _powersLookup.get(msg.getPowerUsedID());
if (powerCast == null) {
ChatManager.chatSayInfo(playerCharacter, "This power is not implemented yet.");
return true;
}
if (playerCharacter.getLastPower() != null)
return true;
// get numTrains for power
int trains = msg.getNumTrains();
if (trains > powerCast.maxLevel) {
trains = powerCast.maxLevel;
msg.setNumTrains(trains);
}
//sanity check for amount of trains in spell cast
if (playerCharacter.getPowers() != null && playerCharacter.getPowers().containsKey(msg.getPowerUsedID())) {
CharacterPower cp = playerCharacter.getPowers().get(msg.getPowerUsedID());
if (cp != null) {
int tot = cp.getTotalTrains();
if (tot == 0)
return false;
if (trains != tot) {
trains = tot;
msg.setNumTrains(trains);
}
}
}
//get casting time
int time = getRecycleTime(powerCast, trains);
//combat mode sanity check
if (playerCharacter.isCombat()) {
if (!allowedInCombat(powerCast))
return true;
} else if (!allowedOutOfCombat(powerCast))
return true;
//stunned check
PlayerBonuses bonus = playerCharacter.getBonuses();
// mbEnums.SourceType sourceType = mbEnums.SourceType.GetSourceType(powerCast.category);
// if (bonus != null && (bonus.getBool(mbEnums.ModType.Stunned, mbEnums.SourceType.None) || bonus.getBool(mbEnums.ModType.CannotCast, mbEnums.SourceType.None) || bonus.getBool(mbEnums.ModType.BlockedPowerType, sourceType)))
// return true;
//sanity check for casting while moving
Vector3fImmutable endLoc = playerCharacter.getEndLoc();
if (!powerCast.canCastWhileMoving)
if (playerCharacter.isMoving()) {
float distanceLeftSquared = endLoc.distanceSquared2D(playerCharacter.getLoc());
if (distanceLeftSquared > sqr(playerCharacter.getSpeed()))
return true;
}
//get the actual target form the message
int type = msg.getTargetType();
int UUID = msg.getTargetID();
if (type == -1 || type == 0 || UUID == -1 || UUID == 0)
return true;
AbstractWorldObject target = (AbstractWorldObject) DbManager.getObject(mbEnums.GameObjectType.values()[type], UUID);
//check to make sure power can be cast on building if target is a building
if (target != null && target.getObjectType() == mbEnums.GameObjectType.Building && !powerCast.target_type.equals(mbEnums.PowerTargetType.BUILDING)) {
sendPowerMsg(playerCharacter, 9, new PerformActionMsg(msg));
return true;
}
//validate casting range
if (playerCharacter.getLoc().distanceSquared2D(msg.getTargetLoc()) > (powerCast.range * powerCast.range))
return true;
//validate prereqs for power cast
//equipment prereqs
if (!powerCast.equipmentPreReq.isEmpty())
for (EquipmentPreReq prereq : powerCast.equipmentPreReq) {
String requiredSkill = prereq.skill;
if (playerCharacter.charItemManager.equipped.get(prereq.slot) != null) {
Item equippedItem = playerCharacter.charItemManager.equipped.get(prereq.slot);
if (!equippedItem.template.item_skill_mastery_used.equals(requiredSkill) && !equippedItem.template.item_skill_used.equals(requiredSkill))
return true;
} else {
return true;
}
}
//effect prereqs
if (!powerCast.effectPreReqs.isEmpty()) {
for (Effect prereq : powerCast.effectPreReqs) {
if (!playerCharacter.effects.contains(prereq.effect_id) && !playerCharacter.effects.contains(prereq.effect_name))
return true;
}
}
float cost = getCost(powerCast, trains);
if (bonus != null)
cost *= (1 + bonus.getFloatPercentAll(mbEnums.ModType.PowerCost, mbEnums.SourceType.None));
if (playerCharacter.getAltitude() > 0)
cost *= 1.5f;
if (cost > 0)
if ((playerCharacter.getObjectTypeMask() & MBServerStatics.MASK_UNDEAD) != 0)
if (playerCharacter.getHealth() <= cost)
return true;
else {
playerCharacter.modifyHealth(-cost, playerCharacter, true);
ModifyHealthMsg mhm = new ModifyHealthMsg(playerCharacter, playerCharacter, -cost, 0f, 0f, 0, null, 9999, 0);
mhm.setOmitFromChat(1);
DispatchManager.dispatchMsgToInterestArea(playerCharacter, mhm, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
}
else if (powerCast.costType.name().equals("MANA"))
if (playerCharacter.getMana() < cost)
return true;
else
playerCharacter.modifyMana(-cost, playerCharacter, true);
else if (powerCast.costType.name().equals("STAMINA"))
if (playerCharacter.getStamina() < cost)
return true;
else
playerCharacter.modifyStamina(-cost, playerCharacter, true);
else if (playerCharacter.getHealth() <= cost)
return true;
else
playerCharacter.modifyHealth(-cost, playerCharacter, true);
if (time > 0) {
FinishRecycleTimeJob frtj = new FinishRecycleTimeJob(playerCharacter, msg);
playerCharacter.getRecycleTimers().put(msg.getPowerUsedID(), js.scheduleJob(frtj, time));
} else {
// else send recycle message to unlock power
RecyclePowerMsg recyclePowerMsg = new RecyclePowerMsg(msg.getPowerUsedID());
Dispatch dispatch = Dispatch.borrow(playerCharacter, recyclePowerMsg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
}
int tr = msg.getNumTrains();
DispatchManager.dispatchMsgToInterestArea(playerCharacter, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, sendCastToSelf, false);
//Make new msg..
PerformActionMsg copyMsg = new PerformActionMsg(msg);
copyMsg.setNumTrains(tr);
// make person casting stand up if spell (unless they're casting a chant which does not make them stand up)
if (powerCast.isSpell() && !powerCast.isChant() && playerCharacter.isSit()) {
playerCharacter.update();
playerCharacter.setSit(false);
UpdateStateMsg updateStateMsg = new UpdateStateMsg(playerCharacter);
DispatchManager.dispatchMsgToInterestArea(playerCharacter, updateStateMsg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
}
// update cast (use skill) fail condition
playerCharacter.cancelOnCast();
// update castSpell (use spell) fail condition if spell
if (powerCast.isSpell())
playerCharacter.cancelOnSpell();
// get cast time in ms.
time = getCastTime(powerCast, trains);
// set player is casting for regens
if (time > 100) {
playerCharacter.update();
playerCharacter.setIsCasting(true);
}
playerCharacter.setLastMovementState(playerCharacter.getMovementState());
// run timer job to end cast
if (time < 1) // run immediately
finishUsePower(copyMsg, playerCharacter, target);
else {
WpakUsePowerJob upj = new WpakUsePowerJob(playerCharacter, copyMsg, target);
JobContainer jc = js.scheduleJob(upj, time);
// make lastPower
playerCharacter.setLastPower(jc);
}
return false;
}
public static void finishUsePower(PerformActionMsg msg, PlayerCharacter caster, AbstractWorldObject target) {
Power powerUsed = _powersLookup.get(msg.getPowerUsedID());
if (powerUsed == null) {
Logger.error("Invalid power: " + msg.getPowerUsedID());
return;
}
if (powerUsed.maxMobTargets > 1 || powerUsed.maxPlayerTargets > 1)
AoeHandler(caster, target, powerUsed, msg.getNumTrains());
else
executeActionsForPower(caster, powerUsed, msg.getNumTrains(), target);
}
private static void AoeHandler(PlayerCharacter caster, AbstractWorldObject target, Power powerUsed, int rank) {
HashSet<AbstractWorldObject> mobTargets = new HashSet<>();
HashSet<AbstractWorldObject> pcTargets = new HashSet<>();
int count = 1;
if (powerUsed.maxMobTargets > 0)
mobTargets = WorldGrid.getObjectsInRangePartial(target.loc, powerUsed.areaRange, MBServerStatics.MASK_MOB);
if (powerUsed.maxPlayerTargets > 0)
pcTargets = WorldGrid.getObjectsInRangePartial(target.loc, powerUsed.areaRange, MBServerStatics.MASK_PLAYER);
for (AbstractWorldObject mob : mobTargets) {
if (count < powerUsed.maxMobTargets + 1) {
executeActionsForPower(caster, powerUsed, rank, mob);
count++;
} else {
break;
}
}
count = 1;
for (AbstractWorldObject pc : pcTargets) {
if (count < powerUsed.maxPlayerTargets + 1) {
executeActionsForPower(caster, powerUsed, rank, pc);
count++;
} else {
break;
}
}
}
public static void executeActionsForPower(AbstractCharacter caster, Power power, int rank, AbstractWorldObject target) {
// Iterate through the poweractions for this power
// and execute them according to PowerActionType.
for (ActionEntry actionEntry : power.actionEntries) {
PowerAction powerAction = _powerActionLookup.get(Hasher.SBStringHash(actionEntry.action_id));
if (powerAction == null) {
Logger.error("Null PowerAction for " + actionEntry.action_id);
continue;
}
powerAction.action_type.execute(caster, power, rank, target,
powerAction);
}
}
public static void sendPowerMsg(PlayerCharacter playerCharacter, int type, PerformActionMsg msg) {
if (playerCharacter == null)
return;
msg.setUnknown05(type);
switch (type) {
case 3:
case 4:
msg.setUnknown04(2);
DispatchManager.dispatchMsgToInterestArea(playerCharacter, msg, mbEnums.DispatchChannel.PRIMARY, MBServerStatics.CHARACTER_LOAD_RANGE, true, false);
break;
default:
msg.setUnknown04(1);
Dispatch dispatch = Dispatch.borrow(playerCharacter, msg);
DispatchManager.dispatchMsgDispatch(dispatch, mbEnums.DispatchChannel.PRIMARY);
}
}
public static int getRecycleTime(Power power, int trains) { // returns cast time in ms
if (power.curves.get("RECYCLETIME") != null) {
mbEnums.CompoundCurveType compoundCurveType = power.curves.get("RECYCLETIME");
return (int) (((power.recycle_time + (compoundCurveType.value * trains)) * 1000) + getCastTime(power, trains));
} else {
mbEnums.CompoundCurveType compoundCurveType = power.curves.get("RECYCLETIME");
return (int) (((power.recycle_time * (1 + (compoundCurveType.value * trains))) * 1000) + getCastTime(power, trains));
}
}
public static int getCastTime(Power power, int trains) { // returns cast time in ms
if (power.curves.get("INITTIME") != null) {
mbEnums.CompoundCurveType compoundCurveType = power.curves.get("INITTIME");
return (int) ((power.init_time + (compoundCurveType.value * trains)) * 1000);
} else {
mbEnums.CompoundCurveType compoundCurveType = power.curves.get("INITTIME");
return (int) ((power.init_time * (1 + (compoundCurveType.value * trains))) * 1000);
}
}
public static float getCost(Power power, int trains) {
if (power.curves.get("COSTAMT") != null) {
mbEnums.CompoundCurveType compoundCurveType = power.curves.get("COSTAMT");
return power.cost + (compoundCurveType.value * trains);
} else {
mbEnums.CompoundCurveType compoundCurveType = power.curves.get("COSTAMT");
return power.cost * (1 + (compoundCurveType.value * trains));
}
}
public static boolean allowedInCombat(Power power) {
return power.castingMode.equals(mbEnums.CastingModeType.NONCOMBAT) == false;
}
public static boolean allowedOutOfCombat(Power power) {
return power.castingMode.equals(mbEnums.CastingModeType.COMBAT) == false;
}
public static Pair<Float, Float> getModifierValues(ModifierEntry modifierEntry, int rank) {
Pair<Float, Float> outData = new Pair<>(0f, 0f);
if (modifierEntry.percentage != 0f) {
outData.first = modifierEntry.percentage + (modifierEntry.compoundCurveType.value * rank);
outData.first = outData.first * 0.01f;
return outData;
}
// As there is a min/max we return both as a pair enabling
// use in the DD modifier.
// MB Dev Note:
// A subset of health/mana/stam modifiers are multiplicative.
// These all have "SIVL" in the curve name suggesting
// interpolation between min max. Not something currently done.
outData.first = modifierEntry.compoundCurveType.type.equals(mbEnums.ModificationType.MULTIPLY) ?
modifierEntry.min * (1 + (modifierEntry.compoundCurveType.value * rank)) :
modifierEntry.min + (modifierEntry.compoundCurveType.value * rank);
if (modifierEntry.max != 0)
outData.second = modifierEntry.compoundCurveType.type.equals(mbEnums.ModificationType.MULTIPLY) ?
modifierEntry.max * (1 + (modifierEntry.compoundCurveType.value * rank)) :
modifierEntry.max + (modifierEntry.compoundCurveType.value * rank);
return outData;
}
public static void DirectDamageHandler(AbstractCharacter caster, AbstractWorldObject target,Power power, Integer rank, ModifierEntry modEntry){
if(caster == null || !caster.isAlive())
return;
if(target == null || !target.isAlive())
return;
mbEnums.DamageType damageType = mbEnums.DamageType.getDamageType(modEntry.arg1);
float focus;
CharacterSkill skill = caster.getSkills().get(power.powers.get(0).focusLine);
if (skill == null)
focus = CharacterSkill.getQuickMastery(caster, power.powers.get(0).focusLine);
else
focus = skill.getModifiedAmount();
float min;
float max;
float percent;
float damage;
if(modEntry.percentage != 0){
//handle percentage damage
percent = getModifierValues(modEntry,rank).first;
damage = target.healthMax * percent;
}else{
//flat damage range
min = getMinDamage(getModifierValues(modEntry,rank).first,caster.getStatIntCurrent(),caster.getStatSpiCurrent(),focus);
max = getMaxDamage(getModifierValues(modEntry,rank).second,caster.getStatIntCurrent(),caster.getStatSpiCurrent(),focus);
damage = ThreadLocalRandom.current().nextInt((int) min, (int) (max) + 1);
}
//apply power damage modifier values
for(AppliedEffect appliedEffect: caster._effects.values()){
if(appliedEffect.modifiers.containsKey(mbEnums.ModType.PowerDamageModifier)){
damage *= 1 + (float)appliedEffect.modifiers.get(mbEnums.ModType.PowerDamageModifier);
}
}
if(AbstractCharacter.IsAbstractCharacter(target)) {
AbstractCharacter absChar = (AbstractCharacter)target;
damage = (int) absChar.resists.getResistedDamage(caster,absChar,damageType,damage,rank);
float newStatValue;
switch(modEntry.type){
case Health:
//damage health
newStatValue = absChar.getHealth() - damage;
if(newStatValue < 0)
newStatValue = 0;
absChar.setHealth(newStatValue);
break;
case Stamina:
//damage stamina
newStatValue = absChar.getStamina() - damage;
if(newStatValue < 0)
newStatValue = 0;
absChar.setStamina(newStatValue,caster);
break;
case Mana:
//damage mana
newStatValue = absChar.getMana() - damage;
if(newStatValue < 0)
newStatValue = 0;
absChar.setMana(newStatValue,caster);
break;
}
}else{
//target is building
float newStatValue = target.getHealth() - damage;
if(newStatValue < 0)
newStatValue = 0;
target.setHealth(newStatValue);
}
}
public static float getMinDamage(float baseMin, float intelligence, float spirit, float focus) {
float min = baseMin * (((float) Math.pow(intelligence, 0.75f) * 0.0311f) + (0.02f * (int) focus) + ((float) Math.pow(spirit, 0.75f) * 0.0416f));
return (float) ((int) (min + 0.5f)); //round to nearest whole number
}
public static float getMaxDamage(float baseMax, float intelligence, float spirit, float focus) {
float max = baseMax * (((float) Math.pow(intelligence, 0.75f) * 0.0785f) + (0.015f * (int) focus) + ((float) Math.pow(spirit, 0.75f) * 0.0157f));
return (float) ((int) (max + 0.5f)); //round to nearest whole number
}
}