

Class GWCoin : Inventory {

	int age;
	int maxAge;
	PlayerPawn player;

	Default {
		Inventory.MaxAmount 99999;
		Inventory.Amount 2;
		Inventory.PickupMessage "";
		Inventory.PickupSound "coins/inventory/up";
		+BRIGHT;
	}
	
	states {
		Spawn:
			COIN A 5;
			COIN B 5 checkAge();
			Loop;
		Decaying:
			COIN A 2;
			COIN B 2;
			TNT1 A 2;
			Loop;
	}

	override void PostBeginPlay() {
		self.maxAge = 350 + random(0, 50);
	}

	action void checkAge() {
		if (invoker.age > invoker.maxAge - 100) {
			invoker.SetState(ResolveState("Decaying"));
		}
	}
	
	override void Tick() {
		super.Tick();
		if (self.owner) { 
			return;
		}
		age++;
		if (age > maxAge){
			player = players[consoleplayer].mo;

				double coinsToGiveFloat = self.Amount / 2;
				// console.printf("Coins to Give: %f", coinsToGiveFloat);
				floor(coinsToGiveFloat);
				// console.printf("Coins to Give Floored: %f", coinsToGiveFloat);
				int coinsToGiveWhole = int(coinsToGiveFloat);
				// console.printf("Coins to Give Whole Conversion: %d", coinsToGiveWhole);

			player.GiveInventory("GWCoin", coinsToGiveWhole);
			// console.printf("Destroying %s", self.getClassName());
			self.Destroy();
		}
	}

	void makeBig() {
		self.Scale = (2,2);
		self.Amount = 10;
		self.maxAge = 700 + random (0, 300);
	}
	
}

Class DeathOfMonsterEventHandler : EventHandler {

	override void WorldThingDied(WorldEvent event) {
		vector3 monsterPosition = event.Thing.pos;
		double monsterHeight = event.Thing.height;
		ScoreMultiplierThinker multiplier = ScoreMultiplierThinker.GetInstance();
		double remainingHealth = event.Thing.GetMaxHealth();

		double monsterPoints = remainingHealth * multiplier.scoreMultiplier;
		floor(monsterPoints);
		int monsterPointsWhole = int(monsterPoints);

		multiplier.scoreFinal = monsterPointsWhole + multiplier.scoreFinal;

		multiplier.RaiseMultiplier();
		// console.printf("Points for %s after multiplying: %f", event.Thing.getClassName(), monsterPoints);

		while (remainingHealth >= 10) {
		
			GWCoin coin = GWCoin(Actor.Spawn("GWCoin",
				(
					monsterPosition.x,
					monsterPosition.y, 
					monsterPosition.z + monsterHeight/2
				)
			));

			if (remainingHealth >= 100) {
				coin.makeBig();
				remainingHealth -= 100;
			} else {
				remainingHealth -= 10;
			}

			vector3 coinVelocity = (
				frandom(-3, 3),
				frandom(-3, 3),
				frandom(5, 10)
			);

			coin.vel = coinVelocity;

		}

	}
	
}

Class CoinUIHandler : EventHandler {

	override void RenderOverlay(RenderEvent event) {

		if (AutoMapActive){
			return;
		}

		PlayerPawn player = players[consoleplayer].mo;

		int coins = player.CountInv("GWCoin");

		ScoreMultiplierThinker scoreThinker = ScoreMultiplierThinker.GetReadOnlyInstance();

		string scoreMultiplierString = String.Format("x%.1f", scoreThinker.scoreMultiplier);
		string scoreFinalString = String.Format("Score - %d", scoreThinker.scoreFinal);
		String coinsString = String.Format("%d", coins);

		Statusbar.BeginHUD();
		HUDFont regularfont = HUDFont.Create(smallfont);
		HUDFont biggerfont = HUDFont.Create(smallfont);

		Statusbar.DrawImage("HUDCOIN", (50, 46),
			Statusbar.DI_SCREEN_LEFT_TOP | Statusbar.DI_ITEM_TOP |
			Statusbar.DI_ITEM_LEFT
		);

		Statusbar.DrawString(biggerfont, coinsString, (100, 48), 
			Statusbar.DI_SCREEN_LEFT_TOP | Statusbar.DI_TEXT_ALIGN_RIGHT,
			Font.CR_GOLD, scale: (1.25, 1.25)
		);

		Statusbar.DrawString(biggerfont, scoreFinalString, (-80, 50), 
			Statusbar.DI_SCREEN_RIGHT_TOP | Statusbar.DI_TEXT_ALIGN_RIGHT,
			Font.CR_GOLD, scale: (1.5, 1.5)
		);

		Statusbar.DrawString(biggerfont, scoreMultiplierString, (-75, 46), 
			Statusbar.DI_SCREEN_RIGHT_TOP | Statusbar.DI_TEXT_ALIGN_LEFT,
			Font.CR_FIRE, scale: (2, 2)
		);

		Statusbar.DrawBar("HUDBAR", "",
			scoreThinker.countdown, scoreThinker.countdownMax,
			(100, 60), 0, Statusbar.SHADER_HORZ,
			Statusbar.DI_SCREEN_LEFT_TOP | Statusbar.DI_ITEM_LEFT_TOP
		);

	}

	override bool InputProcess(InputEvent event) {

		int bind1, bind2 = Bindings.GetKeysForCommand("+user1");
		if ((event.KeyScan == bind1 || event.KeyScan == bind2) && event.Type == InputEvent.Type_KeyDown){
			EventHandler.SendNetworkEvent("coinInefficientHeal");
		}
		return false;

	}

	override void NetworkProcess(ConsoleEvent event) {
		if (event.Name == "coinInefficientHeal"){
			PlayerPawn player = players[event.player].mo;
			int coins = player.CountInv("GWCoin");
			if (coins > 25) {
				player.TakeInventory("GWCoin", 25);
				player.GiveInventory("HealthBonus", 5);
				player.A_StartSound("misc/p_pkup");
			}
		}
	}

}

class ScoreMultiplierThinker : Thinker

{

    double scoreMultiplier;
	int scoreFinal;
	int ticksSinceKill;
    int countdown;
	int countdownMax;

   

    ScoreMultiplierThinker Init(void) {

        ChangeStatNum(STAT_USER);

        self.scoreMultiplier = 1;
		self.countdownMax = 350;


        return self;

    }


    static ScoreMultiplierThinker GetInstance(void) {

        ThinkerIterator it = ThinkerIterator.Create("ScoreMultiplierThinker", STAT_USER);

        let instance = ScoreMultiplierThinker(it.Next());

        if (instance) return instance;

        return new("ScoreMultiplierThinker").Init();

    }

	static clearscope ScoreMultiplierThinker GetReadOnlyInstance(void) {

        ThinkerIterator it = ThinkerIterator.Create("ScoreMultiplierThinker", STAT_USER);

        let instance = ScoreMultiplierThinker(it.Next());

        if (instance) return instance;

        return null;

    }

	void RaiseMultiplier() {

        self.ticksSinceKill = 0;
		self.countdown = self.countdownMax;
        self.scoreMultiplier += 0.1;

		// console.printf("Current Score: %d", self.scoreFinal);

    }

    override void Tick() {

		if (self.countdown > 0) {
			self.countdown -= 1;
			return;
		}
		self.scoreMultiplier = 1;
		
    }

}

Class WaveGameSetupHandler : EventHandler {

	override void WorldLoaded(WorldEvent event)
	{
		ScoreMultiplierThinker.GetInstance();
	}

}

class GWCoinBuyableItem {

	int cost;
	TextureID texture;
	string itemClassName;
	int itemQuantitiy;

	GWCoinBuyableItem Init(int cost, string texture, string itemClassName, int itemQuantity) {

        self.cost = cost;

        self.texture = TexMan.CheckForTexture(texture, TexMan.Type_Any);

        self.itemClassName = itemClassName;

        self.itemQuantitiy = itemQuantitiy;

        return self;

    }

}

class GWCoinDataLibrary : Thinker
{

	Array<GWCoinBuyableItem> buyableItems;

    GWCoinDataLibrary Init(void) {

        ChangeStatNum(STAT_STATIC);
		self.buyableItems.push(new("GWCoinBuyableItem").Init(20, "STIMA0", "HealthBonus", 10));
		return self;

    }

    static GWCoinDataLibrary GetInstance(void) {

        ThinkerIterator it = ThinkerIterator.Create("GWCoinDataLibrary", STAT_STATIC);

        let instance = GWCoinDataLibrary(it.Next());

        if (instance) return instance;

        return new("GWCoinDataLibrary").Init();

    }

	static clearscope GWCoinDataLibrary GetReadOnlyInstance(void) {

        ThinkerIterator it = ThinkerIterator.Create("GWCoinDataLibrary", STAT_STATIC);

        let instance = GWCoinDataLibrary(it.Next());

        if (instance) return instance;

        return null;

    }

}

Class WaveShotgunGuy : ShotgunGuy
{
	Default
	{
		dropitem "";
	}
	
	States
	{
	
		Missile:
		SPOS E 10 A_FaceTarget;
		SPOS E 0 A_StartSound("tracer/attack/shotgun", CHAN_WEAPON);
		SPOS EEEEEE 0 A_SpawnProjectile("MonsterTracer", 36, 0, random(-7, 7), 1, random(-4, 4));
		SPOS E 10;
		Goto See;
	
	}
	
}

Class GWMissileZombieMan : ZombieMan
{

	Default
	{
		dropitem "";
	}
	
	States
	{
		Missile:
		POSS E 10 A_FaceTarget;
		POSS E 0 A_StartSound("tracer/attack/rifle", CHAN_WEAPON);
		POSS F 8 A_SpawnProjectile("MonsterTracer", 36, 0, 0, 1, 0);
		POSS E 8;
		Goto See;
	}

}

Class WaveChaingunGuy : ChaingunGuy
{

	Default
	{
		dropitem "";
	}
	
	States
	{
	
		Missile:
		CPOS E 10 A_FaceTarget;
		CPOS E 0 A_StartSound("tracer/attack/chaingun", CHAN_WEAPON);
		CPOS FE 2 A_SpawnProjectile("MonsterTracer", 36, 0, random(-3, 3), 1, random(-1, 1));
		CPOS F 1 A_MonsterRefire(130, "See");
		Goto Missile+1;
	}
	
}

Class WaveCyberdemon : Cyberdemon
{

	Default
	{
	
		+LOOKALLAROUND;
		+MISSILEMORE;
		+MISSILEEVENMORE;
		+QUICKTORETALIATE;
		+DONTTHRUST;
		
		MinMissileChance 1;
	
	}
	
	States
	{
		Missile:
		CYBR E 9 A_FaceTarget;
		CYBR F 5 A_SpawnProjectile("WaveCyberdemonRocket", 48, -20, random(-1, 1), 0, random(-1, 1));
		CYBR F 5 A_SpawnProjectile("WaveCyberdemonRocket", 48, -20, random(-2, 2), 0, random(-2, 2));
		CYBR F 5 A_SpawnProjectile("WaveCyberdemonRocket", 48, -20, random(-3, 3), 0, random(-3, 3));
		CYBR E 2 A_MonsterRefire(130, "See");
		Loop;
	}

}

Class WaveCyberdemonRocket : Rocket
{

	Default
	{
		+SEEKERMISSILE;
		Speed 25;
	
	}
	
	States
	
	{
		MISL A 2 Bright A_SeekerMissile(30, 60);
		Loop;
	}

}

class GWEmsRifleBase : DoomWeapon
{
	action void A_FireEms(int damage, color c_ring, color c_core, string puffType) {
	
	if(player == null)
		{
			return;
		}
		
		A_RailAttack(
		damage, //damage
		0, //spawnofs xy
		true, //useammo
		c_ring, //ring colour
		c_core, //core colour
		RGF_EXPLICITANGLE | //flags
		RGF_SILENT, 
		0, //diff
		puffType, //puff
		0, //spread xy
		BulletSlope() - pitch, //spread z 
		0, //range
		52, //duration
		0.5, //sparsity
		-0.8, //drift speed
		null, //spawn class
		0,  //spawnofs_z
		10); //spiral offset
	}
}

Class GWHellstormCannon : Weapon
{
  Default
  {
    Obituary "%o was obliterated by %k's HellStorm Cannon!";
	Weapon.SlotNumber 7;
    Weapon.SelectionOrder 5000;
    Weapon.AmmoUse 1;
    Weapon.AmmoGive 8;
    Weapon.AmmoType "GWImpactGrenade";
    Inventory.PickupMessage "You got the HellStorm Cannon";
    +Weapon.NoAutoFire
    +Weapon.NoAutoAim
  }

  States
  {
  Ready:
    HSTM B 1 A_WeaponReady();
    Loop;
  Deselect:
    HSTM B 1 A_Lower();
    Loop;
  Select:
    HSTM B 1 A_Raise();
    Loop;
  Fire:
    HSTM C 4 Bright A_GunFlash();
    HSTM D 5 Bright
    {
      A_StartSound("HellStorm/Fire", CHAN_WEAPON);
      A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 1, 0, 0, 0, Random(-6, 2));
	  A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 1, 0, 0, 0, Random(-6, 2));
	  A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 1, 0, 0, 0, Random(-6, 2));
	  A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb1", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb2", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb3", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 0, 0, 0, 0, Random(-6, 2));
      A_FireProjectile("GWHellStormBomb4", Random(-9, 9), 1, 0, 0, 0, Random(-6, 2));
    }
    HSTM EF 6 Bright;
    HSTM B 6;
    HSTM B 45 A_StartSound("HellStorm/Reload", CHAN_6);
    Goto Ready;
  Flash:
    TNT1 A 1;
    Stop;
  Spawn:
    HSTM A -1;
    Stop;
  }
}

Class GWHellStormBomb1 : Actor
{
  Default
  {
    Radius 16;
    Height 8;
    Speed 35;
    Damage 10;
    Gravity 0.3;
    Scale 0.5;
    DeathSound "HellStorm/Hit";
    Decal "RevenantScorch";
    Projectile;
    -NoGravity
  }

  States
  {
  Spawn:
    HSBM A 1 Bright;
    Loop;
  Death:
    MISL B 8 Bright
    {
      bNoGravity=true;
      A_Explode(64, 64, XF_HURTSOURCE);
    }
    MISL C 6 Bright;
    MISL D 4 Bright;
    Stop;
  }
}

Class GWHellStormBomb2 : GWHellStormBomb1
{
  Default
  {
    Speed 24;
    Gravity 0.28;
  }
}

Class GWHellStormBomb3 : GWHellStormBomb1
{
  Default
  {
    Speed 23;
    Gravity 0.26;
  }
}

Class GWHellStormBomb4 : GWHellStormBomb1
{
  Default
  {
    Speed 22;
    Gravity 0.24;
  }
}

Class GWImpactGrenade : Ammo
{
  Default
  {
    Inventory.PickupMessage "You got some impact grenades";
    Inventory.Amount 4;
    Inventory.MaxAmount 80;
    Ammo.BackpackAmount 4;
    Ammo.BackpackMaxAmount 80;
    Inventory.Icon "HSBMA7A3";
  }

  States
  {
  Spawn:
    HSAM A -1;
    Stop;
  }
}

Class GWImpactGrenadeBox : GWImpactGrenade
{
  Default
  {
    Inventory.PickupMessage "You got a box of impact grenades";
    Inventory.Amount 20;
  }

  States
  {
  Spawn:
    HSAM B -1;
    Stop;
  }
}

Class WaveAmmoUpgrade : PowerInfiniteAmmo
{
	Default
	{
		
		Inventory.Icon "AIUPA0";
		Powerup.Duration -20;
	}

}

Class WaveAmmoUpgradeSecond : WaveAmmoUpgrade
{
	Default
	{
		
		Inventory.Icon "AIUPA0";
		Powerup.Duration -40;
	}

}

Class WaveAmmoUpgradeFinal : WaveAmmoUpgrade
{
	Default
	{
		
		Inventory.Icon "AIUPA0";
		Powerup.Duration 0x7FFFFFFD;
	}

}

Class WaveDamageUpgrade : PowerDamage
{
	Default
	{
		+INVENTORY.PERSISTENTPOWER;
		
		Inventory.Icon "DDUPA0";
		Powerup.Duration 0x7FFFFFFD;
		Damagefactor "normal", 2;
		
	}

}

Class WaveDamageUpgradeSecond : WaveDamageUpgrade
{
	Default
	{
		Damagefactor "normal", 3;
	}

}

Class WaveDamageUpgradeFinal : WaveDamageUpgrade
{
	Default
	{
		Damagefactor "normal", 5;
	}

}

Class WaveFlightUpgrade : PowerFlight
{
	Default
	{
		
		Inventory.Icon "FLUPA0";
		Powerup.Duration -30;
		
	}

}

Class WaveFlightUpgradeSecond : PowerFlight
{
	Default
	{
		
		Inventory.Icon "FLUPA0";
		Powerup.Duration -60;
		
	}

}

Class WaveFlightUpgradeFinal : PowerFlight
{
	Default
	{
		
		Inventory.Icon "FLUPA0";
		Powerup.Duration 0x7FFFFFFD;
		
	}

}

Class WaveDefenceUpgrade : PowerProtection
{
	Default
	{
		Inventory.Icon "QDUPA0";
		Damagefactor "Normal", 0.6;
		Powerup.Duration 0x7FFFFFFD;
	}
}

Class WaveDefenceUpgradeSecond : WaveDefenceUpgrade
{
	Default
	{
		Damagefactor "Normal", 0.4;
	}
}

Class WaveDefenceUpgradeFinal : WaveDefenceUpgrade
{
	Default
	{
		Damagefactor "Normal", 0.2;
	}
}

Class WaveFireSpeedUpgrade : PowerDoubleFiringSpeed
{
	Default
	{
		Inventory.Icon "FSUPA0";
		Powerup.Duration 0x7FFFFFFD;
	}
}

Class WaveInvulnerabilityUpgrade : PowerInvulnerable
{
	Default{
		Inventory.Icon "IVUPA0";
	
		Powerup.Duration -15;
		Powerup.Color "0 0 0", 0;
	}
}

Class WaveInvulnerabilityUpgradeSecond : WaveInvulnerabilityUpgrade
{
	Default{
		Powerup.Duration -30;
	}
}

Class WaveInvulnerabilityUpgradeFinal : WaveInvulnerabilityUpgrade
{
	Default{
		Powerup.Duration -45;
	}
}

Class Tracer : FastProjectile
{

	Default
	{
		+DONTSPLASH
		+FORCEXYBILLBOARD
		+NOEXTREMEDEATH
		+MISSILE
		+RANDOMIZE
		
		Damage 0;
		Height 3;
		Radius 6;
		RenderStyle "Normal";;
		Scale 0.5;
		Speed 15;
	}

}

Class MonsterTracer: Tracer
{
	Default
	{
		+BLOODSPLATTER 
		+THRUGHOST
		-DONTSPLASH
		+MISSILE
		Speed 25;
		Damage 3;
		DamageType "Bullet";
	}
	States
	{
		Spawn:
			ZMMS A 1 BRIGHT;
			ZMMS A 0 ThrustThingZ(0,random(-8, 8),0,1);
			ZMMS B 1 BRIGHT;
			Goto Spawn2;
			
		Spawn2:
			ZMMS A 1 BRIGHT;
			Loop;    
			
	Death:
		LSER A 1 BRIGHT;
		Stop;
	}
}


