| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -22,6 +22,7 @@ import engine.net.client.msg.PerformActionMsg; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import engine.net.client.msg.PowerProjectileMsg; | 
					 | 
					 | 
					 | 
					import engine.net.client.msg.PowerProjectileMsg; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import engine.objects.*; | 
					 | 
					 | 
					 | 
					import engine.objects.*; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import engine.powers.ActionsBase; | 
					 | 
					 | 
					 | 
					import engine.powers.ActionsBase; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					import engine.powers.MobPowerEntry; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import engine.powers.PowersBase; | 
					 | 
					 | 
					 | 
					import engine.powers.PowersBase; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import engine.server.MBServerStatics; | 
					 | 
					 | 
					 | 
					import engine.server.MBServerStatics; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					import org.pmw.tinylog.Logger; | 
					 | 
					 | 
					 | 
					import org.pmw.tinylog.Logger; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -321,7 +322,7 @@ public class MobAI { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    return false; | 
					 | 
					 | 
					 | 
					                    return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if (mob.mobPowers.isEmpty()) | 
					 | 
					 | 
					 | 
					            if (PowersManager.getPowersForMobile(mob).isEmpty()) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                return false; | 
					 | 
					 | 
					 | 
					                return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) { | 
					 | 
					 | 
					 | 
					            if (!mob.canSee((PlayerCharacter) mob.getCombatTarget())) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -346,8 +347,8 @@ public class MobAI { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // and casts it on the current target (or itself).  Validation
 | 
					 | 
					 | 
					 | 
					            // and casts it on the current target (or itself).  Validation
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // (including empty lists) is done previously within canCast();
 | 
					 | 
					 | 
					 | 
					            // (including empty lists) is done previously within canCast();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ArrayList<Integer> powerTokens; | 
					 | 
					 | 
					 | 
					            ArrayList<MobPowerEntry> powerEntries; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ArrayList<Integer> purgeTokens; | 
					 | 
					 | 
					 | 
					            ArrayList<MobPowerEntry> purgeEntries; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); | 
					 | 
					 | 
					 | 
					            AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if (mob.behaviourType.callsForHelp) | 
					 | 
					 | 
					 | 
					            if (mob.behaviourType.callsForHelp) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -355,36 +356,36 @@ public class MobAI { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // Generate a list of tokens from the mob powers for this mobile.
 | 
					 | 
					 | 
					 | 
					            // Generate a list of tokens from the mob powers for this mobile.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            powerTokens = new ArrayList<>(mob.mobPowers.keySet()); | 
					 | 
					 | 
					 | 
					            powerEntries = new ArrayList<>(PowersManager.getPowersForMobile(mob)); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            purgeTokens = new ArrayList<>(); | 
					 | 
					 | 
					 | 
					            purgeEntries = new ArrayList<>(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // If player has this effect on them currently then remove
 | 
					 | 
					 | 
					 | 
					            // If player has this effect on them currently then remove
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // this token from our list.
 | 
					 | 
					 | 
					 | 
					            // this token from our list.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            for (int powerToken : powerTokens) { | 
					 | 
					 | 
					 | 
					            for (MobPowerEntry mobPowerEntry : powerEntries) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                PowersBase powerBase = PowersManager.getPowerByToken(powerToken); | 
					 | 
					 | 
					 | 
					                PowersBase powerBase = PowersManager.getPowerByToken(mobPowerEntry.token); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                for (ActionsBase actionBase : powerBase.getActions()) { | 
					 | 
					 | 
					 | 
					                for (ActionsBase actionBase : powerBase.getActions()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    String stackType = actionBase.stackType; | 
					 | 
					 | 
					 | 
					                    String stackType = actionBase.stackType; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    if (target.getEffects() != null && target.getEffects().containsKey(stackType)) | 
					 | 
					 | 
					 | 
					                    if (target.getEffects() != null && target.getEffects().containsKey(stackType)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        purgeTokens.add(powerToken); | 
					 | 
					 | 
					 | 
					                        purgeEntries.add(mobPowerEntry); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } | 
					 | 
					 | 
					 | 
					                } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            powerTokens.removeAll(purgeTokens); | 
					 | 
					 | 
					 | 
					            powerEntries.removeAll(purgeEntries); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // Sanity check
 | 
					 | 
					 | 
					 | 
					            // Sanity check
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if (powerTokens.isEmpty()) | 
					 | 
					 | 
					 | 
					            if (powerEntries.isEmpty()) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                return false; | 
					 | 
					 | 
					 | 
					                return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // Pick random spell from our list of powers
 | 
					 | 
					 | 
					 | 
					            // Pick random spell from our list of powers
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            int powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); | 
					 | 
					 | 
					 | 
					            int powerToken = powerEntries.get(ThreadLocalRandom.current().nextInt(powerEntries.size())).token; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            int powerRank = mob.mobPowers.get(powerToken); | 
					 | 
					 | 
					 | 
					            int powerRank = powerEntries.get(ThreadLocalRandom.current().nextInt(powerEntries.size())).rank; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            PowersBase mobPower = PowersManager.getPowerByToken(powerToken); | 
					 | 
					 | 
					 | 
					            PowersBase mobPower = PowersManager.getPowerByToken(powerToken); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -429,8 +430,8 @@ public class MobAI { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // and casts it on the current target (or itself).  Validation
 | 
					 | 
					 | 
					 | 
					            // and casts it on the current target (or itself).  Validation
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // (including empty lists) is done previously within canCast();
 | 
					 | 
					 | 
					 | 
					            // (including empty lists) is done previously within canCast();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ArrayList<Integer> powerTokens; | 
					 | 
					 | 
					 | 
					            ArrayList<MobPowerEntry> powerEntries; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            ArrayList<Integer> purgeTokens; | 
					 | 
					 | 
					 | 
					            ArrayList<MobPowerEntry> purgeEntries; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); | 
					 | 
					 | 
					 | 
					            AbstractCharacter target = (AbstractCharacter) mob.getCombatTarget(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if (mob.behaviourType.callsForHelp) | 
					 | 
					 | 
					 | 
					            if (mob.behaviourType.callsForHelp) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -438,30 +439,36 @@ public class MobAI { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // Generate a list of tokens from the mob powers for this mobile.
 | 
					 | 
					 | 
					 | 
					            // Generate a list of tokens from the mob powers for this mobile.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            powerTokens = new ArrayList<>(mob.mobPowers.keySet()); | 
					 | 
					 | 
					 | 
					            powerEntries = PowersManager.getPowersForMobile(mob); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            purgeTokens = new ArrayList<>(); | 
					 | 
					 | 
					 | 
					            purgeEntries = new ArrayList<>(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // If player has this effect on them currently then remove
 | 
					 | 
					 | 
					 | 
					            // If player has this effect on them currently then remove
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // this token from our list.
 | 
					 | 
					 | 
					 | 
					            // this token from our list.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            for (int powerToken : powerTokens) { | 
					 | 
					 | 
					 | 
					            powerEntries = new ArrayList<>(PowersManager.getPowersForMobile(mob)); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            purgeEntries = new ArrayList<>(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                PowersBase powerBase = PowersManager.getPowerByToken(powerToken); | 
					 | 
					 | 
					 | 
					            // If player has this effect on them currently then remove
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            // this token from our list.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            for (MobPowerEntry mobPowerEntry : powerEntries) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                PowersBase powerBase = PowersManager.getPowerByToken(mobPowerEntry.token); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                for (ActionsBase actionBase : powerBase.getActions()) { | 
					 | 
					 | 
					 | 
					                for (ActionsBase actionBase : powerBase.getActions()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    String stackType = actionBase.stackType; | 
					 | 
					 | 
					 | 
					                    String stackType = actionBase.stackType; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    if (target.getEffects() != null && target.getEffects().containsKey(stackType)) | 
					 | 
					 | 
					 | 
					                    if (target.getEffects() != null && target.getEffects().containsKey(stackType)) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        purgeTokens.add(powerToken); | 
					 | 
					 | 
					 | 
					                        purgeEntries.add(mobPowerEntry); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                } | 
					 | 
					 | 
					 | 
					                } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            powerTokens.removeAll(purgeTokens); | 
					 | 
					 | 
					 | 
					            powerEntries.removeAll(purgeEntries); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            // Sanity check
 | 
					 | 
					 | 
					 | 
					            // Sanity check
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if (powerTokens.isEmpty()) | 
					 | 
					 | 
					 | 
					            if (powerEntries.isEmpty()) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                return false; | 
					 | 
					 | 
					 | 
					                return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            int powerToken = 0; | 
					 | 
					 | 
					 | 
					            int powerToken = 0; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -470,11 +477,11 @@ public class MobAI { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            if (nukeRoll < 55) { | 
					 | 
					 | 
					 | 
					            if (nukeRoll < 55) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                //use direct damage spell
 | 
					 | 
					 | 
					 | 
					                //use direct damage spell
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                powerToken = powerTokens.get(powerTokens.size() - 1); | 
					 | 
					 | 
					 | 
					                powerToken = powerEntries.get(powerEntries.size() - 1).token; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } else { | 
					 | 
					 | 
					 | 
					            } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                //use random spell
 | 
					 | 
					 | 
					 | 
					                //use random spell
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                powerToken = powerTokens.get(ThreadLocalRandom.current().nextInt(powerTokens.size())); | 
					 | 
					 | 
					 | 
					                powerToken = powerEntries.get(ThreadLocalRandom.current().nextInt(powerEntries.size())).token; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            int powerRank = 1; | 
					 | 
					 | 
					 | 
					            int powerRank = 1; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |