/**
* Copyright (c) Lambda Innovation, 2013-2016
* This file is part of the AcademyCraft mod.
* https://github.com/LambdaInnovation/AcademyCraft
* Licensed under GPLv3, see project root for more information.
*/
package cn.academy.vanilla.teleporter.util;
import cn.academy.ability.api.AbilityContext;
import cn.academy.ability.api.data.AbilityData;
import cn.academy.ability.api.event.AbilityEvent;
import cn.academy.misc.achievements.ModuleAchievements;
import cn.academy.vanilla.teleporter.CatTeleporter;
import cn.academy.vanilla.teleporter.passiveskill.DimFoldingTheorem;
import cn.academy.vanilla.teleporter.passiveskill.DimFoldingTheorem$;
import cn.academy.vanilla.teleporter.passiveskill.SpaceFluctuation;
import cn.academy.vanilla.teleporter.passiveskill.SpaceFluctuation$;
import cn.lambdalib.annoreg.core.Registrant;
import cn.lambdalib.s11n.network.NetworkMessage;
import cn.lambdalib.s11n.network.NetworkMessage.Listener;
import cn.lambdalib.s11n.network.NetworkS11n.NetworkS11nType;
import cn.lambdalib.util.generic.RandUtils;
import cpw.mods.fml.relauncher.Side;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ChatComponentTranslation;
import net.minecraftforge.common.MinecraftForge;
/**
* @author WeAthFolD
*/
@Registrant
@NetworkS11nType
public class TPSkillHelper {
static final String TPC_ID = "ac_tpcount";
public static void incrTPCount(EntityPlayer player) {
int i = player.getEntityData().getInteger(TPC_ID) + 1;
if (i >= 400) {
ModuleAchievements.trigger(player, "teleporter.mastery");
}
player.getEntityData().setInteger(TPC_ID, i);
}
/**
* You should use this in SERVER only. the critical hit event will be post
* at client if a critical hit happened.
*/
public static void attack(AbilityContext ctx, Entity target, float damage) {
AbilityData aData = ctx.aData;
EntityPlayer player = ctx.player;
// Calculate 3 levels of crit hit
for (int i = 0; i < 3; ++i) {
float prob = prob(aData, i);
if (RandUtils.nextFloat() < prob) {
damage *= rates[i];
player.addChatComponentMessage(new ChatComponentTranslation("ac.ability.teleporter.crithit", rates[i]));
ModuleAchievements.trigger(player, "teleporter.critical_attack");
aData.addSkillExp(CatTeleporter.dimFolding, (i + 1) * 0.005f);
aData.addSkillExp(CatTeleporter.spaceFluct, 0.0001f);
fireCritAttack(player, target, i);
NetworkMessage.sendTo(player, NetworkMessage.staticCaller(TPSkillHelper.class),
"fire", player, target, i);
break;
}
}
ctx.attack(target, damage);
}
public static void attackIgnoreArmor(AbilityContext ctx, Entity target, float damage) {
AbilityData aData = ctx.aData;
EntityPlayer player = ctx.player;
// Calculate 3 levels of crit hit
for (int i = 0; i < 3; ++i) {
float prob = prob(aData, i);
if (RandUtils.nextFloat() < prob) {
damage *= rates[i];
player.addChatComponentMessage(new ChatComponentTranslation("ac.ability.teleporter.crithit", rates[i]));
ModuleAchievements.trigger(player, "teleporter.critical_attack");
aData.addSkillExp(CatTeleporter.dimFolding, (i + 1) * 0.005f);
aData.addSkillExp(CatTeleporter.spaceFluct, 0.0001f);
fireCritAttack(player, target, i);
NetworkMessage.sendTo(player, NetworkMessage.staticCaller(TPSkillHelper.class),
"fire", player, target, i);
break;
}
}
ctx.attackIgnoreArmor(target, damage);
}
private static float prob(AbilityData data, int level) {
float dimFoldingExp = data.isSkillLearned(DimFoldingTheorem$.MODULE$) ? data.getSkillExp(DimFoldingTheorem$.MODULE$) : -1;
float spaceFluctExp = data.isSkillLearned(SpaceFluctuation$.MODULE$) ? data.getSkillExp(SpaceFluctuation$.MODULE$) : -1;
switch (level) {
case 0:
return tryLerp(0.1f, 0.2f, dimFoldingExp) + tryLerp(0.18f, 0.25f, spaceFluctExp);
case 1:
return tryLerp(0.10f, 0.15f, spaceFluctExp);
case 2:
return tryLerp(0.01f, 0.03f, spaceFluctExp);
}
throw new IllegalArgumentException();
}
private static float rates[] = { 1.3f, 1.6f, 2.6f };
private static float tryLerp(float a, float b, float l) {
if (l == -1) return 0;
return a + l * (b - a);
}
@Listener(channel="fire", side=Side.CLIENT)
private static void fireCritAttack(EntityPlayer player, Entity target, int level) {
MinecraftForge.EVENT_BUS.post(new TPCritHitEvent(player, target, level));
}
/**
* Fired both client and server when player emits an critical hit.
*/
public static class TPCritHitEvent extends AbilityEvent {
public final int level;
public final Entity target;
public TPCritHitEvent(EntityPlayer _player, Entity _target, int _level) {
super(_player);
level = _level;
target = _target;
}
}
}