import { world, system , BlockComponent } from '@minecraft/server';

const gates = [
	{x:11.5,y:65,z:38.5},
	{x:-51.5,y:65,z:0},
	{x:-11.5,y:65,z:-38.5},
	{x:11.5,y:65,z:-38.5},
	{x:52.5,y:65,z:0},
	{x:-11.5,y:65,z:38.5}
]
const perks = [
    "crit", //+
    "ballsnumber", // +
    "damage", //+
    "ballspeed", //+
    "playerspeed",//+
    "chargespeed",//+
    "knockback",//+
    "slowness",//+
    "lifetime",//+
    "explode",//+
    "return",//+
    "drag",//+
    "playerknockback",//+
    "areaknockback",//+
    "resistance",//
    "hearts",//
    "untouchable",//
    "split"//+
]
const perks_description = [
    "Hitting an enemy has a chance of dealing 2x damage", //+
    "You spawn more balls", // +
    "Higher damage", //+
    "Higher initial speed of the balls", //+
    "You move faster",//+
    "You charge the ball faster",//+
    "Hitting the enemies knocks them back",//+
    "Hitting the enemies slows them",//+
    "Balls stay alive for longer",//+
    "Balls explode when the time is over",//+
    "Balls move towards you 2s before vanishing",//+
    "Balls have a chance of leashing an enemy",//+
    "You are pushed backwards when hitting a ball",//+
    "Launching the ball knocks back the enemies",//+
    "Decreases the damage you receive",//+
    "Increases the amount of your hearts",//+
    "Deals damage to anyone who attacks you",//+
    "Balls get a chance to spawn a smaller version"//+
]
const ballTypes = [
    "football", // normal ball, no differences // +
	"fireball", // sets enemies on fire // 
	"bowling", // doesn't bounce, deals damage on drop // +
	"balloon", // starts with lvl 2 explosion perk, no hit damage // +
	"rubberball", // The bounces are randomized // +
	"wallball", // with each bounce the damage increases // +
	"puck", // moves only in 2 dimensions // +
	"golden", // doubles the money for kills // +
	"ghostball" // passes through the enemies without bouncing // +
]
const balls_description = [
    "Default ball", //
    "Sets enemies on fire", //
    "Doesn't bounce, deals damage on drop", //
    "Starts with lvl 2 explosion perk, no hit damage", //
    "The bounces are randomized",//
    "with each bounce the damage increases",//
    "moves only in 2 dimensions",//
    "doubles the money at the end",//
    "passes through the enemies without bouncing"
]
function physics (ball) {
	var ballType = world.getDynamicProperty("ball")
	var x = ball.location.x
	var y = ball.location.y
	var z = ball.location.z
	var vx = ball.getDynamicProperty("vx")
	var vy = ball.getDynamicProperty("vy")
	var vz = ball.getDynamicProperty("vz")
	var playerName = ball.getDynamicProperty("owner")
	var player = world.getDimension("Overworld").getPlayers({name: playerName})[0]
	vy += -0.1
	if (world.getDimension("overworld").getBlock(ball.location)?.typeId != "minecraft:air" && ballType!= "puck") ball.runCommand("/tp @s ~~0.5~")
	var precision = 1000/world.getDimension("Overworld").getEntities({families:["fara:ball"]}).length
	for (let i = 0 ; i <= precision; i++){
		var segment = i/precision
		var facingBlock = world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment})?.typeId
		if (facingBlock != "minecraft:air") {
			break
		} else if (facingBlock == "minecraft:air" && i%1000 == 0) {
		}
	}
	let vector = {
		x:x+vx*segment,
		y:y+vy*segment,
		z:z+vz*segment
	}
	if (!facingBlock) {var facingBlock = "minecraft:air"}
	if (facingBlock !="minecraft:air") {
		var xside1 = world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment}).center().x-0.5
		var xside2 = world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment}).center().x+0.5
		var yside1 = world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment}).center().y-0.5
		var yside2 = world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment}).center().y+0.5
		var zside1 = world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment}).center().z-0.5
		var zside2 = world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment}).center().z+0.5
		
		if ( vector.x != x) {var tside_x1 = (xside1 - x)/(vector.x-x)} else {var tside_x1 = (xside1 - x)/(vector.x-x+0.001)}
		if ( vector.x != x) {var tside_x2 = (xside2 - x)/(vector.x-x)} else {var tside_x2 = (xside2 - x)/(vector.x-x+0.001)}
		if ( vector.y != y) {var tside_y1 = (yside1 - y)/(vector.y-y)} else {var tside_y1 = (yside1 - y)/(vector.y-y+0.001)}
		if ( vector.y != y) {var tside_y2 = (yside2 - y)/(vector.y-y)} else {var tside_y2 = (yside2 - y)/(vector.y-y+0.001)}
		if ( vector.z != z) {var tside_z1 = (zside1 - z)/(vector.z-z)} else {var tside_z1 = (zside1 - z)/(vector.z-z+0.001)}
		if ( vector.z != z) {var tside_z2 = (zside2 - z)/(vector.z-z)} else {var tside_z2 = (zside2 - z)/(vector.z-z+0.001)}
		
		var xline_x1 = x + tside_x1*(vector.x-x)
		var xline_x2 = x + tside_x2*(vector.x-x)
		var xline_y1 = x + tside_y1*(vector.x-x)
		var xline_y2 = x + tside_y2*(vector.x-x)
		var xline_z1 = x + tside_z1*(vector.x-x)
		var xline_z2 = x + tside_z2*(vector.x-x)
		
		var yline_x1 = y + tside_x1*(vector.y-y)
		var yline_x2 = y + tside_x2*(vector.y-y)
		var yline_y1 = y + tside_y1*(vector.y-y)
		var yline_y2 = y + tside_y2*(vector.y-y)
		var yline_z1 = y + tside_z1*(vector.y-y)
		var yline_z2 = y + tside_z2*(vector.y-y)
		
		var zline_x1 = z + tside_x1*(vector.z-z)
		var zline_x2 = z + tside_x2*(vector.z-z)
		var zline_y1 = z + tside_y1*(vector.z-z)
		var zline_y2 = z + tside_y2*(vector.z-z)
		var zline_z1 = z + tside_z1*(vector.z-z)
		var zline_z2 = z + tside_z2*(vector.z-z)
		
		//Calculating which distance is shorter to determine which collision is sooner
		var xdistance1 = Math.sqrt(Math.pow(x-xline_x1,2)+Math.pow(y-yline_x1,2)+Math.pow(z-zline_x1,2))
		var xdistance2 = Math.sqrt(Math.pow(x-xline_x2,2)+Math.pow(y-yline_x2,2)+Math.pow(z-zline_x2,2))
		var ydistance1 = Math.sqrt(Math.pow(x-xline_y1,2)+Math.pow(y-yline_y1,2)+Math.pow(z-zline_y1,2))
		var ydistance2 = Math.sqrt(Math.pow(x-xline_y2,2)+Math.pow(y-yline_y2,2)+Math.pow(z-zline_y2,2))
		var zdistance1 = Math.sqrt(Math.pow(x-xline_z1,2)+Math.pow(y-yline_z1,2)+Math.pow(z-zline_z1,2))
		var zdistance2 = Math.sqrt(Math.pow(x-xline_z2,2)+Math.pow(y-yline_z2,2)+Math.pow(z-zline_z2,2))
		if (world.getDimension("overworld").getBlock({x:x+vx*segment-0.5, y:y+vy*segment, z:z+vz*segment}).typeId != "minecraft:air") xdistance1 = 9999
		if (world.getDimension("overworld").getBlock({x:x+vx*segment+0.5, y:y+vy*segment, z:z+vz*segment}).typeId != "minecraft:air") xdistance2 = 9999
		if (world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment-0.5, z:z+vz*segment}).typeId != "minecraft:air") ydistance1 = 9999
		if (world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment+0.5, z:z+vz*segment}).typeId != "minecraft:air") ydistance2 = 9999
		if (world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment-0.5}).typeId != "minecraft:air") zdistance1 = 9999
		if (world.getDimension("overworld").getBlock({x:x+vx*segment, y:y+vy*segment, z:z+vz*segment+0.5}).typeId != "minecraft:air") zdistance2 = 9999
		
		var closestCollision = Math.min(xdistance1,xdistance2,ydistance1,ydistance2,zdistance1,zdistance2)
		if ((xline_x1 == xside1) && (yline_x1 >= yside1) && (yline_x1 <= yside2) && (zline_x1 >= zside1) && (zline_x1 <= zside2)) {
			if (closestCollision == xdistance1) {var collisionX = "x1"}
		}
		if ((xline_x2 == xside2) && (yline_x2 >= yside1) && (yline_x2 <= yside2) && (zline_x2 >= zside1) && (zline_x2 <= zside2)) {
			if ( closestCollision == xdistance2) {var collisionX = "x2"}
		}
	
		if ((xline_y1 >= xside1) && (xline_y1 <= xside2) && (yline_y1 == yside1) && (zline_y1 >= zside1) && zline_y1 <= zside2) {
			if ( closestCollision == ydistance1 ) {var collisionY = "y1"}
		}
		if (xline_y2 >= xside1 && xline_y2 <= xside2 && yline_y2 == yside2 && zline_y2 >= zside1 && zline_y2 <= zside2) {
			if ( closestCollision == ydistance2 ) {var collisionY = "y2"}
		}
	
		if (xline_z1 >= xside1 && xline_z1 <= xside2 && yline_z1 >= yside1 && yline_z1 <= yside2 && zline_z1 == zside1) {
			if ( closestCollision == zdistance1 ) {var collisionZ = "z1"}
		}
		if (xline_z2 >= xside1 && xline_z2 <= xside2 && yline_z2 >= yside1 && yline_z2 <= yside2 && zline_z2 == zside2) {
			if ( closestCollision == zdistance2 ) {var collisionZ = "z2"}
		}
		
		if (collisionX == "x1") ball.teleport({x:xline_x1-0.1,y:yline_x1,z:zline_x1})
		else if (collisionX == "x2") ball.teleport({x:xline_x2+0.1,y:yline_x2,z:zline_x2})
		if (collisionY == "y1") ball.teleport({x:xline_y1,y:yline_y1-0.1,z:zline_y1})
		else if (collisionY == "y2") ball.teleport({x:xline_y2,y:yline_y2+0.1,z:zline_y2})
		if (collisionZ == "z1") ball.teleport({x:xline_z1,y:yline_z1,z:zline_z1-0.1})
		else if (collisionZ == "z2") ball.teleport({x:xline_z2,y:yline_z2,z:zline_z2+0.1})
	}
	if (facingBlock != "minecraft:air" && (collisionX == "x1" || collisionX == "x2")) {
		
		vx = -vx*0.8
		if (ballType == "wallball") {
			ball.setDynamicProperty("bonusdamage",ball.getDynamicProperty("bonusdamage")+1)
		}
		if (Math.abs(vx>0.2)) ball.runCommand("/playsound fall.basalt @a[r=30] ~~~ 1 "+(1+0.5*(Math.random()-0.5)))
		
	}
	if ((facingBlock != "minecraft:air" && Math.abs(vy) > 0 && (collisionY == "y1" || collisionY == "y2"))) {

		vy = -vy*0.8
		if (ballType == "rubberball" && Math.abs(vy)>0.2) {
			let speed = Math.sqrt(Math.pow(vx,2)+Math.pow(vz,2))
			vx = 2*(Math.random()-0.5)*vx
			vz = Math.sign(Math.random()-0.5)*Math.sqrt(Math.pow(speed,2)-Math.pow(vx,2))
			if (Math.pow(speed,2)-Math.pow(vx,2)<0) ball.runCommand("/say problem wuth sign")
		}
		if (ballType == "bowling" && Math.abs(vy)>0.2) {
			world.getDimension("overworld").getEntities({
				location: ball.location,
				maxDistance: Math.min(15,vy*2),
				families:["fara:enemy"]
			}).forEach(enemy=>{
				var bowlingDamage = vy*3
				enemy.applyDamage(bowlingDamage)
				var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:enemy.location.x,y:enemy.location.y+2.5,z:enemy.location.z})
				hologram.nameTag = "§7"+Math.floor(bowlingDamage*100)/100
				system.runTimeout(()=>{try {hologram?.runCommand("/event entity @s despawn")} catch {}},40)
			})
			ball.runCommand("/particle fara:dirt_ring")
			vy = 0
			vx = 0
			vz = 0
		}
		if (Math.abs(vy>0.2)) ball.runCommand("/playsound fall.basalt @a[r=30] ~~~ 1 "+(1+0.5*(Math.random()-0.5)))

	}
	if (facingBlock != "minecraft:air" && (collisionZ == "z1" || collisionZ == "z2")) {

		vz = -vz*0.8
		if (ballType == "wallball") {
			if (!ball.getDynamicProperty("bonusdamage")) ball.setDynamicProperty("bonusdamage",0)
			ball.setDynamicProperty("bonusdamage",ball.getDynamicProperty("bonusdamage")+1)
		}
		if (Math.abs(vz>0.2)) ball.runCommand("/playsound fall.basalt @a[r=30] ~~~ 1 "+(1+0.5*(Math.random()-0.5)))

	}
	// var entity = world.getDimension("Overworld").getEntitiesFromRay(ball.location,{x:vx,y:vy,z:vz},{
		// maxDistance: 2*Math.sqrt(Math.pow(vx,2)+Math.pow(vy,2)+Math.pow(vz,2)),
		// families: ["fara:enemy"] })[0]?.entity
		var entity = world.getDimension("overworld").getEntities({
			location: ball.location,
			maxDistance: 2,
			families:["fara:enemy"]
		})[0]
	if (entity && ballType != "ghostball") {
		var originalSpeed = Math.sqrt(Math.pow(vx,2)+Math.pow(vy,2)+Math.pow(vz,2))
		vx = ball.location.x-entity.location.x
		vz = ball.location.z-entity.location.z
		var k = Math.sqrt((Math.pow(originalSpeed,2)-Math.pow(vy,2))/(Math.pow(vx,2)+Math.pow(vz,2)))
		vx = k*vx
		vz = k*vz
		if (!ballType == "bowling") vy = -vy*0.8
	}
	vx = vx*0.99
	vy = vy*0.99
// Puck ball special
	if (ballType == "puck") vy = 0
	vz = vz*0.99
	if (ballType == "balloon") {
		vx = vx*0.9
		vy = vy*0.9
		vz = vz*0.9
	}
	if (Math.abs(vy) < 0.2 && world.getDimension("overworld").getBlock({x:ball?.location.x, y:ball?.location.y-0.1,z:ball?.location.z})?.typeId != "minecraft:air") { vy = 0}
	ball.clearVelocity()
	ball.applyImpulse({x:vx,y:vy,z:vz})
	ball.setDynamicProperty("vx",vx)
	ball.setDynamicProperty("vy",vy)
	ball.setDynamicProperty("vz",vz)
	world.scoreboard.getObjective("debug").setScore("x",x*100)
	world.scoreboard.getObjective("debug").setScore("y",y*100)
	world.scoreboard.getObjective("debug").setScore("z",z*100)
	world.scoreboard.getObjective("debug").setScore("vx",vx*100)
	world.scoreboard.getObjective("debug").setScore("vy",vy*100)
	world.scoreboard.getObjective("debug").setScore("vz",vz*100)
	
};
function summonPerks (location) {
	var randomPerk = Math.floor(Math.random()*perks.length)
	
	var perk = world.getDimension("Overworld").spawnEntity("fara:perk_selection",location)
	perk.setRotation({x:90,y:90})
	perk.triggerEvent(perks[randomPerk])
	var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",location)
	hologram.nameTag = perkToName(perks[randomPerk])
	hologram.runCommand("/tp @s ~~1.2~")
	var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",location)
	hologram.nameTag = "level "+(world.scoreboard.getObjective("perk_"+perks[randomPerk]).getScore("dummy")+1)
	hologram.runCommand("/tp @s ~~0.9~")
	var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",location)
	hologram.nameTag = perks_description[randomPerk]
	hologram.runCommand("/tp @s ~~0.6~")
}
function perkToName (perk) {
	if (perk == "crit") var name = "Crit"
	if (perk == "ballsnumber") var name = "Number of balls"
	if (perk == "damage") var name = "Damage"
	if (perk == "ballspeed") var name = "Ball Speed"
	if (perk == "playerspeed") var name = "Player Speed"
	if (perk == "chargespeed") var name = "Charge Speed"
	if (perk == "knockback") var name = "Knockback"
	if (perk == "slowness") var name = "Slowness"
	if (perk == "lifetime") var name = "Lifetime"
	if (perk == "explode") var name = "Explosion"
	if (perk == "return") var name = "Return"
	if (perk == "drag") var name = "Drag"
	if (perk == "playerknockback") var name = "Player Knockback"
	if (perk == "areaknockback") var name = "Area Knockback"
	if (perk == "resistance") var name = "Resistance"
	if (perk == "hearts") var name = "More Hearts"
	if (perk == "untouchable") var name = "Untouchable"
	if (perk == "split") var name = "Split"
	return name
}
function startLevel (level) {
	world.setDynamicProperty("level",level)
	world.setDynamicProperty("playing",true)
	for (let j = 0; j <= 2*Math.floor(Math.sqrt(level+1)); j++) {
		for (let i = 0; i <=5; i++) {
			let random_level = Math.random()*level
			var zombie_level = Math.floor(Math.max(Math.min(random_level,40),level/2))
			if (zombie_level > 30) var zombie_type = "fara:zombie_pumped"
			else if (zombie_level > 20) var zombie_type = "fara:zombie_big"
			else if (zombie_level > 10) var zombie_type = "fara:zombie_wide"
			else var zombie_type = "fara:zombie"
			var zombie_level = 1+zombie_level%10
			var zombie = world.getDimension("Overworld").spawnEntity(zombie_type,gates[i])
			zombie.triggerEvent("fara:level"+zombie_level)
		}
	}
}

function countMobs () {
	world.scoreboard.getObjective("enemyCount").setScore("dummy",0)
	world.getDimension("Overworld").getEntities({
		families:["fara:enemy"]
	}).forEach((enemy)=>{
		world.scoreboard.getObjective("enemyCount").addScore("dummy",1)
	})
	if (world.scoreboard.getObjective("enemyCount").getScore("dummy") == 0 && world.getDynamicProperty("level") < 50) {
		world.getDimension("Overworld").runCommand("/title @a subtitle")
		world.getDimension("Overworld").runCommand("/title @a title Round "+world.getDynamicProperty("level")+" complete")
		world.setDynamicProperty("playing",false)
		world.getDimension("Overworld").runCommand("/tp @a -5 65 0 270 0")
		var reroll = world.getDimension("Overworld").spawnEntity("fara:reroll",{x:-2.5,y:66,z:-7})
		let rerollsCount =  world.getDynamicProperty("rerolls")
		var price = Math.floor(Math.pow(5,rerollsCount/2))
		reroll.nameTag = "Reroll the perks for $"+price
		summonPerks({x:0,y:66,z:-2.5})
		summonPerks({x:0,y:66,z:2.5})
		var height = 69
		perks.forEach((perkName) => {
			height -= 0.25
			var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:-2.5,y:height,z:7})
			hologram.nameTag = perkToName(perkName)+" §alevel: §6"+world.scoreboard.getObjective("perk_"+perkName).getScore("dummy")
		})
	}
	else if (world.scoreboard.getObjective("enemyCount").getScore("dummy") == 0 && world.getDynamicProperty("level") >= 50) {
		world.getDimension("Overworld").runCommand("/title @a subtitle")
		world.getDimension("Overworld").runCommand("/title @a title Round "+world.getDynamicProperty("level")+" complete")
		world.setDynamicProperty("level",51)
		world.getDimension("Overworld").runCommand("/execute as @p run scriptevent fara:end_game")
	}
}
world.afterEvents.entityHurt.subscribe(event => {
	var target = event.hurtEntity
	var damage = event.damage
	if (target?.typeId == "minecraft:player" && event.damageSource?.cause == "entityAttack") {
//resistance perk
		let attacker = event.damageSource.damagingEntity
		if (attacker.typeId == "minecraft:player") var damage = 5
		if (attacker.typeId == "fara:zombie") var damage = 1+Math.floor(attacker.getComponent("skin_id").value)/3
		if (attacker.typeId == "fara:zombie_wide") var damage = 3+Math.floor(attacker.getComponent("skin_id").value)/3
		if (attacker.typeId == "fara:zombie_big") var damage = 6+Math.floor(attacker.getComponent("skin_id").value)/3
		if (attacker.typeId == "fara:zombie_pumped") var damage = 9+Math.floor(attacker.getComponent("skin_id").value)/3

		var health = target.getComponent("health").currentValue
		var healthMax = target.getComponent("health").effectiveMax
		var healthBefore = target.getComponent("health").effectiveMax
		let resistanceLevel = world.scoreboard.getObjective("perk_resistance").getScore("dummy")
		//player.runCommand("/say damage: "+damage)
		if (resistanceLevel>0) {target.getComponent("health").setCurrentValue(health-damage*Math.pow(0.6,resistanceLevel))}
		else {target.getComponent("health").setCurrentValue(health-Number(damage))}
//untouchable perk
		let untouchableLevel = world.scoreboard.getObjective("perk_untouchable").getScore("dummy")
		if (attacker.typeId.match("fara:zombie")) attacker.applyDamage(5*Math.pow(untouchableLevel,2))
	}
})
system.afterEvents.scriptEventReceive.subscribe( event => {
    let id = event.id
    let message = event.message
    let player = event.sourceEntity
	if (id == 'fara:say') {
		world.getDimension("Overworld").runCommand("/say §6say event")
	}
	if (id == 'fara:start') {
		world.setDynamicProperty("level",1)
		world.setDynamicProperty("rerolls",0)
		let ballType = world.getDynamicProperty("ball")
		if (ballType == "balloon") {
			world.scoreboard.getObjective("perk_explode").setScore("dummy",2)
		}
		world.scoreboard.getObjective("money").setScore("round",0)
		if (Number(message)>0) {
			world.setDynamicProperty("level",Number(message))
			for (let i = 1;i<=Number(message);i++) {
				let randomPerk = Math.floor(Math.random()*perks.length)
				world.scoreboard.getObjective("perk_"+perks[randomPerk]).addScore("dummy",1)
			}
			perks.forEach(perk=>{
				if (world.scoreboard.getObjective("perk_"+perk).getScore("dummy")>0) world.getDimension("overworld").runCommand("/say "+perk+": "+world.scoreboard.getObjective("perk_"+perk).getScore("dummy"))
			})
			world.getPlayers().forEach((player)=>{
				player.triggerEvent("speed"+world.scoreboard.getObjective("perk_playerspeed").getScore("dummy"))
				player.triggerEvent("hearts"+(10+world.scoreboard.getObjective("perk_hearts").getScore("dummy")))
			})
		}
		world.getDimension("Overworld").runCommand("/clear @a")
		world.getDimension("Overworld").runCommand("/tag @e[family=fara:enemy] add scriptKilled")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:enemy]")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:reroll]")
		world.getDimension("Overworld").runCommand("/give @a fara:ball_"+ballType+"_item 1 0 {\"minecraft:item_lock\":{ \"mode\": \"lock_in_inventory\" }}")
		world.getDimension("Overworld").runCommand("/replaceitem entity @a slot.hotbar 5 fara:exit 1 0 {\"minecraft:item_lock\":{\"mode\":\"lock_in_inventory\"}}")
		player.runCommand("/tp @a 0 65 0")
		world.scoreboard.getObjective("countdown").setScore("dummy",0)
		
	}
	if (id == 'fara:end_game') {
		world.getDimension("Overworld").runCommand("/tp @a 115 49 10 90 0")
		world.getDimension("Overworld").runCommand("/clear @a")
		world.getDimension("Overworld").runCommand("/event entity @a speed1")
		world.getDimension("Overworld").runCommand("/event entity @a hearts10")
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:hologram] despawn")
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:perk_selection] despawn")
		world.getDimension("Overworld").runCommand("/tag @e[family=fara:enemy] add scriptKilled")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:enemy]")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:ball]")
		world.scoreboard.getObjective("countdown").setScore("dummy",300)
		if (world.getDynamicProperty("level") >= 51) {
			world.getDimension("Overworld").runCommand("/execute as @e[family=fara:"+world.getDynamicProperty("ball")+"] at @s run event entity @e[family=fara:checkmark,c=1] unlocked")
			world.getDimension("Overworld").runCommand("/execute as @e[family=fara:"+world.getDynamicProperty("ball")+"] at @s run say I am "+world.getDynamicProperty("ball"))
		}
		var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:104,y:51,z:2})
		hologram.nameTag = "Final stats:"
		var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:104,y:50.7,z:2})
		hologram.nameTag = "level: "+world.getDynamicProperty("level")
		var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:104,y:50.4,z:2})
		hologram.nameTag = "time: "+Math.round(world.scoreboard.getObjective("timer").getScore("dummy")/1200)+" minutes"
		var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:104,y:50.1,z:2})
		hologram.nameTag = "zombies killed: "+world.scoreboard.getObjective("killed").getScore("dummy")
		var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:104,y:49.8,z:2})
		hologram.nameTag = "money earned: "+world.scoreboard.getObjective("money").getScore("round")
		world.getDimension("Overworld").runCommand("/scoreboard players set @a chargeTime 0")
		world.getDimension("Overworld").runCommand("/scoreboard players set dummy timer 0")
		world.getDimension("Overworld").runCommand("/scoreboard players set dummy killed 0")
		//world.getDimension("Overworld").runCommand("/give @a fara:ball_item 1 0 {\"minecraft:item_lock\":{ \"mode\": \"lock_in_inventory\" }}")
		//world.getDimension("Overworld").runCommand("/replaceitem entity @a slot.hotbar 5 fara:exit 1 0 {\"minecraft:item_lock\":{\"mode\":\"lock_in_inventory\"}}")
		world.setDynamicProperty("level",0)
		world.setDynamicProperty("playing",false)
		var height = 53
		perks.forEach((perkName) => {
			height -= 0.25
			var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:115,y:height,z:1})
			hologram.nameTag = perkToName(perkName)+" §alevel: §6"+world.scoreboard.getObjective("perk_"+perkName).getScore("dummy")
		})
		for (let i=0; i<perks.length;i++) {
			world.scoreboard.getObjective("perk_"+perks[i]).setScore("dummy",0)
		}
	}
	if (id == 'fara:perk_selection') {
		let perk = event.sourceEntity
		world.setDynamicProperty("level",world.getDynamicProperty("level")+1)
		perk.runCommand("/particle fara:perk_selected ~~-1~")
		perks.forEach((perkName) => {
			if (perk.getComponent("type_family").hasTypeFamily(perkName)) {
				world.scoreboard.getObjective("perk_"+perkName).addScore("dummy",1)
				//world.getDimension("Overworld").runCommand("/tell @a you've selected "+perkToName(perkName)+", new level: "+world.scoreboard.getObjective("perk_"+perkName).getScore("dummy"))
				world.getDimension("overworld").runCommand("/tellraw @a {\"rawtext\":[{\"text\":\"You've selected: "+perkToName(perkName)+" "+world.scoreboard.getObjective("perk_"+perkName).getScore("dummy")+"\"}]}")
			}
		})
// playerspeed perk
		world.getPlayers().forEach((player)=>{
			let perk_playerspeed = world.scoreboard.getObjective("perk_playerspeed").getScore("dummy")
			player.triggerEvent("speed"+Math.min(100,perk_playerspeed))
// hearts perk
			let perk_hearts = world.scoreboard.getObjective("perk_hearts").getScore("dummy")
			player.triggerEvent("hearts"+Math.min(40,perk_hearts+10))
		})
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:hologram] despawn")
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:perk_selection] despawn")
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:reroll] despawn")
		world.scoreboard.getObjective("countdown").setScore("dummy",0)
	}
	if (id == 'fara:ball_selection') {
		let button = event.sourceEntity
		if (button.getComponent("type_family").hasTypeFamily("fara:football")) var ball = "football"
		if (button.getComponent("type_family").hasTypeFamily("fara:fireball")) var ball = "fireball"
		if (button.getComponent("type_family").hasTypeFamily("fara:bowling")) var ball = "bowling"
		if (button.getComponent("type_family").hasTypeFamily("fara:balloon")) var ball = "balloon"
		if (button.getComponent("type_family").hasTypeFamily("fara:rubberball")) var ball = "rubberball"
		if (button.getComponent("type_family").hasTypeFamily("fara:wallball")) var ball = "wallball"
		if (button.getComponent("type_family").hasTypeFamily("fara:puck")) var ball = "puck"
		if (button.getComponent("type_family").hasTypeFamily("fara:golden")) var ball = "golden"
		if (button.getComponent("type_family").hasTypeFamily("fara:ghostball")) var ball = "ghostball"
		//button.runCommand("/say selecting: "+ball)
		let unlockStatus = world.scoreboard.getObjective("ball_"+ball).getScore("dummy")
		var price = world.scoreboard.getObjective("ball_"+ball).getScore("price")
		let money = world.scoreboard.getObjective("money").getScore("dummy")
		
		if (unlockStatus == 1) {
			ballTypes.forEach(ballType=>{
				if (world.scoreboard.getObjective("ball_"+ballType).getScore("dummy") == 2) world.scoreboard.getObjective("ball_"+ballType).setScore("dummy",1)
			})
			button.runCommand("/playsound note.banjo @a")
			world.scoreboard.getObjective("ball_"+ball).setScore("dummy",2)
			world.getDimension("Overworld").runCommand("/event entity @e[family=fara:arrow] despawn")
			world.getDimension("Overworld").runCommand("/execute as @e[family=fara:"+ball+"] at @s run summon fara:arrow ~~1.5~ 90 0")
			world.setDynamicProperty("ball",ball)
		}
		else if (unlockStatus == 0 && money >= price) {
			ballTypes.forEach(ballType=>{
				if (world.scoreboard.getObjective("ball_"+ballType).getScore("dummy") == 2) world.scoreboard.getObjective("ball_"+ballType).setScore("dummy",1)
			})
			button.runCommand("/playsound armor.equip_chain @a")
			world.scoreboard.getObjective("ball_"+ball).setScore("dummy",2)
			world.scoreboard.getObjective("money").addScore("dummy",-price)
			button.runCommand("/event entity @s unlocked")
			button.nameTag = button.nameTag.split("(")[0]
			world.getDimension("Overworld").runCommand("/event entity @e[family=fara:arrow] despawn")
			world.getDimension("Overworld").runCommand("/execute as @e[family=fara:"+ball+"] at @s run summon fara:arrow ~~1.5~ 90 0")
			world.setDynamicProperty("ball",ball)
		}
		else if (unlockStatus == 0 && money < price) {
			button.runCommand("/playsound note.bass @a")
		}
		button.runCommand("/tag @s remove clicked")
	}
	if (id == 'fara:reroll') {
		let button = event.sourceEntity
		//button.runCommand("/say selecting: "+ball)
		var price = Number(button.nameTag.split("$")[1])
		let money = world.scoreboard.getObjective("money").getScore("dummy")
		
		if (money >= price) {
			button.runCommand("/playsound random.pop @a")
			world.getDimension("Overworld").runCommand("/event entity @e[family=fara:hologram] despawn")
			world.getDimension("Overworld").runCommand("/event entity @e[family=fara:perk_selection] despawn")
			world.scoreboard.getObjective("money").addScore("dummy",-price)
			summonPerks({x:0,y:66,z:-2.5})
			summonPerks({x:0,y:66,z:2.5})
			var height = 69
			perks.forEach((perkName) => {
				height -= 0.25
				var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:-2.5,y:height,z:7})
				hologram.nameTag = perkToName(perkName)+" §alevel: §6"+world.scoreboard.getObjective("perk_"+perkName).getScore("dummy")
			})
			world.setDynamicProperty("rerolls",world.getDynamicProperty("rerolls")+1)
			var price = Math.floor(Math.pow(5,world.getDynamicProperty("rerolls")/2))
			button.nameTag = "Reroll the perks for $"+price
		}
		else if (money < price) {
			button.runCommand("/playsound note.bass @a")
			world.getDimension("overworld").runCommand('/tellraw @a {"rawtext":[{"text":"§cNot enough money"}]}')
		}
		button.runCommand("/tag @s remove clicked")
	}
	if (id == 'fara:reset') {
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove lifetime")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove chargeTime")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove timer")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove killed")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove enemyCount")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove immunity")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_crit")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_ballsnumber")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_damage")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_ballspeed")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_playerspeed")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_chargespeed")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_knockback")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_slowness")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_lifetime")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_explode")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_return")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_drag")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_playerknockback")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_areaknockback")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_hearts")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_resistance")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_untouchable")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove perk_split")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_football")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_fireball")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_bowling")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_balloon")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_rubberball")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_wallball")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_puck")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_golden")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove ball_ghostball")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove moneyFancy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove money")
		world.getDimension("Overworld").runCommand("/scoreboard objectives remove countdown")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add lifetime dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add chargeTime dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add timer dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add killed dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add enemyCount dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add immunity dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_crit dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_ballsnumber dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_damage dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_ballspeed dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_playerspeed dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_chargespeed dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_knockback dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_slowness dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_lifetime dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_explode dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_return dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_drag dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_playerknockback dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_areaknockback dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_hearts dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_resistance dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_untouchable dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add perk_split dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_football dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_fireball dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_bowling dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_balloon dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_rubberball dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_wallball dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_puck dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_golden dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add ball_ghostball dummy")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_football 0")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_fireball 1000")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_bowling 2000")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_balloon 1000")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_rubberball 1000")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_wallball 4000")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_puck 3000")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_golden 1500")
		world.getDimension("Overworld").runCommand("/scoreboard players set price ball_ghostball 5000")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add moneyFancy dummy \"§aMoney\"")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add money dummy")
		world.getDimension("Overworld").runCommand("/scoreboard objectives add countdown dummy")
		world.getDimension("Overworld").runCommand("/scoreboard players set dummy money 0")
		
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:enemy] despawn")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:perk_selection] ")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:hologram] ")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:trident_logo] ")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:trident_board] ")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:ball_selection] ")
		world.getDimension("Overworld").runCommand("/kill @e[family=fara:arrow] ")
		world.getDimension("Overworld").runCommand("/summon fara:trident_logo 99 51 7 270 0")
		world.getDimension("Overworld").runCommand("/summon fara:trident_board 110 49 1 0 0")
		var ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<football>", {x: 103, y: 50, z: 11})
		ballSelection.nameTag = "§6Football Ball"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<fireball>", {x: 103, y: 50, z: 9})
		ballSelection.nameTag = "§6Fire Ball §f(§a"+world.scoreboard.getObjective("ball_fireball").getScore("price")+"§f)"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<bowling>", {x: 103, y: 50, z: 7})
		ballSelection.nameTag = "§6Bowling Ball §f(§a"+world.scoreboard.getObjective("ball_bowling").getScore("price")+"§f)"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<balloon>", {x: 103, y: 50, z: 5})
		ballSelection.nameTag = "§6Balloon Ball §f(§a"+world.scoreboard.getObjective("ball_balloon").getScore("price")+"§f)"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<rubberball>", {x: 103, y: 50, z: 3})
		ballSelection.nameTag = "§6Rubber Ball §f(§a"+world.scoreboard.getObjective("ball_rubberball").getScore("price")+"§f)"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<wallball>", {x: 101, y: 50, z: 10})
		ballSelection.nameTag = "§6Wall Ball §f(§a"+world.scoreboard.getObjective("ball_wallball").getScore("price")+"§f)"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<puck>", {x: 101, y: 50, z: 8})
		ballSelection.nameTag = "§6Puck Ball §f(§a"+world.scoreboard.getObjective("ball_puck").getScore("price")+"§f)"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<golden>", {x: 101, y: 50, z: 6})
		ballSelection.nameTag = "§6Golden Ball §f(§a"+world.scoreboard.getObjective("ball_golden").getScore("price")+"§f)"

		ballSelection = world.getDimension("Overworld").spawnEntity("fara:ball_selection<ghostball>", {x: 101, y: 50, z: 4})
		ballSelection.nameTag = "§6Ghost Ball §f(§a"+world.scoreboard.getObjective("ball_ghostball").getScore("price")+"§f)"
		world.getDimension("Overworld").runCommand("/execute as @e[family=fara:ball_selection] at @s run tp @s ~0.5~~0.5")
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:ball_selection] locked")
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:checkmark] despawn")
		world.getDimension("Overworld").runCommand("/execute as @e[family=fara:ball_selection] at @s run summon fara:checkmark ^1^-1^ 270 0 locked")
		world.getDimension("Overworld").runCommand("/event entity @e[family=fara:football] unlocked")
		world.getDimension("Overworld").runCommand("/execute as @e[family=fara:arrow] run say arrow")
		world.getDimension("Overworld").runCommand("/execute as @e[family=fara:football] at @s run summon fara:arrow ~~1.5~ 90 0")
		
		//world.getDimension("Overworld").runCommand("/give @a fara:ball_football 0 1 {\"minecraft:item_lock\":{ \"mode\": \"lock_in_inventory\" }}")
		
		world.setDynamicProperty("playing",false)
		world.setDynamicProperty("ball","football")
		world.getPlayers().forEach((player)=>{
			player.triggerEvent("speed1")
			player.triggerEvent("hearts10")
		})
	}
	if (id == "fara:launch") {
		var ballType = world.getDynamicProperty("ball")
		
		var perk_lifetime = world.scoreboard.getObjective("perk_lifetime").getScore("dummy")
		var perk_ballspeed = world.scoreboard.getObjective("perk_ballspeed").getScore("dummy")
		var perk_chargespeed = world.scoreboard.getObjective("perk_chargespeed").getScore("dummy")
		var perk_playerknockback = world.scoreboard.getObjective("perk_playerknockback").getScore("dummy")
		var perk_areaknockback = world.scoreboard.getObjective("perk_areaknockback").getScore("dummy")
		var perk_ballsnumber = world.scoreboard.getObjective("perk_ballsnumber").getScore("dummy")
		var x = player.location.x
		var y = player.location.y
		if (ballType == "puck") y = 65
		var z = player.location.z
		var viewX = player.getViewDirection().x
		var viewY = player.getViewDirection().y
		if (ballType == "puck") viewY = 0
		var viewZ = player.getViewDirection().z
		player.applyKnockback(player.getViewDirection().x,player.getViewDirection().z,-perk_playerknockback*0.3,0.1*perk_playerknockback)
		player.runCommand("/playsound fara.swoosh2 @a[r=30] ~~~ 0.3 "+(1+0.5*(Math.random()-0.5)))
// areaknockback perk
		if (perk_areaknockback>0) player.runCommand("/particle fara:dirt_ring")
		world.getDimension("Overworld").getEntities({
			families:["fara:enemy"],
			location:player.location,
			maxDistance:5
		}).forEach((enemy)=>{
			enemy.applyKnockback(enemy.location.x-x,enemy.location.z-z,0.5*perk_areaknockback,0.2)
		})
		if (world.getDimension("overworld").getBlock({x:x, y:y+viewY, z:z}).typeId != "minecraft:air") viewY = -viewY
		for (let i = 1; i <= perk_ballsnumber+1; i++) {
			var ball = world.getDimension("Overworld").spawnEntity("fara:ball_"+world.getDynamicProperty("ball"),{x:x,y:y+0.1,z:z})
			world.scoreboard.getObjective("lifetime").setScore(ball,100+perk_lifetime*20)
			ball.setDynamicProperty("bonusdamage",0)
			var chargeTime = Math.min((1+perk_chargespeed)*world.scoreboard.getObjective("chargeTime").getScore(player),60)
			var power = 2*chargeTime/20+Math.sqrt(perk_ballspeed)*0.5
			var vx = viewX*power
			var vy = viewY*power
// Puck ball special
			if (ballType == "puck") vy = 0
			if (ballType == "bowling") {
				vx=0.25*vx
				vy=0.25*vy
				vz=0.25*vz
			}
			var vz = viewZ*power
			if (ballType == "puck") ball.applyImpulse({x:viewX+(Math.random()-0.5)*i,y:viewY,z:viewZ+(Math.random()-0.5)*i})
			if (ballType != "puck") ball.applyImpulse({x:viewX+(Math.random()-0.5)*i,y:viewY+(Math.random()-0.5)*i,z:viewZ+(Math.random()-0.5)*i})
			ball.setDynamicProperty("vx",vx)
			ball.setDynamicProperty("vy",vy)
			ball.setDynamicProperty("vz",vz)
			ball.setDynamicProperty("owner",player.nameTag)
		}
		world.scoreboard.getObjective("chargeTime").setScore(player,0)
	}
})

world.afterEvents.buttonPush.subscribe( event => {
	//world.getDimension("overworld").runCommand('/tellraw @a {"rawtext":[{"text":"Button pressed at: '+event.block.x+' '+event.block.y+' '+event.block.z+'"}]}')

	if (event.block.x == 109 && event.block.y == 50 && event.block.z == 10) {
		world.getDimension("overworld").runCommand("/execute as @p run scriptevent fara:start")
	}
})

world.afterEvents.entitySpawn.subscribe( event => {
	var entity = event.entity
	if (entity.getComponent("type_family")?.hasTypeFamily("fara:furniture")) {
		let rotx = entity.getRotation().x
		let roty = (360+entity.getRotation().y)%360
		if (roty < 45) entity.setRotation({x:0,y:0})
		else if (roty < 135) entity.setRotation({x:0,y:90})
		else if (roty < 225) entity.setRotation({x:0,y:180})
		else if (roty < 315) entity.setRotation({x:0,y:270})
		else entity.setRotation({x:0,y:0})
	}
})


world.afterEvents.itemUse.subscribe( eventData => {
    let player = eventData.source
    let itemUsed = eventData.itemStack
	var x = player.location.x
	var y = player.location.y
	var z = player.location.z
	
	if (itemUsed.typeId == "fara:exit") {
		player.runCommand("/scriptevent fara:end_game")
	}
})
world.afterEvents.entityDie.subscribe( event => {
    let entity = event.deadEntity
	if (entity.typeId == "minecraft:player") {
		entity.runCommand("/scriptevent fara:end_game")
	}
	else if ((entity.typeId == "fara:zombie" || entity.typeId == "fara:zombie_big" || entity.typeId == "fara:zombie_wide" || entity.typeId == "fara:zombie_pumped") && !entity.hasTag("scriptKilled")) {
		if (entity.typeId == "fara:zombie") var reward = 0
		if (entity.typeId == "fara:zombie_wide") var reward = 5
		if (entity.typeId == "fara:zombie_big") var reward = 10
		if (entity.typeId == "fara:zombie_pumped") var reward = 15
		for (let i=1;i<=10;i++) {
			if (entity.getComponent("type_family").hasTypeFamily("fara:level"+i)) reward += Math.ceil(i/2)
		}
		if (world.getDynamicProperty("ball") == "golden") reward = reward*2
		var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:entity.location.x,y:entity.location.y+1.5,z:entity.location.z})
		hologram.nameTag = "§a$"+reward
		world.scoreboard.getObjective("killed").addScore("dummy",1)
		world.scoreboard.getObjective("money").addScore("dummy",reward)
		world.scoreboard.getObjective("money").addScore("round",reward)
		hologram.applyImpulse({x:0,y:0.1,z:0})
		system.runTimeout(()=>{try {hologram?.runCommand("/event entity @s despawn")} catch {}},40)
	}
})


system.runInterval(() => { 
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_ballsnumber matches 0.. run scoreboard players set dummy perk_ballsnumber 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_damage matches 0.. run scoreboard players set dummy perk_damage 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_ballspeed matches 0.. run scoreboard players set dummy perk_ballspeed 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_playerspeed matches 0.. run scoreboard players set dummy perk_playerspeed 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_chargespeed matches 0.. run scoreboard players set dummy perk_chargespeed 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_knockback matches 0.. run scoreboard players set dummy perk_knockback 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_slowness matches 0.. run scoreboard players set dummy perk_slowness 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_lifetime matches 0.. run scoreboard players set dummy perk_lifetime 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_explode matches 0.. run scoreboard players set dummy perk_explode 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_return matches 0.. run scoreboard players set dummy perk_return 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_drag matches 0.. run scoreboard players set dummy perk_drag 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_playerknockback matches 0.. run scoreboard players set dummy perk_playerknockback 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_areaknockback matches 0.. run scoreboard players set dummy perk_areaknockback 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_resistance matches 0.. run scoreboard players set dummy perk_resistance 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_hearts matches 0.. run scoreboard players set dummy perk_hearts 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_untouchable matches 0.. run scoreboard players set dummy perk_untouchable 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_split matches 0.. run scoreboard players set dummy perk_split 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy perk_crit matches 0.. run scoreboard players set dummy perk_crit 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_football matches 0.. run scoreboard players set dummy ball_football 2")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_fireball matches 0.. run scoreboard players set dummy ball_fireball 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_bowling matches 0.. run scoreboard players set dummy ball_bowling 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_balloon matches 0.. run scoreboard players set dummy ball_balloon 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_rubberball matches 0.. run scoreboard players set dummy ball_rubberball 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_wallball matches 0.. run scoreboard players set dummy ball_wallball 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_puck matches 0.. run scoreboard players set dummy ball_puck 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_golden matches 0.. run scoreboard players set dummy ball_golden 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy ball_ghostball matches 0.. run scoreboard players set dummy ball_ghostball 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy timer matches 0.. run scoreboard players set dummy timer 0")
	world.getDimension("Overworld").runCommand("/execute as @a unless score dummy killed matches 0.. run scoreboard players set dummy killed 0")
	world.getDimension("Overworld").runCommand("/execute as @e[family=fara:enemy] unless score @s immunity matches 0.. run scoreboard players set @s immunity 0")
	world.getDimension("Overworld").runCommand("/execute as @e[family=fara:enemy] unless score @s slowness matches 0.. run scoreboard players set @s slowness 0")
	world.getDimension("Overworld").runCommand("/kill @e[type=item]")
	world.getDimension("Overworld").runCommand("/scoreboard players operation total moneyFancy = dummy money")
	world.getDimension("Overworld").runCommand("/execute if entity @p[x=115,y=49,z=10,r=20] run tag @a add displayMoney")
	world.getDimension("Overworld").runCommand("/execute unless entity @p[x=115,y=49,z=10,r=20] run tag @a remove displayMoney")
	world.getDimension("Overworld").runCommand("/execute if score dummy enemyCount matches 0 run tag @a add displayMoney")
	world.getDimension("Overworld").runCommand("/execute if entity @p[tag=displayMoney] run scoreboard objectives setdisplay sidebar moneyFancy")
	world.getDimension("Overworld").runCommand("/execute unless entity @a[tag=displayMoney] run scoreboard objectives setdisplay sidebar")
	
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches ..300 run scoreboard players add dummy countdown 1")
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches 5 run title @a subtitle starts in 10s")
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches 5 run title @a title Round "+world.getDynamicProperty("level"))
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches 144 run title @a subtitle")
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches 145 run title @a title 3")
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches 165 run title @a title 2")
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches 185 run title @a title 1")
	world.getDimension("Overworld").runCommand("/execute if score dummy countdown matches 205 run title @a title Zombies are coming!")
	if (world.scoreboard.getObjective("countdown").getScore("dummy") == 205) startLevel(world.getDynamicProperty("level"))
	
	
	world.getPlayers().forEach((player)=>{
		let perk_playerspeed = world.scoreboard.getObjective("perk_chargespeed").getScore("dummy")
		
		let perk_chargespeed = world.scoreboard.getObjective("perk_chargespeed").getScore("dummy")
// chargespeed perk
		var chargeTime = Math.min((1+perk_chargespeed)*world.scoreboard.getObjective("chargeTime").getScore(player),60)
		if (chargeTime > 0){
			var powerDisplay = ""
			for (let i = 0; i<=chargeTime/2;i++) {
				powerDisplay += ""
			}
			player.onScreenDisplay.setActionBar(powerDisplay);
		}
	})
	if (world.getDimension("Overworld").getEntities({families:["fara:enemy"]}).length>0) world.setDynamicProperty("playing",1)
	if (world.getDynamicProperty("playing")) {
		world.getDimension("Overworld").runCommand("/scoreboard players add dummy timer 1")
		countMobs()
	}
	world.getDimension("Overworld").getEntities({
		families:["fara:ball_selection"]
	}).forEach((button)=>{
		if (button.getComponent("variant").value == 0) button.dimension.setBlockType({x:button.location.x,y:button.location.y-1,z:button.location.z},"minecraft:coal_block")
		if (button.getComponent("variant").value == 1) button.dimension.setBlockType({x:button.location.x,y:button.location.y-1,z:button.location.z},"minecraft:gold_block")
	})
	world.getDimension("Overworld").getEntities({
		families:["fara:enemy"]
	}).forEach((enemy)=>{
		enemy.runCommand("/execute unless score @s immunity matches 0.. run scoreboard players set @s immunity 0")
		enemy.runCommand("/execute unless score @s slowness matches 0.. run scoreboard players set @s slowness 0")
		if (world.scoreboard.getObjective("immunity").getScore(enemy)>0) world.scoreboard.getObjective("immunity").addScore(enemy,-1)
		if (world.scoreboard.getObjective("slowness").getScore(enemy)>0) world.scoreboard.getObjective("slowness").addScore(enemy,-1)
		if (world.scoreboard.getObjective("slowness").getScore(enemy) <= 0) enemy.getComponent("movement").setCurrentValue(enemy.getComponent("movement").defaultValue)
	})
	world.getDimension("Overworld").getEntities({
		families:["fara:ball"]
	}).forEach((ball)=>{
		var playerName = ball.getDynamicProperty("owner")
		var player = world.getDimension("Overworld").getPlayers({name: playerName})[0]
		var perk_explode = world.scoreboard.getObjective("perk_explode").getScore("dummy")
		var perk_return = world.scoreboard.getObjective("perk_return").getScore("dummy")
		var perk_slowness = world.scoreboard.getObjective("perk_slowness").getScore("dummy")
		var perk_drag = world.scoreboard.getObjective("perk_drag").getScore("dummy")
		var perk_split = world.scoreboard.getObjective("perk_split").getScore("dummy")
		var perk_damage = world.scoreboard.getObjective("perk_damage").getScore("dummy")
		var perk_crit = world.scoreboard.getObjective("perk_crit").getScore("dummy")
		var perk_knockback = world.scoreboard.getObjective("perk_knockback").getScore("dummy")
		world.getDimension("Overworld").getEntities({
			families:["fara:enemy"],
			location: ball.location,
			maxDistance: 2.5
		}).forEach((enemy)=>{
			var immunity = world.scoreboard.getObjective("immunity").getScore(enemy)
			if (immunity == 0) {
				var critChance = Math.random()*100
				var speedDamage = Math.sqrt(Math.pow(ball.getVelocity().x,2)+Math.pow(ball.getVelocity().y,2)+Math.pow(ball.getVelocity().z,2))
				if (world.getDynamicProperty("ball") == "balloon") speedDamage = 0
				if (world.getDynamicProperty("ball") == "fireball") enemy.setOnFire(3+Math.floor(speedDamage))
				if (!ball.getDynamicProperty("bonusdamage")) ball.setDynamicProperty("bonusdamage",0)
// damage perk
				var damage = (Math.sqrt(speedDamage)+1)*Math.pow((perk_damage+1),0.5)+ball.getDynamicProperty("bonusdamage")
// crit perk
				if (critChance <= perk_crit*5) damage *= 2
				enemy.applyDamage(damage)
				enemy.runCommand("/playsound fara.punch @a[r=20] ~~~ 0.5 "+(1+0.5*(Math.random()-0.5)))
				var hologram = world.getDimension("Overworld").spawnEntity("fara:hologram",{x:enemy.location.x,y:enemy.location.y+2,z:enemy.location.z})
				hologram.nameTag = "§6"+Math.floor(damage*100)/100

				if (critChance <= perk_crit*5) hologram.nameTag = "§c§l Crit! "+Math.floor(damage*100)/100
				hologram.applyImpulse({x:0,y:0.1,z:0})
				system.runTimeout(()=>{try {hologram?.runCommand("/event entity @s despawn")} catch {}},40)
// knockback perk
				var horizontalKnockback = (perk_knockback+1)*Math.sqrt(Math.pow(ball.getVelocity().x,2)+Math.pow(ball.getVelocity().z,2))
				var verticalKnockback = (perk_knockback+1)*Math.abs(ball.getVelocity().y)
				enemy.applyKnockback(ball.getVelocity().x,ball.getVelocity().z,horizontalKnockback,verticalKnockback)
				world.scoreboard.getObjective("immunity").setScore(enemy,4)
// split perk
				var splitChance = Math.random()*100
				if (splitChance <= Math.sqrt(perk_split*30) && !ball.hasTag("splitball")) {
					ball.runCommand("/playsound mob.fox.spit @a[r=30]")
					var splitball = world.getDimension("Overworld").spawnEntity("fara:ball_"+world.getDynamicProperty("ball"),{x:ball.location.x,y:ball.location.y,z:ball.location.z})
					world.scoreboard.getObjective("lifetime").setScore(splitball,50)
					splitball.triggerEvent("small")
					splitball.addTag("splitball")
					var vx2 = -ball.getDynamicProperty("vx")*0.8
					var vy2 = Math.abs(ball.getDynamicProperty("vy"))*0.8
					var vz2 = -ball.getDynamicProperty("vz")*0.8

					splitball.applyImpulse({x:vx2,y:vy2,z:vz2})
					splitball.setDynamicProperty("vx",vx2)
					splitball.setDynamicProperty("vy",vy2)
					splitball.setDynamicProperty("vz",vz2)
					splitball.setDynamicProperty("owner",ball.getDynamicProperty("owner"))
				}
// drag perk
				var dragChance = Math.random()*100
				if (perk_drag*5>dragChance && !ball.hasTag("splitball")) {
					enemy.getComponent("leashable")?.leashTo(ball)
				}
//slowness perk
				enemy.getComponent("movement").setCurrentValue(enemy.getComponent("movement").defaultValue/(1+0.2*perk_slowness))
				world.scoreboard.getObjective("slowness").setScore(enemy,20+2*perk_slowness)
			}
		})
		physics(ball)
		world.scoreboard.getObjective("lifetime").addScore(ball,-1)
		if (world.scoreboard.getObjective("lifetime").getScore(ball) <=0) {
			if (perk_explode>0 && !ball.hasTag("splitball")) {
				ball.runCommand("/damage @e[family=fara:enemy,r="+(2+perk_explode)+"] "+perk_explode)
				ball.runCommand("/playsound cauldron.explode @a[r=30] ~~~ 1 1")
				ball.runCommand("/playsound breeze_wind_charge.burst @a[r=30] ~~~ 1 1")
				ball.runCommand("/particle minecraft:breeze_wind_explosion_emitter")
				world.getDimension("Overworld").getEntities({
					families:["fara:enemy"],
					location:ball.location,
					maxDistance:2+perk_explode
				}).forEach((enemy)=>{
					enemy.applyKnockback(enemy.location.x-ball.location.x,enemy.location.z-ball.location.z,0.5*perk_explode,0.2)
				})
			}
			ball.runCommand("/event entity @s despawn")
		}
		else if (ball.location.y <= 60) {
			ball.runCommand("/event entity @s despawn")
		}
		else if (Math.abs(ball.location.z) >= 70) {
			ball.runCommand("/event entity @s despawn")
		}
		else if (Math.abs(ball.location.x) >= 82) {
			ball.runCommand("/event entity @s despawn")
		}
// return perk
		else if (world.scoreboard.getObjective("lifetime").getScore(ball) == 40 && perk_return>0) {
			var vx = ball.getDynamicProperty("vx")
			var vy = ball.getDynamicProperty("vy")
			var vz = ball.getDynamicProperty("vz")
			var originalSpeed = Math.sqrt(Math.pow(vx,2)+Math.pow(vy,2)+Math.pow(vz,2))
			vx = player.location.x-ball.location.x
			vz = player.location.z-ball.location.z
			var k = Math.sqrt((Math.pow(originalSpeed,2)-Math.pow(vy,2))/(Math.pow(vx,2)+Math.pow(vz,2)))*(1+0.2*perk_return)
			vx = k*vx
			vz = k*vz
			vy = -vy*0.8
			ball.setDynamicProperty("vx",vx)
			ball.setDynamicProperty("vy",vy)
			ball.setDynamicProperty("vz",vz)
		}
	})
	
}, 1);