/**
* Copyright (c) Lambda Innovation, 2013-2015
* 本作品版权由Lambda Innovation所有。
* http://www.li-dev.cn/
*
* This project is open-source, and it is distributed under
* the terms of GNU General Public License. You can modify
* and distribute freely as long as you follow the license.
* 本项目是一个开源项目,且遵循GNU通用公共授权协议。
* 在遵照该协议的情况下,您可以自由传播和修改。
* http://www.gnu.org/licenses/gpl.html
*/
package cn.weaponry.impl.generic.action;
import java.util.Random;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.Vec3;
import cn.weaponry.api.action.Action;
import cn.weaponry.api.state.WeaponStateMachine;
import cn.weaponry.impl.classic.WeaponClassic;
import cn.weaponry.impl.classic.WeaponClassic.StateReload;
import cn.weaponry.impl.classic.WeaponClassic.StateShoot;
/**
* Used to silence Minecraft swing action.
* @author WeAthFolD
*/
public class ScatterUpdater extends Action {
//base value
private double shootScatterMin;
private double shootScatterIncrement;
private double movingScatterIncrement;
private double shootScatterStability;
//temp value
private double shootScatter;
private double movingScatter;
private int shootCount;
private int shootCooldown;
//temp value
private double renderShootScatter;
private double renderMovingScatter;
private double oldX, oldY, oldZ;
private Random r = new Random();
//as ms
private int recoverTime = 300;
public void onStart() {
WeaponClassic weapon = (WeaponClassic) itemInfo.getItemType();
this.shootScatterMin = weapon.shootScatterMin;
this.shootScatterIncrement = weapon.shootScatterIncrement;
this.shootScatterStability = weapon.shootScatterStability;
if(this.shootScatterStability < 0)
this.shootScatterStability = 0;
this.movingScatterIncrement = weapon.movingScatterIncrement;
this.shootScatter = 0;
this.movingScatter = 0;
this.shootCount = 0;
this.shootCooldown = 0;
EntityPlayer player = itemInfo.getPlayer();
this.oldX = player.posX;
this.oldY = player.posY;
this.oldZ = player.posZ;
}
public void onTick(int tick) {
shootScatterStability = 3;
WeaponStateMachine machine = (WeaponStateMachine) itemInfo.getAction("StateMachine");
EntityPlayer player = itemInfo.getPlayer();
if(machine != null && machine.getCurrentState() != null){
//flags
Vec3 motion = Vec3.createVectorHelper(player.posX - oldX, player.posY - oldY, player.posZ - oldZ);
boolean moving = motion.lengthVector() > 0.1 || player.isSneaking();
boolean shooting = machine.getCurrentState() instanceof StateShoot;
boolean reloading = machine.getCurrentState() instanceof StateReload;
//for both shoot, reload & move
double recoverTicks = this.recoverTime/50;
double movingScatterMulti = player.isSprinting() ? 1.25 : player.isSneaking() ? 0.1 : 1;
double movingPhase = movingScatterIncrement * movingScatterMulti/recoverTicks;
//incresing
if(shooting){
shootCooldown = 5;
}else if(reloading && shootScatter < shootScatterIncrement){
shootCount = 0;
shootScatter += shootScatterIncrement/recoverTicks;
if(shootScatter > shootScatterIncrement)
shootScatter = shootScatterIncrement;
}
if(moving && movingScatter < movingScatterIncrement * movingScatterMulti){
//System.out.println(movingScatterIncrement * movingScatterMulti);
movingScatter += movingPhase;
if(movingScatter > movingScatterIncrement * movingScatterMulti)
movingScatter = movingScatterIncrement * movingScatterMulti;
oldX = player.posX;
oldY = player.posY;
oldZ = player.posZ;
}
//recovering
if(shootScatter > 0 && !reloading){
shootScatter -= shootScatterIncrement/(recoverTicks * (shooting ? 10 : 1));
if(shootScatter < 0)
shootScatter = 0;
}
if(movingScatter > 0){
movingScatter -= movingPhase / (moving ? 5 : 1);
if(movingScatter < 0)
movingScatter = 0;
}
//judge continuous fire
if(shootCooldown >= 0)
shootCooldown--;
if(shootCooldown == 0)
shootCount = 0;
}
}
@Override
public void onRenderTick(){
long msPerFrame = itemInfo.getDeltaTime();
//System.out.println(dt);
WeaponStateMachine machine = (WeaponStateMachine) itemInfo.getAction("StateMachine");
EntityPlayer player = itemInfo.getPlayer();
if(machine != null && machine.getCurrentState() != null){
//flags
Vec3 motion = Vec3.createVectorHelper(player.motionX, player.motionY, player.motionZ);
boolean moving = motion.lengthVector() > 0.1 || player.isSneaking();
boolean shooting = machine.getCurrentState() instanceof StateShoot;
boolean reloading = machine.getCurrentState() instanceof StateReload;
//for both shoot & move
double recoverFrames = this.recoverTime/msPerFrame;
double movingScatterMulti = player.isSprinting() ? 1.25 : player.isSneaking() ? 0.1 : 1;
double movingPhase = movingScatterIncrement * movingScatterMulti/recoverFrames;
//incresing
if(shooting && shootScatterIncrement > 0){
//different cal to make shaking effect, renderShootScatter update following server-side shootScatter
if(renderShootScatter <= shootScatter){
renderShootScatter += 0.08 + ((1.25 * (Math.pow(2, shootScatterStability) - 1))/1000 * shootCount * shootCount) * msPerFrame / 50.0;
if(renderShootScatter > shootScatter)
renderShootScatter = shootScatter + 0.08;
}else if(renderShootScatter > shootScatter){
renderShootScatter -= 0.04;
if(renderShootScatter < shootScatter)
renderShootScatter = shootScatter;
}
}else if(reloading && renderShootScatter < shootScatter){
renderShootScatter += shootScatterIncrement/recoverFrames;
if(renderShootScatter > shootScatter)
renderShootScatter = shootScatter;
}
if(moving && renderMovingScatter < movingScatter){
renderMovingScatter += movingPhase;
if(renderMovingScatter > movingScatter)
renderMovingScatter = movingScatter;
}
//recovering
if(renderShootScatter > shootScatter){
renderShootScatter -= shootScatterIncrement/(recoverFrames * (shooting ? 10 : 1));
if(renderShootScatter < shootScatter)
renderShootScatter = shootScatter;
}
if(renderMovingScatter > movingScatter){
renderMovingScatter -= movingPhase / (moving ? 5 : 1);
if(renderMovingScatter < movingScatter)
renderMovingScatter = movingScatter;
}
}
}
public void callShoot(){
if(shootScatter < shootScatterIncrement){
shootScatter += (1.25 * (Math.pow(2, shootScatterStability) - 1))/1000 * shootCount * shootCount;
}
if(shootScatter > shootScatterIncrement)
shootScatter = shootScatterIncrement;
shootCount++;
}
public double getCurrentScatter(){
//System.out.println("第" + shootCount + "发精度" + (shootScatterMin + shootScatter + movingScatter));
return shootScatterMin + shootScatter + movingScatter;
}
public double getRenderScatter(){
return shootScatterMin + renderShootScatter + renderMovingScatter;
}
@Override
public String getName() {
return "ScatterUpdater";
}
}