From 5ebf31e057677952d84f702effd27373beeb3e48 Mon Sep 17 00:00:00 2001 From: Robert Fritzen Date: Thu, 12 Feb 2015 19:45:18 -0600 Subject: [PATCH] 3.9.1 Update Patched up some TWM2 bugs, re-did the Vardison Boss. --- scripts/TWM2/Bosses/LordVardison.cs | 3041 +++++++++++----------- scripts/TWM2/ChatCommands/Public.cs | 2 +- scripts/TWM2/ChatCommands/SuperAdmin.cs | 6 +- scripts/TWM2/Systems/BossSystem.cs | 104 +- scripts/TWM2/Systems/NWChallengeIndex.cs | 4 + scripts/TWM2/Zombie/ZombieCreation.cs | 4 +- scripts/chatCommands.cs | 4 - scripts/packs/Medpack.cs | 8 +- scripts/packs/ZSpawnpack.cs | 45 +- scripts/player.cs | 11 + scripts/weapons/Other/ShadowRifle.cs | 43 - 11 files changed, 1697 insertions(+), 1575 deletions(-) diff --git a/scripts/TWM2/Bosses/LordVardison.cs b/scripts/TWM2/Bosses/LordVardison.cs index d60a120..54c93da 100644 --- a/scripts/TWM2/Bosses/LordVardison.cs +++ b/scripts/TWM2/Bosses/LordVardison.cs @@ -1,6 +1,238 @@ -//LORD \/ARDISON & Dark Archmage Vardison -//THIS BOSS WILL MURDER OCCULTBADBOY -//Yeah, he really will +//Lord Vardison +//Version 2.0 +//Revised And Reimagined... The Pure Evil of TWM2 Has Been Reborn, Now With Less Crashing xD +// Now with difficulty levels :P +// 1, Easy: Standard Vardison Battle +// - Limited Mobs +// - Attacks On Normal +// - Has Timed Grab Kills +// 2, Normal: Tougher Vardison Battle +// - Enhanced Mob Spawns +// - Slightly Faster Attacks +// - Phase 3 Insta-Kills +// - Shadow Orb Mechanic: Deaths to phase 3 initiate Shadow Orb, which is a 20 second to kill all mechanic. +// 3, Hard: The True Experience +// - Minions A Plenty +// - Quick Attacks +// - Phases 2 & 3 Insta-Kill +// - Shadow Orb at Phase 2 & 3 +// 4, WTF!?!?! Why God... Why.... +// - The Army Comith... +// - Attacks Are So Rapid.... +// - All Phases Insta-Kill, Phase 3 does the spawn camp thingy :D +// - Shadow Orb at all Phases +// - Shadow Orb regenerates Vardison's HP + +$TWM2::VardisonDifficulty = 1; +$TWM2::Vardison_DMsg[1] = "Lord Vardison Fight [EASY]: The Standard Battle... Work Togther and Be Victorious."; +$TWM2::Vardison_DMsg[2] = "Lord Vardison Fight [NORMAL]: Vardison Has Enhanced His Skills, Will you prove stronger?"; +$TWM2::Vardison_DMsg[3] = "Lord Vardison Fight [HARD]: The True Vardison Experience... Only The True Will Be Victorious..."; +$TWM2::Vardison_DMsg[4] = "Lord Vardison Fight [WTF]: All Prayers Will Be Accepted Before You Painfully Die... Over And Over And Over...."; +//Difficulty Variables, Don't Touch +$TWM2::Vardison_OrbKillTime = 12500; +$TWM2::Vardison1_AttSpeed[1] = 20000; +$TWM2::Vardison1_AttSpeed[2] = 17500; +$TWM2::Vardison1_AttSpeed[3] = 13500; +$TWM2::Vardison1_AttSpeed[4] = 7500; +$TWM2::Vardison2_AttSpeed[1] = 20000; +$TWM2::Vardison2_AttSpeed[2] = 17500; +$TWM2::Vardison2_AttSpeed[3] = 12500; +$TWM2::Vardison2_AttSpeed[4] = 7000; +$TWM2::Vardison3_AttSpeed[1] = 17500; +$TWM2::Vardison3_AttSpeed[2] = 15000; +$TWM2::Vardison3_AttSpeed[3] = 11500; +$TWM2::Vardison3_AttSpeed[4] = 6500; +$TWM2::Vardison1_CanOrb[1] = false; +$TWM2::Vardison1_CanOrb[2] = false; +$TWM2::Vardison1_CanOrb[3] = false; +$TWM2::Vardison1_CanOrb[4] = true; +$TWM2::Vardison2_CanOrb[1] = false; +$TWM2::Vardison2_CanOrb[2] = false; +$TWM2::Vardison2_CanOrb[3] = true; +$TWM2::Vardison2_CanOrb[4] = true; +$TWM2::Vardison3_CanOrb[1] = false; +$TWM2::Vardison3_CanOrb[2] = true; +$TWM2::Vardison3_CanOrb[3] = true; +$TWM2::Vardison3_CanOrb[4] = true; +$TWM2::Vardison_OrbRegenHP[1] = false; +$TWM2::Vardison_OrbRegenHP[2] = false; +$TWM2::Vardison_OrbRegenHP[3] = false; +$TWM2::Vardison_OrbRegenHP[4] = true; +$TWM2::Vardison1_MaxMinions[1] = 5; +$TWM2::Vardison1_MaxMinions[2] = 10; +$TWM2::Vardison1_MaxMinions[3] = 12; +$TWM2::Vardison1_MaxMinions[4] = 15; +$TWM2::Vardison2_MaxMinions[1] = 7; +$TWM2::Vardison2_MaxMinions[2] = 9; +$TWM2::Vardison2_MaxMinions[3] = 12; +$TWM2::Vardison2_MaxMinions[4] = 15; +$TWM2::Vardison3_MaxMinions[1] = 10; +$TWM2::Vardison3_MaxMinions[2] = 13; +$TWM2::Vardison3_MaxMinions[3] = 17; +$TWM2::Vardison3_MaxMinions[4] = 25; +$TWM2::Vardison_MinionCooldown[1] = 20; +$TWM2::Vardison_MinionCooldown[2] = 17; +$TWM2::Vardison_MinionCooldown[3] = 15; +$TWM2::Vardison_MinionCooldown[4] = 10; + +//Particles & Emitters +datablock ParticleData(SummoningPierParticle) { + dragCoeffiecient = 0.0; + gravityCoefficient = -0.1; + inheritedVelFactor = 0.1; + + lifetimeMS = 1500; + lifetimeVarianceMS = 50; + + textureName = "special/cloudflash"; + + spinRandomMin = -10.0; + spinRandomMax = 10.0; + + colors[0] = "1 0.18 0.03 0.4"; + colors[1] = "0 134 139 0.3"; + colors[2] = "1 0.18 0.03 0.0"; + sizes[0] = 10.0; + sizes[1] = 7.5; + sizes[2] = 5.0; + times[0] = 0.0; + times[1] = 0.6; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(SummoningPierEmitter) { + ejectionPeriodMS = 3; + periodVarianceMS = 0; + + ejectionOffset = 0.2; + ejectionVelocity = 10.0; + velocityVariance = 0.0; + + thetaMin = 0.0; + thetaMax = 10.0; + + particles = "SummoningPierParticle"; +}; + +datablock ParticleData(ShadowOrbParticle) { + dragCoefficient = 5; + gravityCoefficient = 0.0; + inheritedVelFactor = 0.0; + constantAcceleration = -1.3; + lifetimeMS = 1000; + lifetimeVarianceMS = 150; + textureName = "special/cloudflash"; + useInvAlpha = false; + colors[0] = "0.5 0.1 0.9 1.0"; + colors[1] = "0.5 0.1 0.9 1.0"; + colors[2] = "0.5 0.1 0.9 1.0"; + sizes[0] = 20.501; + sizes[1] = 25.001; + sizes[2] = 30.001; + times[0] = 0.0; + times[1] = 0.2; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(ShadowOrbEmitter) { + ejectionPeriodMS = 15; + periodVarianceMS = 5; + + ejectionVelocity = 42.7; // A little oomph at the back end + velocityVariance = 0.0; + ejectionoffset = 0; + thetaMin = 0.0; + thetaMax = 180.0; + phiReferenceVel = 0; + phiVariance = "360"; + particles = "ShadowOrbParticle"; + overrideAdvances = true; + orientParticles = true; +}; + +datablock ParticleData(ShadowOrbDetonationParticle) { + dragCoefficient = 1.0; + gravityCoefficient = 0.00; + windcoefficient = 0.0; + inheritedVelFactor = 0.0; + constantAcceleration = 10.0; + lifetimeMS = 1000; + lifetimeVarianceMS = 100; + useInvAlpha = true; + spinRandomMin = -90.0; + spinRandomMax = 90.0; + textureName = "special/cloudFlash"; + + colors[0] = "0.5 0.1 0.9 1.0"; + colors[1] = "156 0 0 0.5"; + colors[2] = "0.5 0.1 0.9 1.0"; + sizes[0] = 500; + sizes[1] = 500; + sizes[2] = 2; + times[0] = 0.0; + times[1] = 0.5; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(ShadowOrbDetonationEmitter) { + ejectionPeriodMS = 1; + periodVarianceMS = 0; + ejectionVelocity = 400.0; + velocityVariance = 150.0; + ejectionOffset = 0.0; + thetaMin = 85; + thetaMax = 85; + phiReferenceVel = 0; + phiVariance = 360; + overrideAdvances = false; + particles = "ShadowOrbDetonationParticle"; +}; + +datablock ParticleData(ShadowBaseParticle) { + dragCoeffiecient = 0.0; + gravityCoefficient = -0.2; + inheritedVelFactor = 0.0; + + lifetimeMS = 800; + lifetimeVarianceMS = 500; + + useInvAlpha = false; + spinRandomMin = -160.0; + spinRandomMax = 160.0; + + animateTexture = true; + framesPerSec = 15; + + textureName = "special/cloudflash"; + + colors[0] = "0.5 0.1 0.9 1.0"; + colors[1] = "0.5 0.1 0.9 1.0"; + colors[2] = "0.5 0.1 0.9 1.0"; + + sizes[0] = 2.5; + sizes[1] = 2.7; + sizes[2] = 3.0; + + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(ShadowBaseEmitter) { + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 1.5; + velocityVariance = 0.3; + + thetaMin = 0.0; + thetaMax = 30.0; + + particles = "ShadowBaseParticle"; +}; + +//Projectile Datablocks: +//Ultimate Laser Projectile datablock LinearFlareProjectileData(SuperlaserProjectile) { scale = "15.0 15.0 15.0"; faceViewer = false; @@ -51,1621 +283,1440 @@ datablock LinearFlareProjectileData(SuperlaserProjectile) { }; -// -datablock ParticleData(ShadowBaseParticle) { - dragCoeffiecient = 0.0; - gravityCoefficient = -0.2; - inheritedVelFactor = 0.0; +datablock LinearFlareProjectileData(ShadowBladeSlam) { + scale = "0.1 0.1 0.1"; + faceViewer = false; + directDamage = 1.0; + hasDamageRadius = true; + indirectDamage = 5.0; + damageRadius = 15.0; + kickBackStrength = 1000.0; + radiusDamageType = $DamageType::BladeOfVengance; - lifetimeMS = 800; - lifetimeVarianceMS = 500; + explosion[0] = "SatchelMainExplosion"; + splash = PlasmaSplash; - useInvAlpha = true; - spinRandomMin = -160.0; - spinRandomMax = 160.0; - animateTexture = true; - framesPerSec = 15; + dryVelocity = 200.0; + wetVelocity = 200; + velInheritFactor = 0.5; + fizzleTimeMS = 10000; + lifetimeMS = 10000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; - textureName = "special/cloudflash"; + //activateDelayMS = 100; + activateDelayMS = -1; - colors[0] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[1] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[2] = "0.1 0.1 0.1 1.0";// \\\\\\\\\\\\\\\\\\\\ + size[0] = "0.1"; + size[1] = "0.1"; + size[2] = "0.1"; - sizes[0] = 2.5; - sizes[1] = 2.7; - sizes[2] = 3.0; - times[0] = 0.0; - times[1] = 0.7; - times[2] = 1.0; + numFlares = 1; + flareColor = "0.0 1.0 0"; + flareModTexture = "flaremod"; + flareBaseTexture = "flarebase"; + + sound = MissileProjectileSound; + fireSound = PlasmaFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 3.0; + lightColor = "0 0.75 0.25"; + }; -datablock ParticleEmitterData(ShadowBaseEmitter) { - ejectionPeriodMS = 10; - periodVarianceMS = 0; +datablock LinearFlareProjectileData(ShadowBlastBolt) { + projectileShapeName = "turret_muzzlepoint.dts"; + scale = "1.0 1.0 1.0"; + faceViewer = true; + directDamage = 0.9; + hasDamageRadius = true; + indirectDamage = 0.9; + damageRadius = 15.0; + kickBackStrength = 0.0; + radiusDamageType = $DamageType::Vardison; - ejectionVelocity = 1.5; - velocityVariance = 0.3; + explosion = "MortarExplosion"; + splash = PlasmaSplash; - thetaMin = 0.0; - thetaMax = 30.0; - - particles = "ShadowBaseParticle"; -}; - -datablock ParticleData(SmallShadowBaseParticle) { - dragCoeffiecient = 0.0; - gravityCoefficient = -0.2; - inheritedVelFactor = 0.0; - - lifetimeMS = 9999999999999; - lifetimeVarianceMS = 9999999999999; - - useInvAlpha = true; - spinRandomMin = -160.0; - spinRandomMax = 160.0; - - animateTexture = true; - framesPerSec = 15; - - textureName = "special/cloudflash"; - - colors[0] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[1] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[2] = "0.1 0.1 0.1 1.0";// \\\\\\\\\\\\\\\\\\\\ - - sizes[0] = 0.5; - sizes[1] = 0.7; - sizes[2] = 1.0; - - times[0] = 0.0; - times[1] = 0.7; - times[2] = 1.0; -}; - -datablock ParticleEmitterData(SmallShadowBaseEmitter) { - ejectionPeriodMS = 10; - periodVarianceMS = 0; - - ejectionVelocity = 1.5; - velocityVariance = 0.3; - - thetaMin = 0.0; - thetaMax = 30.0; - - particles = "SmallShadowBaseParticle"; -}; - -datablock ParticleData(JetShadowParticle) { - dragCoeffiecient = 0.0; - gravityCoefficient = 0; - inheritedVelFactor = 0.0; - - lifetimeMS = 2500; - lifetimeVarianceMS = 0; - - textureName = "particleTest"; - - useInvAlpha = true; - spinRandomMin = -160.0; - spinRandomMax = 160.0; - - animateTexture = true; - framesPerSec = 15; - - animTexName[0] = "special/Explosion/exp_0016"; - animTexName[1] = "special/Explosion/exp_0018"; - animTexName[2] = "special/Explosion/exp_0020"; - animTexName[3] = "special/Explosion/exp_0022"; - animTexName[4] = "special/Explosion/exp_0024"; - animTexName[5] = "special/Explosion/exp_0026"; - animTexName[6] = "special/Explosion/exp_0028"; - animTexName[7] = "special/Explosion/exp_0030"; - animTexName[8] = "special/Explosion/exp_0032"; - - colors[0] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[1] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[2] = "0.1 0.1 0.1 1.0";// \\\\\\\\\\\\\\\\\\\\ - sizes[0] = 2.5; - sizes[1] = 1.25; - sizes[2] = 0.625; - times[0] = 0.0; - times[1] = 0.7; - times[2] = 1.0; -}; - -datablock ParticleEmitterData(JetShadowEmitter) { - ejectionPeriodMS = 2; - periodVarianceMS = 0; - - ejectionVelocity = 0; - velocityVariance = 0; - ejectionOffset = 5; - thetaMin = 22.5; - thetaMax = 45; - phiReferenceVel = 0; - phiVariance = 360; - spinRandomMin = "200"; - spinRandomMax = "-200"; - overrideAdvances = false; - particles = "JetShadowParticle"; -}; - -datablock ParticleData(LaserBallGlobeSmoke) { - dragCoefficient = 50;/////////----------------------- - gravityCoefficient = 0.0; - inheritedVelFactor = 1.0; - constantAcceleration = 0.0; - lifetimeMS = 1000; - lifetimeVarianceMS = 0; - useInvAlpha = true; - spinRandomMin = -360.0; - spinRandomMax = 360.0; - textureName = "particleTest"; - colors[0] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[1] = "0.1 0.1 0.1 1.0";// //////////////////// - colors[2] = "0.1 0.1 0.1 1.0";// \\\\\\\\\\\\\\\\\\\\ - colors[3] = "0.1 0.1 0.1 1.0";// \\\\\\\\\\\\\\\\\\\\ - sizes[0] = 1.0; - sizes[1] = 1.0; - sizes[2] = 1.0; - sizes[3] = 1.0; - times[0] = 0.0; - times[1] = 0.33; - times[2] = 0.66; - times[3] = 1.0; - mass = 0.7; - elasticity = 0.2; - friction = 1; - computeCRC = true; - haslight = true; - lightType = "PulsingLight"; - lightColor = "0.2 0.0 0.5 1.0"; - lightTime = "200"; - lightRadius = "2.0"; -}; - -datablock ParticleEmitterData(MiniShadowBallEmitter) { - ejectionPeriodMS = 0.3; - periodVarianceMS = 0; - ejectionVelocity = 0.0; - velocityVariance = 0.0; - ejectionOffset = 2; - thetaMin = 0; - thetaMax = 180; - overrideAdvances = false; - particles = "LaserBallGlobeSmoke"; -}; - -datablock LinearFlareProjectileData(ShadowBomb) : FlamethrowerBolt { baseEmitter = ShadowBaseEmitter; - fizzleTimeMS = 14000; - lifetimeMS = 10000; // z0dd - ZOD, 4/25/02. Was 6000 -}; -datablock SeekerProjectileData(VardisonLaserBallMissile) : YvexNightmareMissile { - baseEmitter = ShadowBaseEmitter; -}; - -function VardisonLaserBallMissile::OnExplode(%data, %proj, %pos, %mod) { - //LaserBall - %ball = CreateEmitter(%pos, "MiniShadowBallEmitter", "0 0 0 0"); - %ball.schedule(10000, "Delete"); - LaserBallStrike(vectorAdd(%pos, "0 0 3"), 0); -} - -function LaserBallStrike(%position, %count) { - %count++; - if(%count > 100) { - %p = new LinearFlareProjectile() { - dataBlock = VardisonSubShadowBomb; - initialDirection = "0 0 -1"; - initialPosition = %position; - }; - return; //stop here - } - else { - if(%count % 3 == 0) { //multiples of 3 == strike - %p = new TracerProjectile() { - dataBlock = PlasmaCannonMainProj; - initialDirection = vectorAdd(%postition, getRandomPosition(25,0)); - initialPosition = %position; - }; - } - } - schedule(100, 0, "LaserBallStrike", %position, %count); -} - -datablock LinearFlareProjectileData(VardisonSubShadowBomb) : DMPlasma { - explosion = MortarExplosion; - dryVelocity = 500.0; // z0dd - ZOD, 4/25/02. Was 50. Velocity of projectile out of water + dryVelocity = 50.0; // z0dd - ZOD, 7/20/02. Faster plasma projectile. was 55 wetVelocity = -1; - velInheritFactor = 1.0; - fizzleTimeMS = 14000; - lifetimeMS = 10000; // z0dd - ZOD, 4/25/02. Was 6000 + velInheritFactor = 0.3; + fizzleTimeMS = 29500; + lifetimeMS = 30000; + explodeOnDeath = false; + reflectOnWaterImpactAngle = 0.0; + explodeOnWaterImpact = true; + deflectionOnWaterImpact = 0.0; + fizzleUnderwaterMS = -1; + + //activateDelayMS = 100; + activateDelayMS = -1; + + size[0] = 0.2; + size[1] = 0.5; + size[2] = 0.1; + + + numFlares = 35; + flareColor = "1 0.18 0.03"; + flareModTexture = "flaremod"; + flareBaseTexture = "flarebase"; + + sound = PlasmaProjectileSound; + fireSound = FlamethrowerFireSound; + wetFireSound = PlasmaFireWetSound; + + hasLight = true; + lightRadius = 10.0; + lightColor = "0.94 0.03 0.12"; }; -//ARMOR DBs -datablock PlayerData(VardisonStage1Armor) : LightMaleHumanArmor { - runForce = 60.20 * 90; - runEnergyDrain = 0.0; - minRunEnergy = 10; - maxForwardSpeed = 9; - maxBackwardSpeed = 7; - maxSideSpeed = 7; - - jumpForce = 14.0 * 90; +//Armor Datablocks +datablock StaticShapeData(InitialVaridionHoloArmor) : StaticShapeDamageProfile { + className = "player"; + shapeFile = "TR2Heavy_male.dts"; // dmiscf.dts, alternate + mass = 1; + elasticity = 0.1; + friction = 0.9; + collideable = 0; + isInvincible = true; +}; +function InitialVaridionHoloArmor::shouldApplyImpulse(%targetObject) { + return false; +} +datablock PlayerData(VardisonStageOneArmor) : LightMaleHumanArmor { + boundingBox = "1.63 1.63 2.6"; maxDamage = 300.0; minImpactSpeed = 35; - shapeFile = "light_male.dts"; - jetEmitter = BiodermArmorJetEmitter; - jetEffect = BiodermArmorJetEffect; + shapeFile = "medium_male.dts"; debrisShapeName = "bio_player_debris.dts"; //Foot Prints - decalData = LightBiodermFootprint; - decalOffset = 0.3; + decalData = HeavyBiodermFootprint; + decalOffset = 0.4; waterBreathSound = WaterBreathBiodermSound; - damageScale[$DamageType::M1700] = 3.0; - damageScale[$DamageType::Missile] = 0.0000000000000001; - damageScale[$DamageType::Nuclear] = 0.0000000000000001; - damageScale[$DamageType::EMP] = 0.0000000000000001; + damageScale[$DamageType::W1700] = 3.0; damageScale[$DamageType::Bullet] = 0.10; //I deny you shrike n0bs + damageScale[$DamageType::BladeOfVengance] = 0.001; +}; + +datablock PlayerData(VardisonStageTwoArmor) : LightMaleHumanArmor { + shapefile = "TR2medium_male.dts"; + mass = 500; + maxDamage = 350.0; + minImpactSpeed = 50; + speedDamageScale = 0.015; + boundingBox = "2.9 2.9 4.8"; + + underwaterJetForce = 10; + + LFootSoftSound = ZLordFootSound; + RFootSoftSound = ZLordFootSound; + LFootHardSound = HZLordFootSound; + RFootHardSound = HZLordFootSound; + LFootMetalSound = ZLordFootSound; + RFootMetalSound = ZLordFootSound; + LFootSnowSound = ZLordFootSound; + RFootSnowSound = ZLordFootSound; + + damageScale[$DamageType::M1700] = 1.5; + damageScale[$DamageType::BladeOfVengance] = 0.001; max[RepairKit] = 0; max[Mine] = 0; max[Grenade] = 0; }; -datablock PlayerData(DarkArchmageVardisonArmor) : VardisonStage1Armor { - maxDamage = 1000.0; - minImpactSpeed = 35; - shapeFile = "light_male.dts"; - jetEmitter = BiodermArmorJetEmitter; - jetEffect = BiodermArmorJetEffect; - - damageScale[$DamageType::M1700] = 3.0; - damageScale[$DamageType::Missile] = 0.0000000000000001; - damageScale[$DamageType::Nuclear] = 0.0000000000000001; - damageScale[$DamageType::EMP] = 0.0000000000000001; - damageScale[$DamageType::Bullet] = 0.10; //I deny you shrike n0bs - - max[RepairKit] = 0; - max[Mine] = 0; - max[Grenade] = 0; -}; - -datablock FlyingVehicleData(VardisonStage2Flyer) : ShrikeDamageProfile { - spawnOffset = "0 0 2"; - canControl = false; - catagory = "Vehicles"; - shapeFile = "vehicle_air_bomber.dts"; - multipassenger = false; - computeCRC = true; - - debrisShapeName = "vehicle_air_bomber.dts"; - debris = MeShapeDebris; - renderWhenDestroyed = false; - - drag = 0.15; - density = 1.0; - - mountPose[0] = sitting; - numMountPoints = 1; - isProtectedMountPoint[0] = false; - cameraMaxDist = 15; - cameraOffset = 2.5; - cameraLag = 0.9; - explosion = MeVehicleExplosion; - explosionDamage = 1.0; - explosionRadius = 10.0; - - maxDamage = 50.0; - destroyedLevel = 50.0; - - HDAddMassLevel = 49.9; - HDMassImage = LflyerHDMassImage; - - isShielded = false; - energyPerDamagePoint = 0; - maxEnergy = 5000; // Afterburner and any energy weapon pool - rechargeRate = 4; - - minDrag = 22; // Linear Drag (eventually slows you down when not thrusting...constant drag) - rotationalDrag = 900; // Anguler Drag (dampens the drift after you stop moving the mouse...also tumble drag) - - maxAutoSpeed = 50; // Autostabilizer kicks in when less than this speed. (meters/second) - autoAngularForce = 400; // Angular stabilizer force (this force levels you out when autostabilizer kicks in) - autoLinearForce = 1; // Linear stabilzer force (this slows you down when autostabilizer kicks in) - autoInputDamping = 0.8; // Dampen control input so you don't` whack out at very slow speeds - - - // Maneuvering - maxSteeringAngle = 4.5; // Max radiens you can rotate the wheel. Smaller number is more maneuverable. - horizontalSurfaceForce = 6; // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning) - verticalSurfaceForce = 4; // Vertical center "wing" (controls side slip. lower numbers make MORE slide.) - maneuveringForce = 5250; // Horizontal jets (W,S,D,A key thrust) - steeringForce = 675; // Steering jets (force applied when you move the mouse) - steeringRollForce = 3000; // Steering jets (how much you heel over when you turn) - rollForce = 1; // Auto-roll (self-correction to right you after you roll/invert) - hoverHeight = 2.5; // Height off the ground at rest - createHoverHeight = 1; // Height off the ground when created - maxForwardSpeed = 165; // speed in which forward thrust force is no longer applied (meters/second) - - // Turbo Jet - jetForce = 2500; // Afterburner thrust (this is in addition to normal thrust) - minJetEnergy = 40; // Afterburner can't be used if below this threshhold. - jetEnergyDrain = 10; // Energy use of the afterburners (low number is less drain...can be fractional) // Auto stabilize speed - vertThrustMultiple = 1.25; - - // Rigid body - mass = 150; // Mass of the vehicle - bodyFriction = 0; // Don't mess with this. - bodyRestitution = 0.5; // When you hit the ground, how much you rebound. (between 0 and 1) - minRollSpeed = 0; // Don't mess with this. - softImpactSpeed = 14; // Sound hooks. This is the soft hit. - hardImpactSpeed = 25; // Sound hooks. This is the hard hit. - - // Ground Impact Damage (uses DamageType::Ground) - minImpactSpeed = 20; // If hit ground at speed above this then it's an impact. Meters/second - speedDamageScale = 0.06; - - // Object Impact Damage (uses DamageType::Impact) - collDamageThresholdVel = 23.0; - collDamageMultiplier = 0.02; - - // - minTrailSpeed = 70; // The speed your contrail shows up at. - trailEmitter = JetShadowEmitter; - forwardJetEmitter = JetShadowEmitter; - downJetEmitter = JetShadowEmitter; - - // - jetSound = ScoutFlyerThrustSound; - engineSound = ScoutFlyerEngineSound; - softImpactSound = SoftImpactSound; - hardImpactSound = HardImpactSound; - //wheelImpactSound = WheelImpactSound; - - // - softSplashSoundVelocity = 10.0; - mediumSplashSoundVelocity = 15.0; - hardSplashSoundVelocity = 20.0; - exitSplashSoundVelocity = 10.0; - - exitingWater = VehicleExitWaterMediumSound; - impactWaterEasy = VehicleImpactWaterSoftSound; - impactWaterMedium = VehicleImpactWaterMediumSound; - impactWaterHard = VehicleImpactWaterMediumSound; - waterWakeSound = VehicleWakeMediumSplashSound; - - dustEmitter = VehicleLiftoffDustEmitter; - triggerDustHeight = 4.0; - dustHeight = 1.0; - - damageEmitter[0] = MeLightDamageSmoke; - damageEmitter[1] = MeHeavyDamageSmoke; - damageEmitter[2] = MeDamageBubbles; - damageEmitterOffset[0] = "0.0 -3.0 0.0 "; - damageLevelTolerance[0] = 0.4; - damageLevelTolerance[1] = 0.75; - numDmgEmitterAreas = 1; - - // - max[chaingunAmmo] = 2000; - max[MissileLauncherAmmo] = 200; - max[MortarAmmo] = 200; - - damageScale[$DamageType::Nuclear] = 0.0000000000000001; - damageScale[$DamageType::EMP] = 0.0000000000000001; - damageScale[$DamageType::Bullet] = 0.10; //I deny you shrike n0bs - ShieldDamageScale[$DamageType::Bullet] = 0.01; //I deny you shrike n0bs - - minMountDist = 7; - - splashEmitter[0] = VehicleFoamDropletsEmitter; - splashEmitter[1] = VehicleFoamEmitter; - - shieldImpact = VehicleShieldImpact; - - cmdCategory = "Tactical"; - cmdIcon = CMDFlyingScoutIcon; - cmdMiniIconName = "commander/MiniIcons/com_scout_grey"; - targetNameTag = 'Lord Vardison'; - targetTypeTag = ''; - sensorData = SSTurretBaseSensorObj; - sensorRadius = SSTurretBaseSensorObj.detectRadius; - sensorColor = "9 9 255"; - - checkRadius = 5.5; - observeParameters = "1 10 10"; - - runningLight[0] = ShrikeLight1; -// runningLight[1] = ShrikeLight2; - - shieldEffectScale = "0.937 1.125 0.60"; - - numWeapons = 3; - - replaceTime = 90; -}; - -datablock PlayerData(VardisonStage3Armor) : LightMaleHumanArmor { - runForce = 60.20 * 90; - runEnergyDrain = 0.0; - minRunEnergy = 10; - maxForwardSpeed = 9; - maxBackwardSpeed = 7; - maxSideSpeed = 7; - - jumpForce = 14.0 * 90; - +datablock PlayerData(VardisonStageThreeArmor) : LightMaleHumanArmor { + shapefile = "TR2Heavy_male.dts"; + mass = 500; maxDamage = 500.0; - minImpactSpeed = 35; - shapeFile = "TR2Heavy_Male.dts"; - jetEmitter = BiodermArmorJetEmitter; - jetEffect = BiodermArmorJetEffect; + minImpactSpeed = 50; + speedDamageScale = 0.015; + boundingBox = "2.9 2.9 4.8"; - debrisShapeName = "bio_player_debris.dts"; + underwaterJetForce = 10; - //Foot Prints - decalData = LightBiodermFootprint; - decalOffset = 0.3; - - boundingBox = "5 5 10"; + LFootSoftSound = ZLordFootSound; + RFootSoftSound = ZLordFootSound; + LFootHardSound = HZLordFootSound; + RFootHardSound = HZLordFootSound; + LFootMetalSound = ZLordFootSound; + RFootMetalSound = ZLordFootSound; + LFootSnowSound = ZLordFootSound; + RFootSnowSound = ZLordFootSound; - waterBreathSound = WaterBreathBiodermSound; - - damageScale[$DamageType::M1700] = 3.0; - damageScale[$DamageType::PlasmaCannon] = 0.001; - damageScale[$DamageType::Missile] = 0.0000000000000001; - damageScale[$DamageType::Nuclear] = 0.0000000000000001; - damageScale[$DamageType::EMP] = 0.0000000000000001; - damageScale[$DamageType::Bullet] = 0.10; //I deny you shrike n0bs + damageScale[$DamageType::M1700] = 1.5; + damageScale[$DamageType::BladeOfVengance] = 0.001; max[RepairKit] = 0; max[Mine] = 0; max[Grenade] = 0; }; -function StartDAVardison(%pos) { - %Vardison = new player() { - Datablock = "DarkArchmageVardisonArmor"; - }; - %Cpos = vectorAdd(%pos, "0 0 5"); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["DAVardison"]@": Rise forces of darkness, as our enemies shall face their demise"); +datablock StaticShapeData(ShadowOrb) : StaticShapeDamageProfile { + className = "logoprojector"; + shapeFile = "pack_deploy_sensor_motion.dts"; - %command = "DAVardisonmovetotarget"; - %Vardison.ticks = 0; - InitiateBoss(%Vardison, "DAVardison"); + maxDamage = 10.0; + destroyedLevel = 10.0; + disabledLevel = 0.3; - %Vardison.team = 30; - %zname = CollapseEscape("\c7"@$TWM2::BossName["DAVardison"]@""); // <- To Hosts, Enjoy, You can - //Change the Demon Names now!!! - %Vardison.target = createTarget(%Vardison, %zname, "", "Derm3", '', %Vardison.team, PlayerSensor); - setTargetSensorData(%Vardison.target, PlayerSensor); - setTargetSensorGroup(%Vardison.target, 30); - setTargetName(%Vardison.target, addtaggedstring(%zname)); - setTargetSkin(%Vardison.target, 'Inferno'); - // - %Vardison.setPosition(%cpos); - %Vardison.canjump = 1; - %Vardison.hastarget = 1; - MissionCleanup.add(%Vardison); - schedule(1000, %Vardison, %command, %Vardison); + isShielded = false; + energyPerDamagePoint = 240; + maxEnergy = 50; + rechargeRate = 0.25; - DAVardisonAttacks(%Vardison); -} + explosion = HandGrenadeExplosion; + expDmgRadius = 1.0; + expDamage = 0.05; + expImpulse = 200; + + boundingBox = "5.0 5.0 5.0"; + dynamicType = $TypeMasks::StaticShapeObjectType; + deployedObject = true; + cmdCategory = "DSupport"; + cmdIcon = CMDSensorIcon; + cmdMiniIconName = "commander/MiniIcons/com_deploymotionsensor"; + targetNameTag = 'Shadow Rift'; + deployAmbientThread = true; + debrisShapeName = "debris_generic_small.dts"; + debris = DeployableDebris; + heatSignature = 0; + needsPower = true; +}; -function StartVardison1(%pos) { - - %Vardison = new player(){ - Datablock = "VardisonStage1Armor"; - }; - %Cpos = vectorAdd(%pos, "0 0 5"); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": "@$TWM2::BossName["Vardison"]@", Checking into duty, and about to slaughter some fuckin' enemies!!!"); - - %command = "Vardison1movetotarget"; - %Vardison.ticks = 0; - InitiateBoss(%Vardison, "Vardison1"); - - %Vardison.team = 30; - %zname = CollapseEscape("\c7"@$TWM2::BossName["Vardison"]@""); // <- To Hosts, Enjoy, You can - //Change the Demon Names now!!! - %Vardison.target = createTarget(%Vardison, %zname, "", "Derm3", '', %Vardison.team, PlayerSensor); - setTargetSensorData(%Vardison.target, PlayerSensor); - setTargetSensorGroup(%Vardison.target, 30); - setTargetName(%Vardison.target, addtaggedstring(%zname)); - setTargetSkin(%Vardison.target, 'Inferno'); - // - %Vardison.setPosition(%cpos); - %Vardison.canjump = 1; - %Vardison.hastarget = 1; - MissionCleanup.add(%Vardison); - schedule(1000, %Vardison, %command, %Vardison); - - VardisonAttacks(%Vardison); -} - -function StartVardison2(%pos) { - %StartPos = VectorAdd(%pos, "0 0 100"); - %team = 30; - %rotation = "1 0 0 0"; - %skill = 10; - - %Drone = new FlyingVehicle() { - dataBlock = VardisonStage2Flyer; - position = %StartPos; - rotation = %rotation; - team = %team; - }; - MissionCleanUp.add(%Drone); - - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": HA! I'm nowhere near finished with you, Lets take this to the skies.. shall we."); - - setTargetSensorGroup(%Drone.getTarget(), %team); - - %Drone.isdrone = 1; - %drone.dodgeGround = 0; - - %drone.isace = 1; - - %drone.skill = 0.2 + (%skill / 12.5); - - schedule(100, 0, "DroneForwardImpulse", %drone); //special impulse - schedule(101, 0, "DronefindTarget", %drone); - schedule(102, 0, "DroneScanGround", %drone); - - InitiateBoss(%drone, "Vardison2"); - VardisonDroneAttacks(%drone); -} - -function StartVardison3(%pos) { - %Vardison = new player(){ - Datablock = "VardisonStage3Armor"; - }; - %Cpos = vectorAdd(%pos, "0 0 5"); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": Now you will see the full power of a shadow demon!!!"); - - %command = "Vardison3movetotarget"; - %Vardison.ticks = 0; - InitiateBoss(%Vardison, "Vardison3"); - - %Vardison.team = 30; - %zname = CollapseEscape("\c7"@$TWM2::BossName["Vardison"]@""); // <- To Hosts, Enjoy, You can - //Change the Demon Names now!!! - %Vardison.target = createTarget(%Vardison, %zname, "", "Derm3", '', %Vardison.team, PlayerSensor); - setTargetSensorData(%Vardison.target, PlayerSensor); - setTargetSensorGroup(%Vardison.target, 30); - setTargetName(%Vardison.target, addtaggedstring(%zname)); - setTargetSkin(%Vardison.target, 'Inferno'); - // - %Vardison.setTransform(%cpos); - %Vardison.canjump = 1; - %Vardison.hastarget = 1; - MissionCleanup.add(%Vardison); - schedule(1000, %Vardison, %command, %Vardison); - - VardisonDemonAttacks(%Vardison); - - //SpawnVardHelper(%Vardison, vectorAdd(%Vardison.getPosition(), "15 0 100")); - -} - -function DAVardisonmovetotarget(%Demon){ - if(!isobject(%Demon)) - return; - if(%Demon.getState() $= "dead") - return; - %pos = %Demon.getworldboxcenter(); - %closestClient = ZombieLookForTarget(%Demon); - %z = getWord(%pos, 2); - if(%z < -300) { - %Demon.startFade(400, 0, true); - %Demon.startFade(1000, 0, false); - %Demon.setPosition(vectorAdd(vectoradd(%closestclient.player.getPosition(), "0 0 20"), getRandomPosition(25, 1))); - %Demon.setVelocity("0 0 0"); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["DAVardison"]@": I'm back...."); - } - %closestDistance = getWord(%closestClient,1); - %closestClient = getWord(%closestClient,0).Player; - if(%closestDistance <= $Zombie::detectDist){ - if(%closestDistance < 15) { - if(!%closestClient.vardKilling) { - %closestClient.vardKilling = 1; - DoVardisonSuperCloseKill(%Demon, %closestClient, 0); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["DAVardison"]@": Die.... Human...."); - } - } - if(%Demon.hastarget != 1){ - //LZDoYell(%Demon); - %Demon.hastarget = 1; - } - - %vector = ZgetFacingDirection(%Demon,%closestClient,%pos); - - %vector = vectorscale(%vector, $Zombie::DForwardSpeed); - %upvec = "150"; - %x = Getword(%vector,0); - %y = Getword(%vector,1); - %z = Getword(%vector,2); - if(%z >= ($Zombie::DForwardSpeed)) - %upvec = (%upvec * 5); - %vector = %x@" "@%y@" "@%upvec; - %Demon.applyImpulse(%pos, %vector); - } - else if(%Demon.hastarget == 1){ - %Demon.hastarget = 0; - %Demon.DemonRmove = schedule(100, %Demon, "ZSetRandomMove", %Demon); - } - %Demon.moveloop = schedule(500, %Demon, "DAVardisonmovetotarget", %Demon); -} - -function Vardison1movetotarget(%Demon){ - if(!isobject(%Demon)) - return; - if(%Demon.getState() $= "dead") - return; - %pos = %Demon.getworldboxcenter(); - %closestClient = ZombieLookForTarget(%Demon); - %z = getWord(%pos, 2); - if(%z < -300) { - %Demon.startFade(400, 0, true); - %Demon.startFade(1000, 0, false); - %Demon.setPosition(vectorAdd(vectoradd(%closestclient.player.getPosition(), "0 0 20"), getRandomPosition(25, 1))); - %Demon.setVelocity("0 0 0"); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": I'm back...."); - } - %closestDistance = getWord(%closestClient,1); - %closestClient = getWord(%closestClient,0).Player; - if(%closestDistance <= $Zombie::detectDist){ - if(%closestDistance < 15) { - if(!%closestClient.vardKilling) { - %closestClient.vardKilling = 1; - DoVardisonSuperCloseKill(%Demon, %closestClient, 0); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": Die.... Human...."); - } - } - if(%Demon.hastarget != 1){ - //LZDoYell(%Demon); - %Demon.hastarget = 1; - } - - %vector = ZgetFacingDirection(%Demon,%closestClient,%pos); - - %vector = vectorscale(%vector, $Zombie::DForwardSpeed); - %upvec = "150"; - %x = Getword(%vector,0); - %y = Getword(%vector,1); - %z = Getword(%vector,2); - if(%z >= ($Zombie::DForwardSpeed)) - %upvec = (%upvec * 5); - %vector = %x@" "@%y@" "@%upvec; - %Demon.applyImpulse(%pos, %vector); - } - else if(%Demon.hastarget == 1){ - %Demon.hastarget = 0; - %Demon.DemonRmove = schedule(100, %Demon, "ZSetRandomMove", %Demon); - } - %Demon.moveloop = schedule(500, %Demon, "Vardison1movetotarget", %Demon); -} - -function Vardison3movetotarget(%Demon){ - if(!isobject(%Demon)) - return; - if(%Demon.getState() $= "dead") - return; - %pos = %Demon.getworldboxcenter(); - %closestClient = ZombieLookForTarget(%Demon); - %z = getWord(%pos, 2); - if(%z < -300) { - %Demon.startFade(400, 0, true); - %Demon.startFade(1000, 0, false); - %Demon.setPosition(vectorAdd(vectoradd(%closestclient.getPosition(), "0 0 20"), getRandomPosition(25, 1))); - %Demon.setVelocity("0 0 0"); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": I'm back...."); - } - %closestDistance = getWord(%closestClient,1); - %closestClient = getWord(%closestClient,0).Player; - if(%closestDistance <= $Zombie::detectDist){ - if(%closestDistance < 10) { - %closestClient.scriptKill(0); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": DIE!!!!!!"); - } - if(%Demon.hastarget != 1){ - %Demon.hastarget = 1; - } - - %vector = ZgetFacingDirection(%Demon,%closestClient,%pos); - - %vector = vectorscale(%vector, $Zombie::DForwardSpeed*1.8); - %upvec = "150"; - %x = Getword(%vector,0); - %y = Getword(%vector,1); - %z = Getword(%vector,2); - if(%z >= ($Zombie::DForwardSpeed)) - %upvec = (%upvec * 5); - %vector = %x@" "@%y@" "@%upvec; - %Demon.applyImpulse(%pos, %vector); - } - else if(%Demon.hastarget == 1){ - %Demon.hastarget = 0; - %Demon.DemonRmove = schedule(100, %Demon, "ZSetRandomMove", %Demon); - } - %Demon.moveloop = schedule(500, %Demon, "Vardison3movetotarget", %Demon); -} - -//ATTACKS - -function DoVardisonSuperCloseKill(%source, %target, %count) { - %count++; - if(!isObject(%source) || %source.getState() $= "dead") { - %target.setMoveState(false); +function ShadowOrb::onDestroyed(%this, %obj, %prevState) { + if (%obj.isRemoved) { return; } - %source.setMoveState(true); - %target.setMoveState(true); - %target.clearInventory(); //ha, no guns for You! - //lift - if(%count <= 15) { - %ZPos = %count * 0.025; - %newpos = vectoradd(%target.getPosition(),"0 0 "@%ZPos@""); - %target.setTransform(%newpos); - %target.setvelocity("0 0 0"); + %obj.isRemoved = true; + Parent::onDestroyed(%this, %obj, %prevState); + if(isObject(%orb.sfx)) { + %obj.sfx.schedule(500, "delete"); } - else if(%count == 16) { - //MessageAll('MsgDIE', "\c4"@%source.client.namebase@": You're so.... weak..."); - %newpos = vectoradd(%target.getPosition(),"0 0 "@%ZPos * -1@""); - %target.setTransform(%newpos); - %target.setvelocity("0 0 0"); - } - else if(%count == 17) { - %target.setvelocity("1000 1000 1000"); - %target.blowup();//BAM! - ServerPlay3d(BOVHitSound, %target.getPosition()); - ServerPlay3d(BOVHitSound, %target.getPosition()); - ServerPlay3d(BOVHitSound, %target.getPosition()); - %target.damage(%source, %target.getposition(), 9999, $DamageType::BladeOfVengance); - %source.setMoveState(false); - return; - } - schedule(100, 0, "DoVardisonSuperCloseKill", %source, %target, %count); + %obj.schedule(500, "delete"); + $TWM2::VardisonManager.orbDestroyed(); } -function ShadowBomb::onExplode(%data, %proj, %pos, %mod) { - %vec = %proj.spdvec; - %vec = getword(%vec, 0)@" "@getword(%vec, 1)@" 0"; - %vec = vectorNormalize(%vec); - %vec = vectorscale(%vec, 30); - %result = containerRayCast(vectoradd(%pos,"0 0 10"), vectoradd(%pos,%vec), $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::TerrainObjectType, %proj); - for(%i = 0; %i < 3; %i++) { - if(%result) - schedule((5 * %i), 0, "Napalm2FindNewDir", %pos, %vec, %proj.sourceobject, 0, 0); - else { - %rndvec = (getRandom(1, 15) - 7.5)@" "@(getRandom(1, 15) - 7.5)@" "@((getRandom() * 5) + 5); - %newvec = vectoradd(%vec,%rndvec); - %newvec = vectoradd(%pos,%newvec); - %p = new LinearFlareProjectile() { - dataBlock = VardisonSubShadowBomb; - initialDirection = "0 0 -1"; - initialPosition = %newvec; - sourceObject = %proj.sourceobject; - SourceSlot = 5; - }; - %p.sourceobject = %proj.sourceobject; - %p.vector = %vec; - %p.count = 1; - if(%proj.maxExplode $= "") { - %p.maxExplode = 15; +//Boss Functions +function CheckVardisonManager() { + if($TWM2::VardisonDifficulty < 1 || $TWM2::VardisonDifficulty > 4) { + //Are the odds in your favor now, or will Vardison rek you endlessly? + $TWM2::VardisonDifficulty = getRandom(1, 4); + } + if(!isObject($TWM2::VardisonManager)) { + $TWM2::VardisonManager = new ScriptObject() { + class = "VardisonManager"; + }; + } + //Setup default params + $TWM2::VardisonManager.lastAttackTime = getRealTime(); + $TWM2::VardisonManager.minionCount = 0; + $TWM2::VardisonManager.orbObject = -1; +} + +function StartVardison1(%position) { + CheckVardisonManager(); + //Trip the boss manager so nothing else fires up in the initial 10 seconds. + $TWM2::BossGoing = 1; + //Erupt a firestorm in his coming.... + // They shall know fear xD + MessageAll('msgAdminForce', "\c5"@$TWM2::Vardison_DMsg[$TWM2::VardisonDifficulty]); + //Adjust Position + %spawnPos = getWord(%position, 0) SPC getWord(%position, 1) SPC getTerrainHeight(%position); + //First Spawn The Firestorm & Sound FX + MessageAll('msgSound', "~wfx/environment/wind_sandstorm.wav"); + MessageAll('msgSound', "~wfx/environment/snowstorm1.wav"); + schedule(1500, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(2500, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(3500, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(5000, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(5500, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(7500, 0, MessageAll, 'msgSound', "~wfx/armor/breath_bio_uw.wav"); + schedule(10000, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + schedule(10000, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + schedule(10000, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + %fire = new ParticleEmissionDummy(){ + position = vectoradd(%spawnPos, "0 0 0.5"); + dataBlock = "defaultEmissionDummy"; + emitter = "SummoningPierEmitter"; + }; + MissionCleanup.add(%fire); + %fire.schedule(10000, "delete"); + //Spawn the fake hologram vardison. + %fakeHolo = new StaticShape(){ + Datablock = "InitialVaridionHoloArmor"; + }; + %fakeHolo.setTransform(vectorAdd(%spawnPos, "0 0 0.25")); + %fakeHolo.startfade(0, 0, true); + %fakeHolo.schedule(1000, startfade, 2500, 0, false); + %fakeHolo.schedule(7500, startfade, 2500, 0, true); + %fakeHolo.schedule(10000, "Delete"); + //And then start the real one... + schedule(10000, 0, SpawnVardison, %spawnPos); +} + +function SpawnVardison(%position) { + %Boss = new player(){ + Datablock = "VardisonStageOneArmor"; + }; + %Cpos = vectorAdd(%position, "0 0 5"); + InitiateBoss(%Boss, "Vardison1"); + + %Boss.team = 30; + %Boss.target = createTarget(%Boss, "\c7Lord Vardison", "", "Derm3", '', %Boss.team, PlayerSensor); + setTargetSensorData(%Boss.target, PlayerSensor); + setTargetSensorGroup(%Boss.target, 30); + setTargetName(%Boss.target, addtaggedstring("\c7Lord Vardison")); + setTargetSkin(%Boss.target, 'Horde'); + + %Boss.setTransform(%Cpos); + %Boss.phase = 1; + MissionCleanup.add(%Boss); + + %Boss.lastKillCount = $TWM2::BossManager.bossKills; + %Boss.canSummonMinions = true; + $TWM2::VardisonManager.Vardison = %Boss; + + %Boss.thinkSched = schedule(2500, 0, VardisonThink, %Boss); +} + +function SpawnVardison2(%position) { + schedule(250, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(500, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(750, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1000, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1100, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + + %Boss = new player(){ + Datablock = "VardisonStageTwoArmor"; + }; + %Cpos = vectorAdd(%position, "0 0 5"); + InitiateBoss(%Boss, "Vardison2"); + + %Boss.team = 30; + %Boss.target = createTarget(%Boss, "\c7Lord Vardison", "", "Derm3", '', %Boss.team, PlayerSensor); + setTargetSensorData(%Boss.target, PlayerSensor); + setTargetSensorGroup(%Boss.target, 30); + setTargetName(%Boss.target, addtaggedstring("\c7Lord Vardison")); + setTargetSkin(%Boss.target, 'Horde'); + + %Boss.setTransform(%Cpos); + %Boss.phase = 2; + MissionCleanup.add(%Boss); + + %Boss.lastKillCount = $TWM2::BossManager.bossKills; + %Boss.canSummonMinions = true; + $TWM2::VardisonManager.Vardison = %Boss; + + //If we're on difficulty level 4, summon an orb :P + if($TWM2::VardisonDifficulty >= 4) { + VardisonSummonOrb(%Boss); + } + + %Boss.thinkSched = schedule(1000, 0, VardisonThink, %Boss); +} + +function SpawnVardison3(%position) { + schedule(250, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(500, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(750, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1000, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1100, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1250, 0, MessageAll, 'msgSound', "~wfx/armor/breath_bio_uw.wav"); + schedule(1250, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + schedule(1250, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + schedule(1250, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + + %Boss = new player(){ + Datablock = "VardisonStageThreeArmor"; + }; + %Cpos = vectorAdd(%position, "0 0 5"); + InitiateBoss(%Boss, "Vardison3"); + + %Boss.team = 30; + %Boss.target = createTarget(%Boss, "\c7Lord Vardison", "", "Derm3", '', %Boss.team, PlayerSensor); + setTargetSensorData(%Boss.target, PlayerSensor); + setTargetSensorGroup(%Boss.target, 30); + setTargetName(%Boss.target, addtaggedstring("\c7Lord Vardison")); + setTargetSkin(%Boss.target, 'Horde'); + + %Boss.setTransform(%Cpos); + %Boss.phase = 3; + MissionCleanup.add(%Boss); + + %Boss.lastKillCount = $TWM2::BossManager.bossKills; + %Boss.canSummonMinions = true; + $TWM2::VardisonManager.Vardison = %Boss; + + //If we're on level 3 or 4, instantly summon the Shadow Orb to kick things off + if($TWM2::VardisonDifficulty >= 3) { + VardisonSummonOrb(%Boss); + } + + %Boss.thinkSched = schedule(1000, 0, VardisonThink, %Boss); +} + +function VardisonThink(%Boss) { + if(!isObject(%Boss) || %Boss.getState() $= "Dead") { + //Kill this think instance, let the next one take over. + return; + } + if(%Boss.busy) { + //I'm currently doing something, check back soon. + %Boss.thinkSched = schedule(200, 0, VardisonThink, %Boss); + return; + } + %dLevel = $TWM2::VardisonDifficulty; + %lastAtt = $TWM2::VardisonManager.lastAttackTime; //<--- Note: This value is from the time the last attack ENDED + %cTime = getRealTime(); + %lastKC = %Boss.lastKillCount; + %nowKC = $TWM2::BossManager.bossKills; + %Boss.lastKillCount = $TWM2::BossManager.bossKills; + //Possible Outcomes... + %needAttack = false; + %needMinions = false; + %needOrbSummon = false; + %needMove = false; + //Check for anti-fall.... + if(getWord(%Boss.getPosition(), 2) < (getTerrainHeight(%Boss.getPosition()) - 250)) { + if(getWord(%Boss.getVelocity(), 2) < -1) { + //Block the fall... bring us back up... + echo("VardisonThink(): Anti-Fall Countermeasures activated."); + %Boss.setPosition(getWord(%Boss.getPosition(), 0) SPC getWord(%Boss.getPosition(), 1) SPC getTerrainHeight(%Boss.getPosition()) + 15); + %Boss.setVelocity("0 0 1"); + %Boss.startfade(0, 0, true); + %Boss.schedule(250, startfade, 1000, 0, false); + } + } + //Determine the correct action. + switch(%Boss.phase) { + case 1: + //Did I just get a kill? + if(%nowKC > %lastKC) { + //Do I need to summon a shadow orb? + if($TWM2::Vardison1_CanOrb[%dLevel]) { + //Is there already an active orb? + if(!isObject($TWM2::VardisonManager.orbObject)) { + //Yep, I need to summon it. + %needOrbSummon = true; + } + } + } + if((%cTime - %lastAtt) >= $TWM2::Vardison1_AttSpeed[%dLevel]) { + //Time for an attack + %needAttack = true; } else { - %p.maxExplode = %proj.maxExplode; + //If we're not ready to dish out an attack, let's check what else we need to do... + // Are we low on minions? + if($TWM2::VardisonManager.minionCount < $TWM2::Vardison1_MaxMinions[%dLevel]) { + //How many players am I up against? + %pCount = $HostGamePlayerCount; + //How low is my health? + %percentage = mCeil((mFloor(%boss.getDamageLeft()*100) / mFloor(%boss.getMaxDamage()*100)) * 100); + %BackwardsHP = 100 - %percentage; + %chance = %BackwardsHP * %pCount * (%Boss.canSummonMinions ? 1 : 0); + //Using our test factor, determine if I need minions. + if(%chance <= getRandom(1, 100)) { + %needMinions = true; + } + } + //Do I need to be moving towards the enemy? + %needMove = true; //Phase 1 is always doing this... + } + case 2: + //Did I just get a kill? + if(%nowKC > %lastKC) { + //Do I need to summon a shadow orb? + if($TWM2::Vardison2_CanOrb[%dLevel]) { + //Is there already an active orb? + if(!isObject($TWM2::VardisonManager.orbObject)) { + //Yep, I need to summon it. + %needOrbSummon = true; + } + } + } + if((%cTime - %lastAtt) >= $TWM2::Vardison2_AttSpeed[%dLevel]) { + //Time for an attack + %needAttack = true; + } + else { + //If we're not ready to dish out an attack, let's check what else we need to do... + // Are we low on minions? + if($TWM2::VardisonManager.minionCount < $TWM2::Vardison2_MaxMinions[%dLevel]) { + //How many players am I up against? + %pCount = $HostGamePlayerCount; + //How low is my health? + %percentage = mCeil((mFloor(%boss.getDamageLeft()*100) / mFloor(%boss.getMaxDamage()*100)) * 100); + %BackwardsHP = 100 - %percentage; + %chance = %BackwardsHP * %pCount * (%Boss.canSummonMinions ? 1 : 0); + //Using our test factor, determine if I need minions. + if(%chance <= getRandom(1, 100)) { + %needMinions = true; + } + } + //Phase 2 is stationary unless you're on Hard or WTF mode + if(%dLevel >= 3) { + %needMove = true; + } + else { + //Phase Two only Super-Lunges if you get too close + if(getWord(VardisonGetClosest(%Boss), 1) <= 50) { + %needMove = true; + } + } + } + case 3: + //Did I just get a kill? + if(%nowKC > %lastKC) { + //Do I need to summon a shadow orb? + if($TWM2::Vardison3_CanOrb[%dLevel]) { + //Is there already an active orb? + if(!isObject($TWM2::VardisonManager.orbObject)) { + //Yep, I need to summon it. + %needOrbSummon = true; + } + } + } + if((%cTime - %lastAtt) >= $TWM2::Vardison3_AttSpeed[%dLevel]) { + //Time for an attack + %needAttack = true; + } + else { + //If we're not ready to dish out an attack, let's check what else we need to do... + // Are we low on minions? + if($TWM2::VardisonManager.minionCount < $TWM2::Vardison3_MaxMinions[%dLevel]) { + //How many players am I up against? + %pCount = $HostGamePlayerCount; + //How low is my health? + %percentage = mCeil((mFloor(%boss.getDamageLeft()*100) / mFloor(%boss.getMaxDamage()*100)) * 100); + %BackwardsHP = 100 - %percentage; + %chance = %BackwardsHP * %pCount * (%Boss.canSummonMinions ? 1 : 0); + //Using our test factor, determine if I need minions. + if(%chance <= getRandom(1, 100)) { + %needMinions = true; + } + } + //Do I need to be moving towards the enemy? + %needMove = true; //Phase 3 is always doing this... } - } } - if (%data.hasDamageRadius) - RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); -} - -function VardisonSubShadowBomb::onExplode(%data, %proj, %pos, %mod) { - if(%proj.count < %proj.maxExplode) { //holy... christ - %vec = vectorscale(vectornormalize(%proj.vector), 24); - %result = containerRayCast(vectoradd(%pos,"0 0 10"), vectoradd(%pos,%vec), $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::TerrainObjectType, %proj); - if(%result) - schedule(5, 0, "Napalm2FindNewDir", %pos, %vec, %proj.sourceobject, %proj.count, 0); - else { - %rndvec = (getRandom(1, 10) - 5)@" "@(getRandom(1, 10) - 5)@" "@((getRandom() * 5) + 5); - %newvec = vectoradd(%vec,%rndvec); - %newvec = vectoradd(%pos,%newvec); - %p = new LinearFlareProjectile() { - dataBlock = VardisonSubShadowBomb; - initialDirection = "0 0 -1"; - initialPosition = %newvec; - sourceObject = %proj.sourceobject; - sourceSlot = 5; - }; - %p.sourceobject = %proj.sourceobject; - %p.vector = %vec; - %p.count = %proj.count + 1; - } + //Call the correct function... + if(%needOrbSummon) { + VardisonSummonOrb(%Boss); } - if (%data.hasDamageRadius) - RadiusExplosion(%proj, %pos, %data.damageRadius, %data.indirectDamage, %data.kickBackStrength, %proj.sourceObject, %data.radiusDamageType); -} - -function Napalm2FindNewDir(%pos, %vec, %source, %count, %count2) { - if(%count2 == 2) { - %rndvec = getRandom(1, 10)@" "@getRandom(1, 10)@" "@((getRandom() * 5) + 4); - %newvec = vectoradd(%pos,%rndvec); - %p = new LinearFlareProjectile() { - dataBlock = VardisonSubShadowBomb; - initialDirection = "0 0 -1"; - initialPosition = %newvec; - sourceObject = %source; - sourceSlot = 5; - }; - %p.sourceobject = %source; - %p.vector = %vec; - %p.count = %count+1; - return; - } - if(%count2 == 1) { - %vec = vectorscale(%vec,-1); - %result = containerRayCast(vectoradd(%pos,"0 0 10"), vectoradd(%pos,%vec), $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::TerrainObjectType, 0); - if(!(%result)){ - %rndvec = getRandom(1, 10)@" "@getRandom(1, 10)@" "@((getRandom() * 5) + 4); - %newvec = vectoradd(%vec,%rndvec); - %newvec = vectoradd(%pos,%newvec); - %p = new LinearFlareProjectile() { - dataBlock = VardisonSubShadowBomb; - initialDirection = "0 0 -1"; - initialPosition = %newvec; - sourceObject = %source; - sourceSlot = 5; - }; - %p.sourceobject = %source; - %p.vector = %vec; - %p.count = %count+1; - return; - } + else if(%needAttack) { + VardisonPerformAttack(%Boss); } else { - %chance = getrandom(1,4); - if(%chance <= 2){ - %nv2 = (getword(%vec, 0) * -1); - %nv1 = getword(%vec, 1); - %vec = %nv1@" "@%nv2@" 0"; - } - else { - %nv2 = getword(%vec, 0); - %nv1 = (getword(%vec, 1) * -1); - %vec = %nv1@" "@%nv2@" 0"; - } - %result = containerRayCast(vectoradd(%pos,"0 0 10"), vectoradd(%pos,%vec), $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::ForceFieldObjectType | $TypeMasks::TerrainObjectType, 0); - if(!(%result)){ - %rndvec = getRandom(1, 10)@" "@getRandom(1, 10)@" "@((getRandom() * 5) + 4); - %newvec = vectoradd(%vec,%rndvec); - %newvec = vectoradd(%pos,%newvec); - %p = new LinearFlareProjectile() { - dataBlock = VardisonSubShadowBomb; - initialDirection = "0 0 -1"; - initialPosition = %newvec; - sourceObject = %source; - sourceSlot = 5; - }; - %p.sourceobject = %source; - %p.vector = %vec; - %p.count = %count+1; - return; + if(%needMinions) { + VardisonSummonMinions(%Boss); + } + if(%needMove) { + VardisonDoMove(%Boss); } } - %count2++; - schedule(2, 0, "Napalm2FindNewDir", %pos, %vec, %source, %count, %count2); + %Boss.thinkSched = schedule(500, 0, VardisonThink, %Boss); } -function GOVDoFlameCano(%g, %target) { - if(!isObject(%g) || %g.getState() $= "dead") { +function VardisonDoMove(%Boss) { + if(!isObject(%Boss) || %Boss.getState() $= "Dead") { return; } - %g.setPosition(VectorAdd(%target.getPosition(), "0 0 70")); - %Pad = new StaticShape() { - dataBlock = DeployedSpine; - scale = ".1 .1 1"; - position = VectorAdd(%target.getPosition(), "0 0 69"); + %pos = %Boss.getworldboxcenter(); + switch(%Boss.phase) { + case 1: + %closest = VardisonGetClosest(%Boss); + %clDst = getWord(%closest, 1); + %clPlayer = getWord(%closest, 0).Player; + if(%clDst < 12) { + //Perform a sword slam + VardisonDoSlam(%Boss, %clPlayer); + return; + } + if(%Boss.hastarget != 1){ + %Boss.hastarget = 1; + } + %vector = ZgetFacingDirection(%Boss, %clPlayer, %pos); + %vector = vectorscale(%vector, $Zombie::DForwardSpeed); + %upvec = "150"; + %x = Getword(%vector,0); + %y = Getword(%vector,1); + %z = Getword(%vector,2); + if(%z >= ($Zombie::DForwardSpeed)) { + %upvec = (%upvec * 5); + } + %vector = %x@" "@%y@" "@%upvec; + %Boss.applyImpulse(%pos, %vector); + + case 2: + %closest = VardisonGetClosest(%Boss); + %clDst = getWord(%closest, 1); + %clPlayer = getWord(%closest, 0).Player; + if(%clDst < 15) { + //Perform a sword slam + VardisonDoSlam(%Boss, %clPlayer); + return; + } + if(%Boss.hastarget != 1){ + %Boss.hastarget = 1; + } + %vector = ZgetFacingDirection(%Boss, %clPlayer, %pos); + %vector = vectorscale(%vector, $Zombie::DForwardSpeed*2); + %upvec = "150"; + %x = Getword(%vector,0); + %y = Getword(%vector,1); + %z = Getword(%vector,2); + if(%z >= ($Zombie::DForwardSpeed)) { + %upvec = (%upvec * 5); + } + %vector = %x@" "@%y@" "@%upvec; + %Boss.applyImpulse(%pos, %vector); + + case 3: + %closest = VardisonGetClosest(%Boss); + %clDst = getWord(%closest, 1); + %clPlayer = getWord(%closest, 0).Player; + if(%clDst < 6) { + //Insta-Kill xD + %clPlayer.setInvincible(false); + MessageAll('msgDie', "\c4Lord Vardision: DIE "@getWord(%closest, 0).namebase@"!!!"); + %clPlayer.damage(%boss, %clPlayer.getPosition(), 10000, $DamageType::Idiocy); + return; + } + if(%Boss.hastarget != 1){ + %Boss.hastarget = 1; + } + %vector = ZgetFacingDirection(%Boss, %clPlayer, %pos); + %vector = vectorscale(%vector, $Zombie::DForwardSpeed*1.8); + %upvec = "150"; + %x = Getword(%vector,0); + %y = Getword(%vector,1); + %z = Getword(%vector,2); + if(%z >= ($Zombie::DForwardSpeed)) { + %upvec = (%upvec * 5); + } + %vector = %x@" "@%y@" "@%upvec; + %Boss.applyImpulse(%pos, %vector); + } +} + +function VardisonDoSlam(%Boss, %ToDie) { + %Boss.busy = true; + %vector = ZgetFacingDirection(%Boss, %ToDie, %Boss.getWorldBoxCenter()); + %vector = vectorscale(%vector, $Zombie::DForwardSpeed * 7.5); + %upvec = "150"; + %x = Getword(%vector,0); + %y = Getword(%vector,1); + %z = Getword(%vector,2); + if(%z >= ($Zombie::DForwardSpeed)) { + %upvec = (%upvec * 5); + } + %vector = %x@" "@%y@" "@%upvec; + %Boss.applyImpulse(%pos, %vector); + schedule(750, 0, "VardisonFinishSlam", %Boss, %ToDie); +} + +function VardisonFinishSlam(%Boss, %ToDie) { + //Summon the invis-projectile + %Boss.setMoveState(true); + %p = new LinearFlareProjectile() { + dataBlock = ShadowBladeSlam; + initialDirection = "0 0 -10"; + initialPosition = vectorAdd(%ToDie.getPosition(), "0 0 1"); + sourceSlot = 0; }; - %g.setMoveState(true); - %Pad.setCloaked(true); - %Pad.schedule(3000, "setPosition", vectorSub(%Pad.getPosition(), "0 0 10")); - %Pad.schedule(4000, "setPosition", vectorSub(%Pad.getPosition(), "0 0 20")); - %Pad.schedule(5000, "setPosition", vectorSub(%Pad.getPosition(), "0 0 30")); - %Pad.schedule(6000, "setPosition", vectorSub(%Pad.getPosition(), "0 0 40")); - %g.schedule(6500, "SetMoveState", false); - %pad.schedule(6500, "Delete"); - //The Vector Crap - schedule(2500,0,"DropFlameCano2", %g, %target); + %p.sourceObject = %Boss; + MissionCleanup.add(%p); + %Boss.schedule(1000, "setMoveState", false); + ServerPlay3d(BOVHitSound, %ToDie.getPosition()); + ServerPlay3d(BOVHitSound, %ToDie.getPosition()); + ServerPlay3d(BOVHitSound, %ToDie.getPosition()); + $TWM2::VardisonManager.schedule(1000, cooldownOff, %Boss, "busy"); } -function DropFlameCano2(%g, %target) { - if(!isObject(%g) || %g.getState() $= "dead") { +function VardisonSummonOrb(%Boss) { + if(isObject($TWM2::VardisonManager.orbObject)) { + //Stop, we already have an orb. return; } - //First, Specify All Directions - %vec[1] = vectorscale(vectornormalize("1 0 0"), 24); // +X 0Y - %vec[2] = vectorscale(vectornormalize("1 1 0"), 24); // +X +Y - %vec[3] = vectorscale(vectornormalize("1 -1 0"), 24); // +X -Y - %vec[4] = vectorscale(vectornormalize("-1 0 0"), 24); // -X 0Y - %vec[5] = vectorscale(vectornormalize("-1 1 0"), 24); // -X +Y - %vec[6] = vectorscale(vectornormalize("-1 -1 0"), 24); //-X -Y - %vec[7] = vectorscale(vectornormalize("0 1 0"), 24); // 0X +Y - %vec[8] = vectorscale(vectornormalize("0 -1 0"), 24); // 0X -Y - //Oh.. long crap - for(%i = 1; %i <= 8; %i++) { - %p = new LinearFlareProjectile() { - dataBlock = ShadowBomb; - initialDirection = "0 0 -30"; - initialPosition = vectorAdd(%g.getPosition(), "0 0 -3"); - sourceObject = %g; - sourceSlot = 5; - }; - %p.vector = %vec[%i]; - %p.count = 1; - %p.MaxExplode = 15; - } + //Shadow Orb Time... + MessageAll('msgAttack', "\c5Alert: Lord Vardison Opens The Shadow Rift..."); + schedule(250, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(700, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1250, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1350, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(1500, 0, MessageAll, 'msgSound', "~wfx/environment/ctmelody4.wav"); + schedule(2000, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + schedule(2000, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + schedule(2000, 0, MessageAll, 'msgSound', "~wfx/explosions/explosion.xpl03.wav"); + %Boss.busy = true; + %Boss.rapierShield = true; + %Boss.setMoveState(true); + //Fire SFX + $TWM2::VardisonManager.orbFire = new ParticleEmissionDummy(){ + position = vectoradd(%Boss.getPosition(), "0 0 0.5"); + dataBlock = "defaultEmissionDummy"; + emitter = "SummoningPierEmitter"; + }; + MissionCleanup.add($TWM2::VardisonManager.orbFire); + //Create the Orb Object + $TWM2::VardisonManager.schedule(2000, summonOrb, %Boss); } -//The evilness Begins Here -function DAVardisonAttacks(%boss) { - if(!isObject(%boss) || %boss.getState() $= "dead") { - return; - } - schedule(23500, 0, "DAVardisonAttacks", %boss); - %attack = getRandom(1, 10); - switch(%attack) { +function VardisonSummonMinions(%Boss) { + %currentCount = $TWM2::VardisonManager.minionCount; + %dLevel = $TWM2::VardisonDifficulty; + %max = 0; + switch(%Boss.phase) { case 1: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "NMM", %target); - } + %max = $TWM2::Vardison1_MaxMinions[%dLevel]; case 2: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "LBM", %target); - } + %max = $TWM2::Vardison2_MaxMinions[%dLevel]; case 3: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "ShadowBombDirect", %target SPC 2); - } - case 4: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - GOVDoFlameCano(%boss, %target); - } - case 5: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "ShadowBombDirect", %target SPC 4); - } - case 6: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - for(%i = 0; %i < 10; %i++) { - %timeInt = %i * 200; - schedule(%timeInt, 0, VardisonAttack, %boss, "ShadowBombLaunchAbove", %target SPC 4); - } - } - case 7: - %boss.setMoveState(true); - %vS[0] = "10 10 0"; - %vS[1] = "-10 10 0"; - %vS[2] = "10 -10 0"; - %vS[3] = "-10 -10 0"; - for(%i = 0; %i < 4; %i++) { - CreateDemon(vectorAdd(%boss.getPosition(), %vS[%i])); - } - %boss.schedule(5000, setMoveState, false); - case 8: - %boss.setMoveState(true); - //four charge-up beams - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - //the actual attack - for(%i = 0; %i < 50; %i++) { - %timeAtt = 5000 + (%i *150); - //-------------------------- - %vec = %boss.GetMuzzleVector(4); - %pos = %boss.GetMuzzlePoint(4); - schedule(%timeAtt, 0, VardisonAttack, %boss, "HyperspeedPlasmaBolt", %pos TAB %vec); - } - %boss.schedule(12500, setMoveState, false); - case 9: - VardisonAttack(%boss, "LinearFlameWall"); - case 10: - VardisonAttack(%boss, "SeekingRapiers", %target); + %max = $TWM2::Vardison3_MaxMinions[%dLevel]; + } + %Low = 1; + %High = %max - %currentCount; + for(%i = 0; %i < getRandom(%Low, %High); %i++) { + VardisonDoMinionSummon(%Boss); + } + %Boss.canSummonMinions = false; + $TWM2::VardisonManager.schedule($TWM2::Vardison_MinionCooldown[%dLevel] * 1000, cooldownOff, %Boss, "minions"); +} + +function VardisonDoMinionSummon(%Boss) { + %posSpawn = vectorAdd(%Boss.getPosition(), getRandomposition(50, 1)); + %spawnFire = new ParticleEmissionDummy(){ + position = vectoradd(%posSpawn, "0 0 0.5"); + dataBlock = "defaultEmissionDummy"; + emitter = "SummoningPierEmitter"; + }; + MissionCleanup.add(%spawnFire); + %spawnFire.schedule(500, "delete"); + schedule(650, 0, SpawnVMinion, %posSpawn); +} + +function SpawnVMinion(%position) { + %minion = StartAZombie(%position, 17); + if(isObject(%minion)) { + //Apply minion settings & increase count + $TWM2::VardisonManager.minionCount++; + %minion.isBossMinion = true; + %minion.isVardisonMinion = true; } } -function VardisonAttacks(%boss) { - if(!isObject(%boss) || %boss.getState() $= "dead") { - return; - } - schedule(23500, 0, "VardisonAttacks", %boss); - %attack = getRandom(1, 8); - switch(%attack) { - case 1: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "NMM", %target); - } - case 2: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "LBM", %target); - } - case 3: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "ShadowBombDirect", %target SPC 2); - } - case 4: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - GOVDoFlameCano(%boss, %target); - } - case 5: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "ShadowBombDirect", %target SPC 4); - } - case 6: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - for(%i = 0; %i < 10; %i++) { - %timeInt = %i * 200; - schedule(%timeInt, 0, VardisonAttack, %boss, "ShadowBombLaunchAbove", %target SPC 4); - } - } - case 7: - %boss.setMoveState(true); - %vS[0] = "10 10 0"; - %vS[1] = "-10 10 0"; - %vS[2] = "10 -10 0"; - %vS[3] = "-10 -10 0"; - for(%i = 0; %i < 4; %i++) { - CreateDemon(vectorAdd(%boss.getPosition(), %vS[%i])); - } - %boss.schedule(5000, setMoveState, false); - case 8: - %boss.setMoveState(true); - //four charge-up beams - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - createLifeEmitter(%boss.getPosition(), PrebeamEmitter, 5000); - //the actual attack - for(%i = 0; %i < 50; %i++) { - %timeAtt = 5000 + (%i *150); - //-------------------------- - %vec = %boss.GetMuzzleVector(4); - %pos = %boss.GetMuzzlePoint(4); - schedule(%timeAtt, 0, VardisonAttack, %boss, "HyperspeedPlasmaBolt", %pos TAB %vec); - } - %boss.schedule(12500, setMoveState, false); +function VardisonGetClosest(%Boss) { + %wbpos = %Boss.getworldboxcenter(); + %count = ClientGroup.getCount(); + %closestClient = -1; + %closestDistance = 32767; + for(%i = 0; %i < %count; %i++) { + %cl = ClientGroup.getObject(%i); + if(isObject(%cl.player)){ + %testPos = %cl.player.getWorldBoxCenter(); + %distance = vectorDist(%wbpos, %testPos); + if (%distance > 0 && %distance < %closestDistance) { + %closestClient = %cl; + %closestDistance = %distance; + } + } } + return %closestClient SPC %closestDistance; } -function VardisonDroneAttacks(%boss) { - if(!isObject(%boss)) { - return; - } - schedule(10000, 0, "VardisonDroneAttacks", %boss); - %attack = getRandom(1,3); - switch(%attack) { +function VardisonPerformAttack(%Boss) { + //The do-all opening function for Vardison's attacks + //Start by halting the think() method + %Boss.busy = true; + switch(%Boss.phase) { case 1: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - VardisonAttack(%boss, "NMM", %target.player); - } - case 2: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "LBM", %target); - } - case 3: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "SuperLaser", %target); - } - } -} - -function VardisonDemonAttacks(%boss) { - if(!isObject(%boss) || %boss.getState() $= "dead") { - return; - } - //create a mini-demon - CreateDemon(vectorAdd(%boss.getPosition(), getRandomPosition(10, 1))); - // - %boss.setMoveState(true); - schedule(15000, 0, "VardisonDemonAttacks", %boss); - %attack = getRandom(1,8); - switch(%attack) { - case 1: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "LBM", %target); - schedule(2500, 0, VardisonAttack, %boss, "LBM", %target); - schedule(3500, 0, VardisonAttack, %boss, "LBM", %target); - schedule(5000, 0, VardisonAttack, %boss, "LBM", %target); - schedule(5100, 0, VardisonAttack, %boss, "LBM", %target); - %boss.schedule(5100, "SetMoveState", false); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": I've got some missiles for you "@getTaggedString(%target.client.name)@"."); - return; - } - %boss.schedule(1, "SetMoveState", false); - case 2: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - VardisonAttack(%boss, "NMM", %target.player); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": It's time to invoke darkness upon "@getTaggedString(%target.name)@"."); - %boss.schedule(1000, "SetMoveState", false); - return; - } - %boss.schedule(1, "SetMoveState", false); - case 3: - setgravity(-1000); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": I'll disorient you all!"); - schedule(3000, 0, "SetGravity", 1000); - schedule(7500, 0, "SetGravity", -20); - %boss.schedule(7500, "SetMoveState", false); - //%boss.InvokeLoop = InvokeStillwallLoop(%boss); - schedule(7500, 0, "Cancel", %boss.InvokeLoop); - case 4: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - VardisonAttack(%boss, "LaserDrop", %target); - %boss.schedule(3000, "SetMoveState", false); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": Your time has come "@getTaggedString(%target.client.name)@"."); - return; - } - %boss.schedule(1, "SetMoveState", false); - case 5: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - %target = %target.player; - for(%i = 0; %i < 25; %i++) { - schedule(50+(%i*150), 0, VardisonAttack, %boss, "SuperLaser", %target); - } - %boss.schedule(10000, "SetMoveState", false); - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": BLAAAAHAAHAHAHAAHA!!!"); - return; - } - %boss.schedule(1, "SetMoveState", false); - case 6: - for(%i = 0; %i < ClientGroup.getCount(); %i++) { - %target = ClientGroup.getObject(%i); - if(isObject(%target.player)) { - VardisonAttack(%boss, "NMM", %target.player); - } - } - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": All must suffer!!!"); - %boss.schedule(1000, "SetMoveState", false); - return; - case 7: - for(%i = 0; %i < ClientGroup.getCount(); %i++) { - %target = ClientGroup.getObject(%i); - if(isObject(%target.player)) { - %target = %target.player; - for(%l = 0; %l < 25; %l++) { - schedule(50+(%l*150), 0, VardisonAttack, %boss, "SuperLaser", %target); + %attackSelect = getRandom(1, 5); + switch(%attackSelect) { + case 1: + //Shadow Bomb Strike + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "ShadowBombStrike", %tPl); + $TWM2::VardisonManager.schedule(4000, cooldownOff, %Boss, "attackFinished"); } - } - } - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": Everyone DIES NOW!!!!"); - %boss.schedule(10000, "SetMoveState", false); - return; - case 8: - %target = FindValidTarget(%boss); - if(isObject(%target.player)) { - for(%i = 0; %i < 15; %i++) { - %time = %i * 150; - %mType = getRandom(0, 1); - switch(%mType) { - case 0: - schedule(%time, 0, VardisonAttack, %boss, "NMM", %target.player); - case 1: - schedule(%time, 0, VardisonAttack, %boss, "LBM", %target.player); - default: - schedule(%time, 0, VardisonAttack, %boss, "NMM", %target.player); + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 2: + //Nightmare Missile + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "NightmareMissile", %tPl); + $TWM2::VardisonManager.schedule(4500, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 3: + //Shadow Fissure + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + %tPos = %tPl.getPosition(); + %bPos = %Boss.getPosition(); + %fVec = vectorNormalize(vectorSub(%tPos, %bPos)); + //Phase Vardison Out To Safety + %fire = new ParticleEmissionDummy(){ + position = vectoradd(%spawnPos, "0 0 0.5"); + dataBlock = "defaultEmissionDummy"; + emitter = "SummoningPierEmitter"; + }; + MissionCleanup.add(%fire); + %fire.schedule(6500, "delete"); + //Fades & Teleports + %Boss.startfade(1500, 0, true); + %Boss.schedule(2000, setPosition, vectorAdd(%bPos, "9999 9999 10")); + schedule(3000, 0, "VardisonNamedAttack", %Boss, "ShadowFissure", %bPos TAB %fVec); + %Boss.schedule(6000, setPosition, %bPos); + %Boss.schedule(6000, startFade, 1000, 0, false); + // + $TWM2::VardisonManager.schedule(7000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 4: + //4x Seeker Photon + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + schedule(1000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(2000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(3000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(4000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + $TWM2::VardisonManager.schedule(5000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 5: + //Fire Missile + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "FireSeeker", %tPl); + $TWM2::VardisonManager.schedule(4500, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; } - } - MessageAll('MsgVardison', "\c4"@$TWM2::BossName["Vardison"]@": "@getTaggedString(%target.name)@" Will Feel the Power of My Missiles."); - %boss.schedule(1000, "SetMoveState", false); - return; } - %boss.schedule(1, "SetMoveState", false); + + case 2: + %attackSelect = getRandom(1, 8); + switch(%attackSelect) { + case 1: + //Shadow Bomb Strike + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "ShadowBombStrike", %tPl); + $TWM2::VardisonManager.schedule(4000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 2: + //Nightmare Missile + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "NightmareMissile", %tPl); + $TWM2::VardisonManager.schedule(4500, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 3: + //Shadow Fissure + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + %tPos = %tPl.getPosition(); + %bPos = %Boss.getPosition(); + %fVec = vectorNormalize(vectorSub(%tPos, %bPos)); + //Phase Vardison Out To Safety + %fire = new ParticleEmissionDummy(){ + position = vectoradd(%spawnPos, "0 0 0.5"); + dataBlock = "defaultEmissionDummy"; + emitter = "SummoningPierEmitter"; + }; + MissionCleanup.add(%fire); + %fire.schedule(6500, "delete"); + //Fades & Teleports + %Boss.startfade(1500, 0, true); + %Boss.schedule(2000, setPosition, vectorAdd(%bPos, "9999 9999 10")); + schedule(3000, 0, "VardisonNamedAttack", %Boss, "ShadowFissure", %bPos TAB %fVec); + %Boss.schedule(6000, setPosition, %bPos); + %Boss.schedule(6000, startFade, 1000, 0, false); + // + $TWM2::VardisonManager.schedule(7000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 4: + //4x Seeker Photon + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + schedule(1000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(2000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(3000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(4000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + $TWM2::VardisonManager.schedule(5000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 5: + //Minion Army + VardisonNamedAttack(%Boss, "MinionFlood", ""); + + case 6: + //Stasis Gate + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player.getPosition(); + VardisonNamedAttack(%Boss, "StasisGate", %tPl); + $TWM2::VardisonManager.schedule(10000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 7: + //Rift Gate + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player.getPosition(); + VardisonNamedAttack(%Boss, "RiftGate", %tPl); + $TWM2::VardisonManager.schedule(10000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 8: + //SGF + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "SolomentaryGravityFlux", %tPl TAB 0); + $TWM2::VardisonManager.schedule(5000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + } + + case 3: + %attackSelect = getRandom(1, 7); + switch(%attackSelect) { + case 1: + //Shadow Bomb Strike + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "ShadowBombStrike", %tPl); + $TWM2::VardisonManager.schedule(4000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 2: + //Nightmare Missile + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "NightmareMissile", %tPl); + $TWM2::VardisonManager.schedule(4500, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 3: + //Shadow Fissure + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + %tPos = %tPl.getPosition(); + %bPos = %Boss.getPosition(); + %fVec = vectorNormalize(vectorSub(%tPos, %bPos)); + //Phase Vardison Out To Safety + %fire = new ParticleEmissionDummy(){ + position = vectoradd(%spawnPos, "0 0 0.5"); + dataBlock = "defaultEmissionDummy"; + emitter = "SummoningPierEmitter"; + }; + MissionCleanup.add(%fire); + %fire.schedule(6500, "delete"); + //Fades & Teleports + %Boss.startfade(1500, 0, true); + %Boss.schedule(2000, setPosition, vectorAdd(%bPos, "9999 9999 10")); + schedule(3000, 0, "VardisonNamedAttack", %Boss, "ShadowFissure", %bPos TAB %fVec); + %Boss.schedule(6000, setPosition, %bPos); + %Boss.schedule(6000, startFade, 1000, 0, false); + // + $TWM2::VardisonManager.schedule(7000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 4: + //4x Seeker Photon + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + schedule(1000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(2000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(3000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + schedule(4000, 0, "VardisonNamedAttack", %Boss, "SeekerPhoton", %tPl); + $TWM2::VardisonManager.schedule(5000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 5: + //Laser Drop + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + VardisonNamedAttack(%Boss, "LaserDrop", %tPl); + $TWM2::VardisonManager.schedule(5000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 6: + //Laser Wall + %Boss.setMoveState(true); + %target = FindValidTarget(%Boss); + if(isObject(%target)) { + %tPl = %target.player; + for(%i = 0; %i < 25; %i++) { + schedule(50+(%i*150), 0, VardisonNamedAttack, %Boss, "LaserWall", %tPl); + } + $TWM2::VardisonManager.schedule(10000, cooldownOff, %Boss, "attackFinished"); + } + else { + %Boss.setMoveState(false); + %Boss.busy = false; + } + + case 7: + //Gravity Well + %Boss.setMoveState(true); + VardisonNamedAttack(%Boss, "GravityWell", 0); + $TWM2::VardisonManager.schedule(5000, cooldownOff, %Boss, "attackFinished"); + } + } } -function VardisonAttack(%boss, %att, %arg) { - if(!isObject(%boss) || %boss.getState() $= "dead") { +function VardisonNamedAttack(%Boss, %attack, %args) { + if(!isObject(%Boss) || %Boss.getState() $= "Dead") { return; } - switch$(%att) { - case "ShadowBombDirect": - %target = getWord(%arg, 0); - %detCt = getWord(%arg, 1); - if(!isObject(%target) || %target.getState() $= "dead") { + %bPos = %Boss.getPosition(); + + switch$(%attack) { + case "ShadowBombStrike": + //Spawn 4 Pulses Above Vardison Fired at a guy + %target = getField(%args, 0); + %sPos = vectorAdd(%bPos, "0 0 25"); + %vec = vectorNormalize(vectorSub(%target.getPosition(), %sPos)); + for(%i = 0; %i < 4; %i++) { + %p = new LinearFlareProjectile() { + dataBlock = ShadowBlastBolt; + initialDirection = vectorScale(%vec, 10); + initialPosition = %sPos; + sourceSlot = 4; + }; + %p.sourceObject = %Boss; + MissionCleanup.add(%p); + } + + case "NightmareMissile": + %target = getField(%args, 0); + %sPos = vectorAdd(%bPos, "0 0 25"); + %vec = vectorNormalize(vectorSub(%target.getPosition(), %sPos)); + %p = new SeekerProjectile() { + dataBlock = YvexNightmareMissile; + initialDirection = %vec; + initialPosition = %sPos; + sourceSlot = 4; + }; + %p.sourceObject = %Boss; + %beacon = new BeaconObject() { + dataBlock = "SubBeacon"; + beaconType = "vehicle"; + position = %target.getWorldBoxCenter(); + }; + %beacon.team = 0; + %beacon.setTarget(0); + MissionCleanup.add(%beacon); + %p.setObjectTarget(%beacon); + DemonMotherMissileFollow(%target, %beacon, %p); + + case "ShadowFissure": + %sPos = getField(%args, 0); + %fVec = getField(%args, 1); + for(%i = 1; %i < 20; %i++) { + %sPos = vectorAdd(%sPos, "0 0 0.5"); + %sPos = vectorAdd(%sPos, vectorScale(%fVec, %i*3)); + %p = new LinearFlareProjectile() { + dataBlock = ShadowBlastBolt; + initialDirection = "0 0 -15"; + initialPosition = %sPos; + sourceSlot = 4; + }; + %p.sourceObject = %Boss; + MissionCleanup.add(%p); + } + + case "SeekerPhoton": + %target = getField(%args, 0); + FireSeekerPhotons(%Boss, %target); + + case "FireSeeker": + %target = getField(%args, 0); + %sPos = vectorAdd(%bPos, "0 0 25"); + %vec = vectorNormalize(vectorSub(%target.getPosition(), %sPos)); + %p = new SeekerProjectile() { + dataBlock = VegenorFireMissile; + initialDirection = %vec; + initialPosition = %sPos; + sourceSlot = 4; + }; + %p.sourceObject = %Boss; + %beacon = new BeaconObject() { + dataBlock = "SubBeacon"; + beaconType = "vehicle"; + position = %target.getWorldBoxCenter(); + }; + %beacon.team = 0; + %beacon.setTarget(0); + MissionCleanup.add(%beacon); + %p.setObjectTarget(%beacon); + DemonMotherMissileFollow(%target, %beacon, %p); + + case "MinionFlood": + //Summon Maximum Minions & then Phase out until the team drops them + %max = $TWM2::Vardison2_MaxMinions[$TWM2::VardisonDifficulty]; + %lowEnd = mFloor(%max * 0.25); + %retPos = %bPos; + %current = $TWM2::VardisonManager.minionCount; + %need = %max - %current; + for(%i = 0; %i < %need; %i++) { + VardisonDoMinionSummon(%Boss); + } + //Meanwhile, I take my leave :) + %Boss.startfade(1500, 0, true); + %Boss.rapierShield = true; + %Boss.schedule(2000, setPosition, vectorAdd(%bPos, "9999 9999 10")); + %Boss.vmcountLoop = schedule(1000, 0, VardisonMinionCountCheckup, %Boss, %retPos, %lowEnd); + + case "StasisGate": + %pos = getField(%args, 0); + %TargetSearchMask = $TypeMasks::PlayerObjectType; + %c = createEmitter(%pos, FlashLEmitter, "1 0 0"); //Rotate it + %c.schedule(1000, delete); + InitContainerRadiusSearch(%pos, 25, %TargetSearchMask); + while ((%potentialTarget = ContainerSearchNext()) != 0){ + if (!%potentialTarget.isZombie && !%potentialTarget.isBoss && !%potentialTarget.isVardisonMinion) { + VardisonNamedAttack(%Boss, "StasisLoop", %potentialTarget TAB 0); + } + } + + case "StasisLoop": + %pl = getField(%args, 0); + if(!isObject(%pl) || %pl.getState() $= "dead") { return; } - %vec = vectorNormalize(vectorSub(%target.getPosition(),%boss.getPosition())); - %p = new LinearFlareProjectile() { - dataBlock = ShadowBomb; - initialDirection = vectorScale(%vec, 10); - initialPosition = %boss.getPosition(); - sourceObject = %boss; - sourceSlot = 4; - }; - %p.maxExplode = %detCt; - MissionCleanup.add(%p); - - case "ShadowBombLaunchAbove": - %target = getWord(%arg, 0); - %detCt = getWord(%arg, 1); - if(!isObject(%target) || %target.getState() $= "dead") { + %counter = getField(%args, 1); + %counter++; + if(%counter > 10) { + %pl.setMoveState(false); return; } - %vec = vectorNormalize(vectorSub(%target.getPosition(), vectorAdd(%boss.getPosition(), "0 0 35"))); - %p = new LinearFlareProjectile() { - dataBlock = ShadowBomb; - initialDirection = vectorScale(%vec, 10); - initialPosition = vectorAdd(%boss.getPosition(), "0 0 35"); - sourceSlot = 4; - }; - %p.maxExplode = %detCt; - %p.sourceObject = %boss; - MissionCleanup.add(%p); - - case "HyperspeedPlasmaBolt": - %boss.playShieldEffect("1 1 1"); - %pos = getField(%arg, 0); - %dir = getField(%arg, 1); - %p = new TracerProjectile() { - dataBlock = PlasmaCannonMainProj; - initialDirection = %dir; - initialPosition = %pos; - sourceObject = %boss; - sourceSlot = 4; - }; - MissionCleanup.add(%p); - + %c = createEmitter(%pl.getPosition(), PBCExpEmitter, "1 0 0"); //Rotate it + %c.schedule(1000, delete); + %pl.setMoveState(true); + schedule(1000, 0, VardisonNamedAttack, %Boss, %attack, %pl TAB %counter); + + case "RiftGate": + %pos = getField(%args, 0); + %goPos = RMPG(); + %TargetSearchMask = $TypeMasks::PlayerObjectType; + %c = createEmitter(%pos, FlashLEmitter, "1 0 0"); //Rotate it + %c.schedule(1000, delete); + %c2 = createEmitter(%goPos, FlashLEmitter, "1 0 0"); //Rotate it + %c2.schedule(1000, delete); + InitContainerRadiusSearch(%pos, 25, %TargetSearchMask); + while ((%potentialTarget = ContainerSearchNext()) != 0){ + if (!%potentialTarget.isZombie && !%potentialTarget.isBoss && !%potentialTarget.isVardisonMinion) { + %PosAdd = vectorNormalize(vectorSub(%pos, %potentialTarget.getPosition())); + %PosDst = vectorDist(%pos, %potentialTarget.getPosition()); + %newPos = vectorAdd(%goPos, vectorScale(%PosAdd, %PosDst)); + %potentialTarget.setPosition(%newPos); + } + } + case "LaserDrop": - %toDie = %arg; + %toDie = getField(%args, 0); if(!isObject(%toDie) || %toDie.getState() $= "dead") { return; } %p = new LinearFlareProjectile() { dataBlock = HyperDevestatorBeam; initialDirection = "0 0 -10"; - initialPosition = vectoradd(%target.getPosition(), "0 0 500"); - sourceObject = %boss; + initialPosition = vectoradd(%toDie.getPosition(), "0 0 500"); sourceSlot = 4; }; + %p.sourceObject = %boss; MissionCleanup.add(%p); - - case "SuperLaser": - %toDie = %arg; + + case "LaserWall": + %toDie = getField(%args, 0); if(!isObject(%toDie) || %toDie.getState() $= "dead") { return; } - %vec = vectorNormalize(vectorSub(%toDie.getPosition(), %boss.getPosition())); + %vec = vectorNormalize(vectorSub(%toDie.getPosition(), %bPos)); %p = new LinearFlareProjectile() { dataBlock = SuperlaserProjectile; initialDirection = %vec; - initialPosition = %boss.getPosition(); + initialPosition = %bPos; sourceObject = %boss; sourceSlot = 4; }; MissionCleanup.add(%p); - - case "NMM": - %target = %arg; - %vec = vectorNormalize(vectorSub(%target.getPosition(), %boss.getPosition())); - %p = new SeekerProjectile() { - dataBlock = YvexNightmareMissile; - initialDirection = %vec; - initialPosition = %boss.getPosition(); - sourceObject = %boss; - sourceSlot = 4; - }; - %beacon = new BeaconObject() { - dataBlock = "SubBeacon"; - beaconType = "vehicle"; - position = %target.getWorldBoxCenter(); - }; - %beacon.team = 0; - %beacon.setTarget(0); - MissionCleanup.add(%p); - MissionCleanup.add(%beacon); - %p.setObjectTarget(%beacon); - DemonMotherMissileFollow(%target,%beacon,%p); - - case "LBM": - %target = %arg; - %vec = vectorNormalize(vectorSub(%target.getPosition(), %boss.getPosition())); - %p = new SeekerProjectile() { - dataBlock = VardisonLaserBallMissile; - initialDirection = %vec; - initialPosition = %boss.getPosition(); - sourceObject = %boss; - sourceSlot = 4; - }; - %beacon = new BeaconObject() { - dataBlock = "SubBeacon"; - beaconType = "vehicle"; - position = %target.getWorldBoxCenter(); - }; - %beacon.team = 0; - %beacon.setTarget(0); - MissionCleanup.add(%p); - MissionCleanup.add(%beacon); - %p.setObjectTarget(%beacon); - DemonMotherMissileFollow(%target,%beacon,%p); - - case "LinearFlameWall": - %fVec = %boss.getEyeVector(); - %fPos = %boss.getEyePosition(); - %lPos = vectorAdd(%fPos, vectorScale(%fVec, 10)); - %vec = vectorScale(%fVec, 24); - //drop a line fire hire - %p = new TracerProjectile() { - dataBlock = napalmSubExplosion; - initialDirection = "0 0 -30"; - initialPosition = vectorAdd(%lPos, "0 0 3"); - sourceSlot = 5; - maxCount = 15; - }; - %p.sourceObject = %g; - %p.vector = %vec; - %p.count = 1; - - case "SeekingRapiers": - %target = %arg; - %iVec[0] = "1 0 0"; - %iVec[1] = "0 1 0"; - %iVec[2] = "-1 0 0"; - %iVec[3] = "0 -1 0"; - for(%i = 0; %i < 4; %i++) { - createSeekingProjectile("RapierShieldForwardProjectile", "LinearFlareProjectile", %boss.getPosition(), %iVec[%i], %boss, %target, 3000); + + case "SolomentaryGravityFlux": + %target = getField(%args, 0); + if(!isObject(%target) || %target.getState() $= "dead") { + return; } + %counter = getField(%args, 1); + %counter++; + if(%counter < 15) { + %target.setVelocity("0 0 300"); + } + else if(%counter > 25) { + //Stop... + return; + } + else { + %target.setVelocity("0 0 -300"); + } + schedule(150, 0, VardisonNamedAttack, %Boss, %attack, %target TAB %counter); + + case "GravityWell": + %counter = getField(%args, 0); + %counter++; + if(%counter < 15) { + for(%i = 0; %i < ClientGroup.getCount(); %i++) { + %cl = ClientGroup.getObject(%i); + if(isObject(%cl.player) || %cl.player.getState() !$= "dead") { + %cl.player.setVelocity("0 0 300"); + } + } + } + else if(%counter > 25) { + //Stop... + return; + } + else { + for(%i = 0; %i < ClientGroup.getCount(); %i++) { + %cl = ClientGroup.getObject(%i); + if(isObject(%cl.player) || %cl.player.getState() !$= "dead") { + %cl.player.setVelocity("0 0 -300"); + } + } + } + schedule(150, 0, VardisonNamedAttack, %Boss, %attack, %counter); + + default: + error("Invalid vardison attack..."); } } -function InvokeStillwallLoop(%boss) { - if(!isObject(%boss) || %boss.getState() $= "dead") { +function VardisonMinionCountCheckup(%boss, %retPos, %lowEnd) { + if($TWM2::VardisonManager.minionCount < %lowEnd) { + //Return to the arena + %Boss.schedule(1500, setPosition, %retPos); + %Boss.schedule(1500, startFade, 1000, 0, false); + %Boss.rapierShield = false; + $TWM2::VardisonManager.schedule(7000, cooldownOff, %Boss, "attackFinished"); return; } - %boss.setVelocity("0 0 0"); - %boss.InvokeLoop = schedule(100, 0, "InvokeStillwallLoop", %boss); + %boss.vmcountLoop = schedule(1000, 0, VardisonMinionCountCheckup, %boss, %retPos, %lowEnd); } - - - - - - - -//============================================================================== -datablock SeekerProjectileData(VardisonMiniDemonSpawner) : VardisonNightmareMissile { - baseEmitter = ShadowBaseEmitter; -}; - -function VardisonMiniDemonSpawner::OnExplode(%data, %proj, %pos, %mod) { - //LaserBall - %ball = CreateEmitter(%pos, "MiniShadowBallEmitter", "0 0 0 0"); - %ball.schedule(1000, "Delete"); - %Fire = CreateEmitter(%pos, "burnEmitter", "0 0 0 0"); - %Fire.schedule(2500, "Delete"); - CreateDemonAT(vectorAdd(%pos, "0 0 3")); -} - -datablock PlayerData(MiniDemonArmor) : LightMaleHumanArmor { - runForce = 60.20 * 90; - runEnergyDrain = 0.0; - minRunEnergy = 10; - maxForwardSpeed = 9; - maxBackwardSpeed = 7; - maxSideSpeed = 7; - - jumpForce = 14.0 * 90; - - maxDamage = 2.8; - minImpactSpeed = 1000; - shapeFile = "bioderm_medium.dts"; - jetEmitter = BiodermArmorJetEmitter; - jetEffect = BiodermArmorJetEffect; - - debrisShapeName = "bio_player_debris.dts"; - - //Foot Prints - decalData = LightBiodermFootprint; - decalOffset = 0.3; - - waterBreathSound = WaterBreathBiodermSound; - - damageScale[$DamageType::M1700] = 3.0; - damageScale[$DamageType::PlasmaCannon] = 0.001; - damageScale[$DamageType::Missile] = 0.0000000000000001; - damageScale[$DamageType::Nuclear] = 0.0000000000000001; - damageScale[$DamageType::EMP] = 0.0000000000000001; - - max[RepairKit] = 0; - max[Mine] = 0; - max[Grenade] = 0; -}; - -datablock GrenadeProjectileData(MiniDemonBlaster) { - projectileShapeName = "plasmabolt.dts"; - emitterDelay = -1; - directDamage = 0.0; - hasDamageRadius = true; - indirectDamage = 0.45; - damageRadius = 5.0; // z0dd - ZOD, 8/13/02. Was 20.0 - radiusDamageType = $DamageType::Demon; - kickBackStrength = 1500; - - explosion = "MortarExplosion"; - underwaterExplosion = "MortarExplosion"; - velInheritFactor = 0; - splash = PlasmaSplash; - depthTolerance = 100.0; - - baseEmitter = DemonFBSmokeEmitter; - bubbleEmitter = DemonFBSmokeEmitter; - - grenadeElasticity = 0; - grenadeFriction = 0.4; - armingDelayMS = -1; // z0dd - ZOD, 4/14/02. Was 2000 - - gravityMod = 0.4; // z0dd - ZOD, 5/18/02. Make mortar projectile heavier, less floaty - muzzleVelocity = 125.0; // z0dd - ZOD, 8/13/02. More velocity to compensate for higher gravity. Was 63.7 - drag = 0; - sound = PlasmaProjectileSound; - - hasLight = true; - lightRadius = 10; - lightColor = "1 0.75 0.25"; - - hasLightUnderwaterColor = true; - underWaterLightColor = "1 0.75 0.25"; -}; - -function CreateDemon(%pos) { - %p = new SeekerProjectile() { - dataBlock = VardisonMiniDemonSpawner; - initialDirection = "0 0 -10"; - initialPosition = vectorAdd(%pos, "0 0 500"); - //sourceObject = %boss; - //sourceSlot = 4; +//Vardison Manager Functions +//SummonOrb() +function VardisonManager::summonOrb(%this, %boss) { + %summonPos = vectorAdd(%boss.getPosition(), "0 0 35"); + %orb = new (StaticShape)() { + dataBlock = ShadowOrb; }; -} + %orb.setTransform(%summonPos SPC "0 0 0 1"); + %orb.team = %boss.Team; + %orb.setOwner(%boss); -function CreateDemonAT(%Pos) { - %Demon = new player(){ - Datablock = "MiniDemonArmor"; - }; - %Demon.setTransform(%Pos); - %Demon.type = 1; - %Demon.canjump = 1; - %Demon.hastarget = 1; - %Demon.isBoss = 1; //grant boss-like ability - - %Demon.team = 30; - - %Demon.target = createTarget(%Demon, "Shadow Warrior", "", "Derm3", '', %Demon.team, PlayerSensor); - setTargetSensorData(%Demon.target, PlayerSensor); - setTargetSensorGroup(%Demon.target, 30); - setTargetName(%Demon.target, addtaggedstring("Shadow Warrior")); - setTargetSkin(%Demon.target, 'Horde'); - - MissionCleanup.add(%Demon); - schedule(1000, %Demon, "MiniDemonMoveToTarget", %Demon); -} - -function MiniDemonMoveToTarget(%Demon){ - if(!isobject(%Demon)) - return; - if(%Demon.getState() $= "dead") - return; - %pos = %Demon.getworldboxcenter(); - %closestClient = ZombieLookForTarget(%Demon); - %closestDistance = getWord(%closestClient,1); - %closestClient = getWord(%closestClient,0).Player; - %Demon.counter++; - if(%Demon.counter >= 5) { - %Demon.counter = 0; - %Demon.canFire = 1; - } - if(%closestDistance <= $Zombie::detectDist) { - if(%Demon.hastarget != 1){ - %Demon.hastarget = 1; - } - %upvec = "250"; - %fmultiplier = $Zombie::FForwardSpeed; - - %vector = ZgetFacingDirection(%Demon,%closestClient,%pos); - - %vector = vectorscale(%vector, %Fmultiplier); - %x = Getword(%vector,0); - %y = Getword(%vector,1); - %z = Getword(%vector,2); - if(%z >= "1200" && %Demon.canjump == 1){ - %Demon.setvelocity("0 0 0"); - %upvec = (%upvec * 8); - %x = (%x * 0.5); - %y = (%y * 0.5); - %Demon.canjump = 0; - schedule(2500, %Demon, "Zsetjump", %Demon); - } - - if(%Demon.canFire) { - MiniDemonFire(%Demon, %closestclient); - } - - %vector = %x@" "@%y@" "@%upvec; - %Demon.applyImpulse(%pos, %vector); - } - else if(%Demon.hastarget == 1) { - %Demon.hastarget = 0; - %Demon.DemonRmove = schedule(100, %Demon, "ZSetRandomMove", %Demon); - } - %Demon.moveloop = schedule(500, %Demon, "MiniDemonMoveToTarget", %Demon); -} - -function MiniDemonFire(%demon, %closestclient){ - %pos = %demon.getMuzzlePoint(4); - %tpos = %closestclient.getWorldBoxCenter(); - %tvel = %closestclient.getvelocity(); - %vec = vectorsub(%tpos,%pos); - %dist = vectorlen(%vec); - %velpredict = vectorscale(%tvel,(%dist / 125)); - %vector = vectoradd(%vec,%velpredict); - %ndist = vectorlen(%vector); - %upvec = "0 0 "@((%ndist / 125) * (%ndist / 125) * 2); - %vector = vectornormalize(vectoradd(%vector,%upvec)); + %orb.team = 30; + %orb.target = createTarget(%orb, "\c7Shadow Rift", "", "Derm3", '', %orb.team, PlayerSensor); + setTargetSensorData(%orb.target, PlayerSensor); + setTargetSensorGroup(%orb.target, 30); + setTargetName(%orb.target, addtaggedstring("\c7Shadow Rift")); - %p = new GrenadeProjectile() { - dataBlock = MiniDemonBlaster; - initialDirection = %vector; - initialPosition = %pos; - sourceObject = %demon; - sourceSlot = 4; - }; - - %demon.canFire = 0; + //SFX + %orb.sfx = new ParticleEmissionDummy(){ + position = %orb.getPosition(); + dataBlock = "defaultEmissionDummy"; + emitter = "ShadowOrbEmitter"; + }; + MissionCleanup.add(%orb.sfx); + // + %this.orbKillSched = %this.schedule($TWM2::Vardison_OrbKillTime, orbKill, %boss, %orb); +} + +function VardisonManager::orbKill(%this, %boss, %orb) { + for(%i = 0; %i < ClientGroup.getCount(); %i++) { + %cl = ClientGroup.getObject(%i); + if(isObject(%cl.player) && %cl.player.getState() !$= "dead") { + //Bye Bye :) + %cl.player.setInvincible(false); + %cl.player.damage(%boss, %cl.player.getPosition(), 10000, $DamageType::ShadowOrb); + %cl.player.blowup(); + MessageAll('msgDeath', "\c2"@%cl.player.namebase@" has been annihilated by the Shadow Rift."); + //If Vardison Restores HP from rift kills, do that now :P + if($TWM2::Vardison_OrbRegenHP[$TWM2::VardisonDifficulty]) { + %boss.setDamageLevel(%boss.getDamageLevel() - 0.35); + } + } + } + %wipeEmit = new ParticleEmissionDummy(){ + position = %orb.getPosition(); + dataBlock = "defaultEmissionDummy"; + emitter = "ShadowOrbDetonationEmitter"; + }; + %wipeEmit.schedule(500, "delete"); + //Delete the orb & it's effects + if(isObject(%orb.sfx)) { + %obj.sfx.schedule(500, "delete"); + } + %orb.schedule(500, "delete"); + if(isObject(%this.orbFire)) { + %this.orbFire.schedule(500, "delete"); + } + %this.orbObject = -1; + %boss.rapierShield = false; + %boss.busy = false; //<-- let think() resume... +} + +function VardisonManager::orbDestroyed(%this) { + if(isObject(%this.orbFire)) { + %this.orbFire.schedule(500, "delete"); + } + cancel(%this.orbKillSched); + %this.orbObject = -1; + %boss = %this.Vardison; + %boss.rapierShield = false; + %boss.busy = false; //<-- let think() resume... +} + +function VardisonManager::cooldownOff(%this, %Boss, %type) { + if(!isObject(%this)) { + error("VardisonManager::cooldownOff(): Missing instance of VM."); + return; + } + if(!isObject(%Boss) || %Boss.getState() $= "dead") { + error("VardisonManager::cooldownOff(): Vardison Dead."); + return; + } + switch$(%type) { + case "minions": + %Boss.canSummonMinions = true; + + case "busy": + %Boss.busy = false; + + case "attackFinished": + //Unlock the boss & update LAT + %Boss.setMoveState(false); + %this.lastAttackTime = getRealTime(); + %Boss.busy = false; + } } diff --git a/scripts/TWM2/ChatCommands/Public.cs b/scripts/TWM2/ChatCommands/Public.cs index 80c1f71..f8511f3 100644 --- a/scripts/TWM2/ChatCommands/Public.cs +++ b/scripts/TWM2/ChatCommands/Public.cs @@ -831,7 +831,7 @@ function parsePublicCommands(%sender, %command, %args) { } else if (!isBoss(strlwr(%Boss))) { messageclient(%sender, 'MsgClient', '\c2Invalid Boss Name.'); - messageclient(%sender, 'MsgClient', '\c2Bosses: Yvex, CnlWindshear, GOL, GOF, Stormrider, DAVardison.'); + messageclient(%sender, 'MsgClient', '\c2Bosses: Yvex, CnlWindshear, GOL, GOF, Stormrider.'); messageclient(%sender, 'MsgClient', '\c2GenVeg, LordRog, Insignia, Trebor, Vardison, ShadeLord.'); return 1; } diff --git a/scripts/TWM2/ChatCommands/SuperAdmin.cs b/scripts/TWM2/ChatCommands/SuperAdmin.cs index 553dfa6..796f23e 100644 --- a/scripts/TWM2/ChatCommands/SuperAdmin.cs +++ b/scripts/TWM2/ChatCommands/SuperAdmin.cs @@ -143,10 +143,6 @@ function parseSuperAdminCommands(%sender, %command, %args) { %pos = VectorAdd(%sender.player.getPosition(), "0 0 5"); StartVardison1(%pos); MessageAll('MsgAdminForce', "\c3"@%sender.namebase@"\c2 spawned Lord Vardison, go hide noobs."); - case "DAVardison": - %pos = VectorAdd(%sender.player.getPosition(), "0 0 5"); - StartDAVardison(%pos); - MessageAll('MsgAdminForce', "\c3"@%sender.namebase@"\c2 spawned Dark Archmage Vardison, run in fear n0bs."); case "ShadeLord": %pos = VectorAdd(%sender.player.getPosition(), "0 0 5"); SpawnShadeLord(%pos); @@ -155,7 +151,7 @@ function parseSuperAdminCommands(%sender, %command, %args) { messageclient(%sender, 'MsgClient', '\c2Invalid Boss Name.'); messageclient(%sender, 'MsgClient', '\c2Bosses: Yvex, CnlWindshear, GhostOfLightning.'); messageclient(%sender, 'MsgClient', '\c2GenVegenor, LordRog, Insignia, Trebor, Vardison.'); - messageclient(%sender, 'MsgClient', '\c2Stormrider, GhostOfFire, ShadeLord, DAVardison.'); + messageclient(%sender, 'MsgClient', '\c2Stormrider, GhostOfFire, ShadeLord.'); } return 1; diff --git a/scripts/TWM2/Systems/BossSystem.cs b/scripts/TWM2/Systems/BossSystem.cs index c455401..33bef7f 100644 --- a/scripts/TWM2/Systems/BossSystem.cs +++ b/scripts/TWM2/Systems/BossSystem.cs @@ -3,6 +3,15 @@ function InitiateBoss(%Boss, %name) { error("SERVER: Cannot initiate boss, in horde/helljump"); return; } + + if(!isObject($TWM2::BossManager)) { + $TWM2::BossManager = new scriptObject() { + class = "BossManager"; + }; + } + $TWM2::BossManager.bossKills = 0; + $TWM2::BossManager.bossObject = %Boss; + $TWM2::BossManager.activeBoss = %name; $TWM2::BossGoing = 1; switch$(%name) { @@ -21,9 +30,9 @@ function InitiateBoss(%Boss, %name) { case "Vardison1": %print = "BOSS BATTLE \n LORD VARDISON"; case "Vardison2": - %print = "!DANGER! \n VARDISON HAS TRANSFORMED \n AIR FORM"; + %print = "BOSS ALERT \n LORD VARDISON HAS ENTERED HIS SECOND FORM"; case "Vardison3": - %print = "!DANGER! \n VARDISON HAS TRANSFORMED AGAIN \n DEMON FORM"; + %print = "BOSS ALERT \n LORD VARDISON HAS ENTERED HIS FINAL FORM"; case "Trebor": %print = "BOSS BATTLE \n LORDRANIUS TREVOR"; case "Stormrider": @@ -49,11 +58,11 @@ function InitiateBoss(%Boss, %name) { } function BossCheckUp(%boss, %name) { + %percentage = (mFloor(%boss.getDamageLeft()*100) / mFloor(%boss.getMaxDamage()*100)) * 100; + MessageAll('MsgSPCurrentObjective1', "", "Boss Battle: "@$TWM2::BossName[%name]@" [Boss Kill Count: "@$TWM2::BossManager.bossKills@"]"); + MessageAll('MsgSPCurrentObjective2', "", "Boss HP: "@mFloor(%boss.getDamageLeft()*100)@"/"@mFloor(%boss.getMaxDamage()*100)@" ("@%percentage@"%)"); - MessageAll('MsgSPCurrentObjective1', "", "Boss Battle: "@$TWM2::BossName[%name]@""); - MessageAll('MsgSPCurrentObjective2', "", "Boss HP: "@mFloor(%boss.getDamageLeft()*100)@"/"@mFloor(%boss.getMaxDamage()*100)@""); - - if(%name !$= "CnlWindshear" && %name !$= "Vardison2" && %name !$= "Trebor" && %name !$= "Stormrider") { + if(%name !$= "CnlWindshear" && %name !$= "Trebor" && %name !$= "Stormrider") { if(!isObject(%boss) || %boss.getState() $= "dead") { if(%name $= "Vardison1") { %count = ClientGroup.getCount(); @@ -61,7 +70,16 @@ function BossCheckUp(%boss, %name) { %cl = ClientGroup.getObject(%i); recordAction(%cl, "BOSS", "Vardison1"); } - StartVardison2(%boss.getPosition()); + SpawnVardison2(%boss.getPosition()); + return; + } + if(%name $= "Vardison2") { + %count = ClientGroup.getCount(); + for(%i = 0; %i < %count; %i++) { + %cl = ClientGroup.getObject(%i); + recordAction(%cl, "BOSS", "Vardison2"); + } + SpawnVardison3(%boss.getPosition()); return; } //the boss has been defeated, horrah!!! @@ -81,17 +99,6 @@ function BossCheckUp(%boss, %name) { } else { if(!isObject(%boss)) { - //the boss has been defeated, horrah!!! - if(%name $= "Vardison2") { - //but not quite so xD - %count = ClientGroup.getCount(); - for(%i = 0; %i < %count; %i++) { - %cl = ClientGroup.getObject(%i); - recordAction(%cl, "BOSS", "Vardison2"); - } - StartVardison3("0 0 200"); - return; - } %count = ClientGroup.getCount(); for(%i = 0; %i < %count; %i++) { %cl = ClientGroup.getObject(%i); @@ -167,11 +174,27 @@ function GameConnection::GiveBossAward(%client, %bossName) { } function FindValidTarget(%boss, %counter) { //This is usefull - %client = ClientGroup.getObject(GetRandom()*ClientGroup.getCount()); - if(!isObject(%client.player) || %client.player.getState() $= "dead" || %boss == %client.player) { - return schedule(500,0,"FindValidTarget", %boss, %counter++); //Keep Looking; + if(%counter $= "") { + %counter = 10; //10 attempts } - return %client; //target is good + for(%i = 0; %i < %counter; %i++) { + %test = ClientGroup.getObject(getRandom(0, ClientGroup.getCount())); + if(isObject(%test)) { + %tPL = %test.getControlObject(); + if(isObject(%tPL)) { + if(isPlayer(%tPL)) { + if(%tPL.getState() !$= "dead") { + //Got one! + return %test; + } + } + else { + return %test; + } + } + } + } + return -1; //Found nothing. } function CheckBossChallenge(%client, %boss) { @@ -430,9 +453,46 @@ function GenerateBossChallengeMenu(%client, %tag, %index) { %index++; } // + if(%client.CheckNWChallengeCompletion("VardEasy")) { + messageClient( %client, 'SetLineHud', "", %tag, %index, "The Standard Experience - Done"); + %index++; + } + else { + messageClient( %client, 'SetLineHud', "", %tag, %index, "The Standard Experience - Defeat Lord Vardison on Easy Difficulty"); + %index++; + } + if(%client.CheckNWChallengeCompletion("VardNorm")) { + messageClient( %client, 'SetLineHud', "", %tag, %index, "Demon Hunter - Done"); + %index++; + } + else { + messageClient( %client, 'SetLineHud', "", %tag, %index, "Demon Hunter - Defeat Lord Vardison on Normal Difficulty"); + %index++; + } + if(%client.CheckNWChallengeCompletion("VardHard")) { + messageClient( %client, 'SetLineHud', "", %tag, %index, "Master Demon Slayer - Done"); + %index++; + } + else { + messageClient( %client, 'SetLineHud', "", %tag, %index, "Master Demon Slayer - Defeat Lord Vardison on Hard Difficulty"); + %index++; + } + if(%client.CheckNWChallengeCompletion("VardWtf")) { + messageClient( %client, 'SetLineHud', "", %tag, %index, "God of the Shadow Realm - Done [You are a freaking boss master]"); + %index++; + } + else { + messageClient( %client, 'SetLineHud', "", %tag, %index, "God of the Shadow Realm - Against all odds, emerge victorious against WTF difficulty Lord Vardison"); + %index++; + } + // return %index; } +function BossManager::addKill(%this, %tObj) { + %this.bossKills++; +} + //Load The Boss Files exec("scripts/TWM2/Bosses/LordYvex.cs"); exec("scripts/TWM2/Bosses/ColonelWindshear.cs"); diff --git a/scripts/TWM2/Systems/NWChallengeIndex.cs b/scripts/TWM2/Systems/NWChallengeIndex.cs index 9e0b266..c19c53e 100644 --- a/scripts/TWM2/Systems/NWChallengeIndex.cs +++ b/scripts/TWM2/Systems/NWChallengeIndex.cs @@ -80,6 +80,10 @@ $Challenge::Info["Treb3"] = "Tank Halter\t2\t10000\tNone"; $Challenge::Info["Vard1"] = "Shining Star\t2\t3500\tNone"; $Challenge::Info["Vard2"] = "Glare The Dark\t2\t7000\tNone"; $Challenge::Info["Vard3"] = "Outevil The Wicked\t2\t12500\tLord Vardison Recruitable Ally"; +$Challenge::Info["VardEasy"] = "The Standard Experience\t2\t7000\tNone"; +$Challenge::Info["VardNorm"] = "Demon Hunter\t2\t1500\tNone"; +$Challenge::Info["VardHard"] = "Master Demon Slayer\t2\t25000\tNone"; +$Challenge::Info["VardWtf"] = "God of the Shadow Realm\t2\t50000\tNone"; //Blacklist $Challenge::Info["Acceptance"] = "Acceptance\t3\t1000\tNone"; $Challenge::Info["ListHit"] = "Hitlister of The List\t3\t2500\tNone"; diff --git a/scripts/TWM2/Zombie/ZombieCreation.cs b/scripts/TWM2/Zombie/ZombieCreation.cs index be42947..1e682be 100644 --- a/scripts/TWM2/Zombie/ZombieCreation.cs +++ b/scripts/TWM2/Zombie/ZombieCreation.cs @@ -182,10 +182,10 @@ function ZPCreateZombie(%obj){ function StartAZombie(%pos, %type){ if(!isObject(Game)) { error("UE Blocked..."); - return; + return -1; } if($Game::ZombieCount > $TWM2::MaxZombies || !$TWM2::CanSpawnZ) { - return; + return -1; } // if(%type $= "") { diff --git a/scripts/chatCommands.cs b/scripts/chatCommands.cs index ba5c5d2..2a30a72 100644 --- a/scripts/chatCommands.cs +++ b/scripts/chatCommands.cs @@ -286,8 +286,6 @@ function BossFullname(%BossAbbr) return "Ghost of Fire"; case "vardison": return "Lord Vardison"; - case "davardison": - return "Dark Archmage Vardison"; case "shadelord": return "The Shade Lord"; } @@ -317,8 +315,6 @@ function isBoss(%Boss) return 1; case "vardison": return 1; - case "davardison": - return 1; case "shadelord": return 1; } diff --git a/scripts/packs/Medpack.cs b/scripts/packs/Medpack.cs index 21230b7..633ab51 100644 --- a/scripts/packs/Medpack.cs +++ b/scripts/packs/Medpack.cs @@ -235,7 +235,7 @@ function Medrepair(%obj, %targets){ if(%obj.isreping == 0) return; if(%targets !$= ""){ - %numtrgs = getNumberOfWords(%targets); + %numtrgs = getWordCount(%targets); for(%i = 0; %i < %numtrgs; %i++){ %target = getWord(%targets, %i); if(vectorDist(%obj.getWorldBoxCenter(), %target.getWorldBoxCenter()) <= 10 && %target.getDamageLevel() > 0.0){ @@ -267,7 +267,7 @@ function Medrepair(%obj, %targets){ function MedstopRepair(%obj){ %obj.isreping = 0; if(%obj.reptargets !$= ""){ - %numtrgs = getNumberOfWords(%obj.reptargets); + %numtrgs = getWordCount(%obj.reptargets); for(%i = 0; %i < %numtrgs; %i++){ %target = getWord(%obj.reptargets, %i); if(%target.reping == 1){ @@ -305,6 +305,10 @@ function checkrevive(%obj){ messageclient(%obj.client, 'MsgClient', "\c2This body is destroyed."); return; } + if(%Tobj.isBoss == 1){ + messageclient(%obj.client, 'MsgClient', "\c2ARE YOU INSANE!?!??! YEAH... LETS JUST REVIVE THE DAMNED BOSS THAT JUST REKT YOU ABOUT 100 TIMES!!!!"); + return; + } if(%Tobj.infected || %Tobj.isZombie) { messageclient(%obj.client, 'MsgClient', "\c2WHOA!!! We don't want to make the Undead.... UnDead AGAIN."); return; diff --git a/scripts/packs/ZSpawnpack.cs b/scripts/packs/ZSpawnpack.cs index e2e10ce..6ac77ed 100644 --- a/scripts/packs/ZSpawnpack.cs +++ b/scripts/packs/ZSpawnpack.cs @@ -26,8 +26,51 @@ datablock AudioProfile(ZombieHOWL) preload = true; }; -//USED IN FLAMETHROWER +//USED IN FLAMETHROWER / NMM //DO NOT REMOVE: NEEDED HERE +datablock ParticleData(NMMissileBaseParticle) { + dragCoeffiecient = 0.0; + gravityCoefficient = -0.2; + inheritedVelFactor = 0.0; + + lifetimeMS = 800; + lifetimeVarianceMS = 500; + + useInvAlpha = false; + spinRandomMin = -160.0; + spinRandomMax = 160.0; + + animateTexture = true; + framesPerSec = 15; + + textureName = "special/cloudflash"; + + colors[0] = "0.5 0.1 0.9 1.0"; + colors[1] = "0.5 0.1 0.9 1.0"; + colors[2] = "0.5 0.1 0.9 1.0"; + + sizes[0] = 2.5; + sizes[1] = 2.7; + sizes[2] = 3.0; + + times[0] = 0.0; + times[1] = 0.7; + times[2] = 1.0; +}; + +datablock ParticleEmitterData(NMMissileBaseEmitter) { + ejectionPeriodMS = 10; + periodVarianceMS = 0; + + ejectionVelocity = 1.5; + velocityVariance = 0.3; + + thetaMin = 0.0; + thetaMax = 30.0; + + particles = "NMMissileBaseParticle"; +}; + datablock ParticleData(ThrowerBaseParticle) { dragCoeffiecient = 0.0; gravityCoefficient = -0.2; diff --git a/scripts/player.cs b/scripts/player.cs index 7920a9e..a6c8b89 100644 --- a/scripts/player.cs +++ b/scripts/player.cs @@ -3585,6 +3585,17 @@ function Armor::damageObject(%data, %targetObject, %sourceObject, %position, %am //now call the "onKilled" function if the client was... you know... if(%targetObject.getState() $= "Dead") { + //Is there a boss going? + if(!%targetObject.isZombie && !%targetObject.isBossMinion) { + if($TWM2::BossGoing) { + //Chalk up the kill count :P + $TWM2::BossManager.addKill(%targetObject); + } + } + if(%targetObject.isVardisonMinion) { + $TWM2::VardisonManager.minionCount--; + } + if($TWM2::PlayingSabo) { if(Game.Bomb.Carrier == %targetObject) { if(%damageType == $DamageType::FellOff) { diff --git a/scripts/weapons/Other/ShadowRifle.cs b/scripts/weapons/Other/ShadowRifle.cs index 84825f1..19bac80 100644 --- a/scripts/weapons/Other/ShadowRifle.cs +++ b/scripts/weapons/Other/ShadowRifle.cs @@ -1,46 +1,3 @@ -datablock ParticleData(NMMissileBaseParticle) { - dragCoeffiecient = 0.0; - gravityCoefficient = -0.2; - inheritedVelFactor = 0.0; - - lifetimeMS = 800; - lifetimeVarianceMS = 500; - - useInvAlpha = false; - spinRandomMin = -160.0; - spinRandomMax = 160.0; - - animateTexture = true; - framesPerSec = 15; - - textureName = "special/cloudflash"; - - colors[0] = "0.5 0.1 0.9 1.0"; - colors[1] = "0.5 0.1 0.9 1.0"; - colors[2] = "0.5 0.1 0.9 1.0"; - - sizes[0] = 2.5; - sizes[1] = 2.7; - sizes[2] = 3.0; - - times[0] = 0.0; - times[1] = 0.7; - times[2] = 1.0; -}; - -datablock ParticleEmitterData(NMMissileBaseEmitter) { - ejectionPeriodMS = 10; - periodVarianceMS = 0; - - ejectionVelocity = 1.5; - velocityVariance = 0.3; - - thetaMin = 0.0; - thetaMax = 30.0; - - particles = "NMMissileBaseParticle"; -}; - datablock LinearFlareProjectileData(ShadowRifleBolt) { projectileShapeName = "turret_muzzlepoint.dts"; scale = "1.0 1.0 1.0";