IncludeScript("hell_on_earth", getroottable()) bladeAttachments <- [ "lblade1", "lblade3", "lblade4", "rblade1", "rblade3", "rblade4", ]; PrecacheSound("Baron.RoarBig") PrecacheSound("Baron.GroundPound") PrecacheSound("Baron.HandWave") PrecacheSound("Baron.HandWaveAttack") PrecacheSound("Baron.FireballExplosion") PrecacheSound("ptx/sfx/baron_armor_regenerated.wav") PrecacheSound("ptx/sfx/baron_armor_regenerating.wav") PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = "fluidSmokeExpl_ring"}) PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = "eyeboss_doorway_vortex"}) PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = "bombinomicon_flash_halloween"}) PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = "drg_cow_explosioncore_charged_blue"}) PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = "drg_cow_explosion_sparkles_charged_blue"}) PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = "utaunt_elebound_green_glow"}) PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = "h2013_corpse_flame"}) local objRes = Entities.FindByClassname(null, "tf_objective_resource"); function MiniCritboost(player) { if(player.GetClassname()!= "player" || !player.InCond) return false return player.InCond(Constants.ETFCond.TF_COND_ENERGY_BUFF) || player.InCond(Constants.ETFCond.TF_COND_NOHEALINGDAMAGEBUFF) || player.InCond(Constants.ETFCond.TF_COND_OFFENSEBUFF) } function DispatchParticleAttached(entity, name, attachment) { if(entity == null) return if(name == null) { entity.AcceptInput("DispatchEffect", "ParticleEffectStop", null, null); return } local hParticle = CreateByClassname("trigger_particle") hParticle.KeyValueFromInt("attachment_type", 4) hParticle.KeyValueFromInt("spawnflags", 64) hParticle.KeyValueFromString("particle_name", name) hParticle.KeyValueFromString("attachment_name", attachment) hParticle.DispatchSpawn() hParticle.AcceptInput("StartTouch", "", entity, entity) hParticle.Kill() } function Ignite(player, duration = 10.0, damage = 1) { local utilignite = FindByName(null, "__utilignite") if (utilignite == null) { utilignite = SpawnEntityFromTable("trigger_ignite", { targetname = "__utilignite" burn_duration = duration damage = damage spawnflags = 1 }) } EntFireByHandle(utilignite, "StartTouch", "", -1, player, player) EntFireByHandle(utilignite, "EndTouch", "", 0.015, player, player) } function CreateExplosion(location, damage, range, inflictor, particleEffect, forceMultiplier = 0.0, upwardForce = 0.0, teamNumber = TF_TEAM_RED, explosionFX = "misc/null.wav") { ScreenShake(location, 5000, 5000, 4, 350, 0, true); local bomb = SpawnEntityFromTable("tf_generic_bomb", { explode_particle = "rd_robot_explosion", sound = explosionFX, damage = damage.tostring(), radius = range.tostring(), friendlyfire = "0", }); local particleEntity = SpawnEntityFromTable("info_particle_system", { effect_name = particleEffect, start_active = "0", targetname = "Explosion_PFX_Ent", origin = location, }); particleEntity.ValidateScriptScope(); particleEntity.GetScriptScope().m_flKillTime <- (Time() + 2.0).tofloat(); AddThinkToEnt(particleEntity, "KillMeThink"); bomb.ValidateScriptScope(); bomb.GetScriptScope().m_flKillTime <- (Time() + 0.1).tofloat(); bomb.GetScriptScope().m_hOwner <- inflictor; particleEntity.DispatchSpawn() EntFireByHandle(particleEntity, "Start", "", -1, null, null); SetPropInt(bomb, "m_iTeamNum", teamNumber); EmitSoundOn("Breakable.MatFlesh", bomb); EmitSoundOn(explosionFX, bomb); bomb.DispatchSpawn() bomb.SetTeam(teamNumber) bomb.SetOrigin(location) bomb.SetOwner(inflictor) bomb.KeyValueFromString("classname", "megaton") bomb.TakeDamage(1, DMG_CLUB, inflictor) return; } function DispatchInfoParticleSystem(entity, particle_name, vertical_offset) { local iparticle = SpawnEntityFromTable("info_particle_system", { effect_name = particle_name, start_active = 1, origin = entity.GetOrigin() + Vector(0, 0, vertical_offset), angles = Vector(0, 0, 0) }); iparticle.AcceptInput("SetParent", "!activator", entity, entity) } function IsOnGround(bot) { return bot.GetFlags() & FL_ONGROUND } function BossSlamRegular(bot, damage, radius) { ScreenShake(Vector(), 8, 40, 1, 0, 0, true) local StompOrigin = bot.GetOrigin() + Vector(0, 0, 15) local stompBomb = CreateByClassname("tf_generic_bomb") stompBomb.KeyValueFromInt("damage", 100) stompBomb.KeyValueFromInt("radius", 450) stompBomb.KeyValueFromInt("friendlyfire", 0) stompBomb.KeyValueFromString("classname", "purgatory") stompBomb.DispatchSpawn() stompBomb.SetAbsOrigin(StompOrigin) stompBomb.SetTeam(bot.GetTeam()) stompBomb.SetOwner(bot) stompBomb.AcceptInput("Detonate", null, bot, bot) DispatchParticleEffect("hammer_impact_button", StompOrigin, Vector(0, 0, 0)) DispatchParticleEffect("heavy_ring_of_fire_fp", StompOrigin, Vector(0, 0, 0)) DispatchParticleEffect("heavy_ring_of_fire_fp", StompOrigin, Vector(0, 0, 0)) local StompRadiusSquared = 202500 for (local i = 0, i_max = MaxClients(); i < i_max; i++) { local hPlayer = PlayerInstanceFromIndex(i + 1); // 0 is always worldspawn if (hPlayer == null) break if (((StompOrigin) - hPlayer.GetOrigin()).LengthSqr() < StompRadiusSquared) { hPlayer.SetAbsVelocity(Vector(0, 0, 500)) } bot.EmitSound("npc/roller/mine/rmine_explode_shock1.wav") } EntFireByHandle(stompBomb, "Kill", "", 0.1, null, null); } function isElementInArray(array, element) { foreach (item in array) { if (item == element) return true; } return false; } // POPEXT FUNCTIONS FOR LOOKAT function NormalizeAngle(target) { target %= 360.0 if (target > 180.0) target -= 360.0 else if (target < -180.0) target += 360.0 return target } function RemapValClamped(v, A, B, C, D) { if (A == B) { if (v >= B) return D return C } local cv = (v - A) / (B - A) if (cv <= 0.0) return C if (cv >= 1.0) return D return C + (D - C) * cv } function ApproachAngle(bot, target, value, speed) { target = NormalizeAngle(target) value = NormalizeAngle(value) local delta = NormalizeAngle(target - value) if (delta > speed) return value + speed else if (delta < -speed) return value - speed return target } function VectorAngles(forward) { local yaw, pitch if ( forward.y == 0.0 && forward.x == 0.0 ) { yaw = 0.0 if (forward.z > 0.0) pitch = 270.0 else pitch = 90.0 } else { yaw = (atan2(forward.y, forward.x) * 180.0 / Pi) if (yaw < 0.0) yaw += 360.0 pitch = (atan2(-forward.z, forward.Length2D()) * 180.0 / Pi) if (pitch < 0.0) pitch += 360.0 } return QAngle(pitch, yaw, 0.0) } function LookAt(bot, target_pos, min_rate, max_rate) { local cur_eye_ang = bot.EyeAngles() local dt = FrameTime() local dir = target_pos - bot.EyePosition() dir.Norm() local dot = cur_eye_ang.Forward().Dot(dir) local desired_angles = VectorAngles(dir) local rate_x = RemapValClamped(fabs(NormalizeAngle(cur_eye_ang.x) - NormalizeAngle(desired_angles.x)), 0.0, 180.0, min_rate, max_rate) local rate_y = RemapValClamped(fabs(NormalizeAngle(cur_eye_ang.y) - NormalizeAngle(desired_angles.y)), 0.0, 180.0, min_rate, max_rate) if (dot > 0.7) { local t = RemapValClamped(dot, 0.7, 1.0, 1.0, 0.05) local d = sin(1.57 * t) // pi/2 rate_x *= d rate_y *= d } cur_eye_ang.x = NormalizeAngle(ApproachAngle(bot, desired_angles.x, cur_eye_ang.x, rate_x * dt)) cur_eye_ang.y = NormalizeAngle(ApproachAngle(bot, desired_angles.y, cur_eye_ang.y, rate_y * dt)) bot.SnapEyeAngles(cur_eye_ang) } // LOOK AT END --------------- FROM POPEXT function CorrectTargetPos(hBot, hTarget) { local trace_box_landing = { start = hTarget, end = hTarget, hullmin = hBot.GetBoundingMins(), hullmax = hBot.GetBoundingMaxs(), mask = MASK_PLAYERSOLID, ignore = hBot } TraceHull(trace_box_landing) if ("startsolid" in trace_box_landing) { local dirs = [Vector(1, 0, 0), Vector(-1, 0, 0), Vector(0, 1, 0), Vector(0, -1, 0), Vector(0, 0, 1), Vector(0, 0, -1)]; for (local i = 16; i <= 96; i += 16) { foreach (dir in dirs) { trace_box_landing.start = hTarget + dir * i; trace_box_landing.end = trace_box_landing.start delete trace_box_landing.startsolid TraceHull(trace_box_landing) if (!("startsolid" in trace_box_landing)) { return trace_box_landing.end } } } } return hTarget } function IsInFieldOfView(user, target) { local tolerance = 0.5736 // cos(110/2) local eyefwd = user.EyeAngles().Forward() local eyepos = user.EyePosition() local delta = target.GetOrigin() - eyepos delta.Norm() if (eyefwd.Dot(delta) >= tolerance) return true delta = target.GetCenter() - eyepos delta.Norm() if (eyefwd.Dot(delta) >= tolerance) return true delta = target.EyePosition() - eyepos delta.Norm() return (eyefwd.Dot(delta) >= tolerance) } function IsVisible(user, target) { local trace = { start = user.EyePosition(), end = target.EyePosition(), mask = MASK_OPAQUE, ignore = user } TraceLineEx(trace) return !trace.hit } function Bezier(t, p0, p1, p2, p3) { local invT = 1.0 - t; p1.z = p1.z + 1.5; p2.z = p2.z + 1.5; return p0 * invT * invT * invT + p1 * 3.0 * invT * invT * t + p2 * 3.0 * invT * t * t + p3 * t * t * t; } function VectorLerp(v1, v2, t) { return v1 + (v2 - v1) * t; } function Max(a, b) { return a > b ? a : b; } function clamp(value, min, max) { if (value < min) return min; if (value > max) return max; return value; } function CalculateRange(hpPercentage) { hpPercentage = clamp(hpPercentage, 0, 100); local minA = 5, minB = 7; local maxA = 8, maxB = 14; local t = hpPercentage / 100; local resultA = minA + (t * (maxA - minA)).tointeger(); local resultB = minB + (t * (maxB - minB)).tointeger(); return [resultA, resultB]; } local function playSoundFromEntity(hEntity, soundname, huRange = 1500) { local hEnt = hEntity; if (typeof(hEntity) == "string") { hEnt = Entities.FindByName(null, hEntity) } local snd_lvl = (40 + (20 * log10(huRange / 36))).tointeger() PrecacheSound(soundname) EmitSoundEx({ sound_name = soundname entity = hEnt volume = 1 sound_level = snd_lvl filter_type = RECIPIENT_FILTER_GLOBAL }) } // FUNCTION WRITTEN BY KMLP, with my modifications function MeleeAttack_Base(attacker, attacker_team_id = Constants.ETFTeam.TF_TEAM_PVE_INVADERS, melee_damage = 65, melee_range = 84, max_degrees_field_of_view = 180, weapon_to_register = null, damage_type = Constants.FDmgType.DMG_CLUB, melee_emit_sound = null, melee_strike_sound = null, melee_strike_particle_effect = null) { /* -Mandatory arguments: attacker = Entity handle of who will be performing the melee attack. -Optional arguments: attacker_team_id = Red team or Bot team. melee_damage = Raw melee damage. melee_range = Raw melee range. max_degrees_field_of_view = If there are enemies outside of the attacker's max field of view, they will not be damaged. weapon_to_register = Want the attacker's weapon to show up in the killfeed? Pass in a tf_weapon entity here. damage_type = Damage type. TF2 melee is labeled as "Constants.FDmgType.DMG_CLUB". melee_emit_sound = The sound the attacker emits when executing the melee attack. melee_strike_sound = The sound that is played when the enemy is hit by the melee attack. melee_strike_particle_effect = The particle that shows when the enemy is hit by the melee attack. */ if (!attacker || !attacker.IsValid()) { return; } if (0 != NetProps.GetPropInt(attacker, "m_lifeState")) { return; } local enemy_types_to_damage = [ "player", "obj_sentrygun", "obj_dispenser", "obj_teleporter", "base_boss", "tank_boss", "tf_zombie" ] local opposite_team = -1 local players_hit = 0 /* I did not use "if (enemy_team != attacker_team)" as the conditional statement because spectators are considered its own team (Constants.ETFTeam.TEAM_SPECTATOR) And VScript might crash if you attempt to call "TakeDamageEx()" on a player who's loitering in spectator. */ switch (attacker_team_id) { case Constants.ETFTeam.TF_TEAM_PVE_DEFENDERS: opposite_team = Constants.ETFTeam.TF_TEAM_PVE_INVADERS; break; case Constants.ETFTeam.TF_TEAM_PVE_INVADERS: opposite_team = Constants.ETFTeam.TF_TEAM_PVE_DEFENDERS; break; } for (local i = 0; i < enemy_types_to_damage.len(); i = i + 1) { for (local entity_to_damage = null; entity_to_damage = Entities.FindByClassnameWithin(entity_to_damage, enemy_types_to_damage[i], attacker.GetOrigin(), melee_range); ) { if (!entity_to_damage || !entity_to_damage.IsValid()) { continue; } if (opposite_team != entity_to_damage.GetTeam()) { continue; } if (0 != NetProps.GetPropInt(entity_to_damage, "m_lifeState")) { continue; } local attacker_position = attacker.GetOrigin() if (attacker.HasBotTag("bot_baron_of_hell_armored") && attacker.GetSequence() == 14) { CreateExplosion(entity_to_damage.GetOrigin(), 750, 350, attacker, "fluidSmokeExpl_ring", 5) DispatchParticleEffect("flash_doomsday", entity_to_damage.GetOrigin(), Vector(0, 0, 0)) playSoundFromEntity(attacker, "Building_Sentry.Explode") players_hit++ return } local enemy_position = entity_to_damage.GetOrigin() local pawn_look_direction = attacker.GetAbsAngles().Forward() local direction_to_enemy = enemy_position - attacker_position direction_to_enemy.Norm() local bIs_within_field_of_view = cos((max_degrees_field_of_view/2.0) * (PI/180.0)) <= pawn_look_direction.Dot(direction_to_enemy) if (!bIs_within_field_of_view) { continue; } if (entity_to_damage.IsBotOfType(1337)) dmg *= 15 entity_to_damage.TakeDamageEx(attacker, attacker, weapon_to_register, Vector(0, 0, 0), attacker_position, melee_damage, damage_type) players_hit++ Ignite(entity_to_damage, 5, 4) if (melee_strike_sound) { playSoundFromEntity(entity_to_damage, melee_emit_sound, 650) } if (melee_strike_particle_effect) { DispatchParticleEffect(melee_strike_particle_effect, entity_to_damage.EyePosition(), Vector(0, 0, 0)); } } if (players_hit == 0) { local fireballAngles = attacker.GetAbsAngles() local deviations = [-15, 0, 15] local weapon = SpawnEntityFromTable("tf_point_weapon_mimic", { origin = attacker.GetCenter(), angles = fireballAngles, teamnum = 2, }) weapon.KeyValueFromString("$weaponname", "BaronFireWeapon") weapon.SetOwner(attacker) foreach (deviation in deviations) { local v = fireballAngles + Vector(0, deviation, 0) weapon.SetAbsAngles(QAngle(v.x, v.y, v.z)) weapon.SetAbsOrigin(attacker.GetCenter()) weapon.AcceptInput("FireOnce", null, null, null) } weapon.Kill() return } } if (melee_emit_sound) { playSoundFromEntity(attacker, melee_emit_sound) } } // -------------- SLAM LOGIC END ------------------- function DealPhysicalDamage(hAttacker) { if (isElementInArray([6, 7, 8, 21, 19], hAttacker.GetSequence())) return MeleeAttack_Base( hAttacker, //attacker hAttacker.GetTeam(), //attacker_team_id 75, //melee_damage 256,//melee_range 120, //max_degrees_field_of_view hAttacker.GetActiveWeapon(), //weapon_to_register Constants.FDmgType.DMG_PLASMA, //damage_type "Baron.HandWave", //melee_emit_sound "Baron.FireballExplosion", //melee_strike_sound "spell_fireball_tendril_flash_red" //melee_strike_particle_effect ) } ::MeleeSwipe <- function() { self.AddCustomAttribute("CARD: move speed bonus", 0.01, 1.5) local i = RandomInt(1, 2) if (isElementInArray([6, 7, 8, 13, 14, 21, 19], self.GetSequence())) return switch (i) { case 1: self.AcceptInput("$PlaySequence", "MELEE_R_Taunt", self, self) break case 2: self.AcceptInput("$PlaySequence", "MELEE_L_Taunt", self, self) break default: break } EntFireByHandle(self, "runscriptcode", "DealPhysicalDamage(self)", 0.47, self, null) } ::baronCallbacks <- { OnGameEvent_player_spawn = function(params) { local hPlayer = GetPlayerFromUserID(params.userid) if(hPlayer == null) return if (hPlayer.IsBotOfType(TF_BOT_TYPE)) { EntFireByHandle(hPlayer, "CallScriptFunction", "baronEnable", 0.01, null, null); EntFireByHandle(hPlayer, "CallScriptFunction", "ArmoredBaronEnable", 0.01, null, null); } } function OnScriptHook_OnTakeDamage(params) { if (params.const_entity == null || params.attacker == null || params.attacker == params.const_entity) return local hVictim = params.const_entity if(!hVictim.IsPlayer() || !hVictim.IsBotOfType(TF_BOT_TYPE) || !hVictim.HasBotTag("bot_baron_of_hell_armored")) return local dmg = params.damage local isCrit = false if ((params.damage_type & Constants.FDmgType.DMG_ACID)) { dmg *= 3 isCrit = true } else if (MiniCritboost(hVictim)) dmg *= 1.35 hVictim.SetHealth(hVictim.GetHealth() + dmg) if (GetPropInt(hVictim, "m_LastHitGroup") == 5 && params.attacker.GetSequence() == 14) hVictim.GetScriptScope().ARMOR_DAMAGE_ACCUMULATED += 5001 hVictim.GetScriptScope().ARMOR_DAMAGE_ACCUMULATED += dmg } } ::baronThink <- function() { if(NetProps.GetPropInt(self, "m_lifeState") != 0) { AddThinkToEnt(self, null) NetProps.SetPropString(self, "m_iszScriptThinkFunction", "") } local current_anim = self.GetSequence() // anim overlay prevention and shit if (!isElementInArray([0, 13, 14, 18, 19, 20, 29], current_anim)) { is_allowed_slam = true } else { is_allowed_slam = false } local currHp = self.GetHealth() if (PREVIOUS_HP != currHp) { local iHpPercentile = CONST_MAX_HP / currHp local result = CalculateRange(iHpPercentile) COOLDOWN_MIN = result[0] COOLDOWN_MAX = result[1] } // SEE PLAYER ---------------------------------------------------- SLAM LOGIC if (find_next_victim && NEXT_VICTIM_TARGET_TIME < Time() && is_allowed_slam) { for(local i = 1; i <= MAX_PLAYERS; i++) { local hPlayer = PlayerInstanceFromIndex(i) if (hPlayer != null && IsInFieldOfView(self, hPlayer)) { if (hPlayer.GetTeam() == self.GetTeam()) return -1 local trace = { start = self.EyePosition(), end = hPlayer.EyePosition(), mask = MASK_OPAQUE, ignore = self } TraceLineEx(trace) if (!trace.hit) { setup_jump_think = true find_next_victim = false local playerToGround = { start = hPlayer.GetOrigin() end = hPlayer.GetOrigin() - Vector(0, 0, 1000) mask = MASK_VISIBLE_AND_NPCS & ~(CONTENTS_MONSTER) } TraceLineEx(playerToGround) slam_target = CorrectTargetPos(self, playerToGround.pos) break } } } } // TRAVERSAL SLAM LOGIC if (setup_jump_think) { SetPropFloat(self.GetActiveWeapon(), "m_flNextPrimaryAttack", 6) execute_jump_think = true setup_jump_think = false local t = 0 local leap_index = 1 self.AddCustomAttribute("CARD: move speed bonus", 0.01, -1) local distance = (self.GetOrigin() - slam_target).Length() slam_damage = 75 if (distance > 1800) { t = 0.833 duration = 0.5667 wait_after_duration = 1.3336 } else if (distance > 650 && distance <= 1800) { t = 0.8334 duration = 0.8 leap_index = 3 wait_after_duration = 1.2 slam_damage += 35 slam_radius += 75 } else { t = 0.5667 duration = 0.6 leap_index = 2 wait_after_duration = 2.4333 slam_damage += 75 slam_radius += 125 } self.AcceptInput("$PlaySequence", "idle_leapattack" + leap_index, self, self) time_before_jump = Time() + t } if (execute_jump_think && time_before_jump < Time()) { playSoundFromEntity(self, "Baron.HandWave") LookAt(self, slam_target, 2147483647, 2147483647) startPos = self.GetOrigin() endPos = slam_target duration += 0.2 elapsedTime = 0.0; totalDistance = 0.0; currentDistance = 0.0; p1 = VectorLerp(startPos, endPos, 0.5); p1.z = Max(startPos.z, endPos.z) + 150.0; p2 = VectorLerp(startPos, endPos, 0.75); p2.z = (startPos.z + endPos.z) / 2.0 + 75.0; for (local t = 0.0; t <= 1.0; t += 0.01) { totalDistance += (Bezier(t + 0.01, startPos, p1, p2, endPos) - Bezier(t, startPos, p1, p2, endPos)).Length(); } local velocity = totalDistance / duration; local initialVerticalVelocity = velocity * 0.5; start_curve = true execute_jump_think = false } if (start_curve) { elapsedTime += FrameTime(); if (elapsedTime >= duration) { self.SetAbsOrigin(endPos); start_curve = false; NEXT_VICTIM_TARGET_TIME = Time() + RandomInt(COOLDOWN_MIN, COOLDOWN_MAX) BossSlamRegular(self, slam_damage, slam_radius) self.AddCustomAttribute("CARD: move speed bonus", 0.01, wait_after_duration) self.AddCustomAttribute("no_attack", 1, wait_after_duration) self.AddCustomAttribute("CARD: damage bonus", 0.001, wait_after_duration) playSoundFromEntity(self, "Baron.GroundPound") find_next_victim = true return -1; } local t = elapsedTime / duration; // Normalize time for curve local newPos = Bezier(t, startPos, p1, p2, endPos); self.SetAbsOrigin(newPos); } return -1 } ::baronEnable <- function() { local scope = self.GetScriptScope() if (self.IsBotOfType(TF_BOT_TYPE)) { self.ValidateScriptScope() if (self.HasBotTag("bot_baron_of_hell")) { self.ValidateScriptScope(); scope.CONST_MAX_HP <- self.GetMaxHealth() scope.PREVIOUS_HP <- self.GetMaxHealth() scope.baron_buttons_last <- null scope.execute_jump_think <- false scope.start_curve <- false scope.slam_target <- null scope.g <- 600 scope.startPos <- null scope.endPos <- null scope.duration <- null scope.elapsedTime <- null scope.totalDistance <- null scope.currentDistance <- null scope.p1 <- null scope.p2 <- null scope.find_next_victim <- true scope.setup_jump_think <- false scope.time_before_jump <- null scope.wait_after_duration <- 0 scope.is_allowed_slam <- true scope.COOLDOWN_MIN <- 5 scope.COOLDOWN_MAX <- 11 scope.slam_damage <- 75 scope.slam_radius <- 400 HP_DAMAGE_THRESHOLD <- 500 scope.LAST_TRIGGER_TIME <- Time() scope.HP_TRIGGER_INTERVAL <- 30 scope.NEXT_VICTIM_TARGET_TIME <- Time() PrecacheModel("models/doom_eternal/demons/unarmoredbaron_new.mdl") foreach (blade in bladeAttachments) { DispatchParticleAttached(self, "buildingdamage_dispenser_fire0", blade) } DispatchParticleAttached(self, "h2013_corpse_flame", "lblade2") DispatchParticleAttached(self, "h2013_corpse_flame", "rblade2") AddThinkToEnt(self, "baronThink") } } } // ARMORED BARON LOGIC ------------------------------------------------------ // ::ArmoredBaronEnable <- function() { local scope = self.GetScriptScope() if (self.IsBotOfType(TF_BOT_TYPE)) { self.ValidateScriptScope() if (self.HasBotTag("bot_baron_of_hell_armored")) { scope.CONST_MAX_HP <- self.GetMaxHealth() scope.PREVIOUS_HP <- self.GetMaxHealth() scope.baron_buttons_last <- null scope.execute_jump_think <- false scope.start_curve <- false scope.slam_target <- null scope.g <- 600 scope.startPos <- null scope.endPos <- null scope.duration <- null scope.elapsedTime <- null scope.totalDistance <- null scope.currentDistance <- null scope.p1 <- null scope.p2 <- null scope.find_next_victim <- true scope.setup_jump_think <- false scope.time_before_jump <- null scope.wait_after_duration <- 0 scope.is_allowed_slam <- true scope.COOLDOWN_MIN <- 5 scope.COOLDOWN_MAX <- 11 scope.slam_damage <- 75 scope.slam_radius <- 400 HP_DAMAGE_THRESHOLD <- 500 scope.LAST_TRIGGER_TIME <- Time() scope.HP_TRIGGER_INTERVAL <- 30 scope.NEXT_VICTIM_TARGET_TIME <- Time() scope.REGENERATING_SEQ <- false scope.ARMOR_DAMAGE_ACCUMULATED <- 0 scope.ARMOR_BROKEN_EVENT_TIME <- null scope.ARMOR_REGENERATING_EVENT_TIME <- null scope.armor_broken_event_triggered <- false scope.armor_regenerating_event_triggered <- false scope.armor_regenerated_event_triggered <- false PrecacheModel("models/doom_eternal/demons/unarmoredbaron_new.mdl") PrecacheModel("models/doom_eternal/demons/armoredbaron_new.mdl") DispatchParticleAttached(self, "h2013_corpse_flame", "mace") AddThinkToEnt(self, "ArmoredBaronThink") } } } ::ArmoredBaronThink <- function() { if(NetProps.GetPropInt(self, "m_lifeState") != 0) { AddThinkToEnt(self, null) NetProps.SetPropString(self, "m_iszScriptThinkFunction", "") } local current_anim = self.GetSequence() // anim overlay prevention and shit if (!isElementInArray([0, 13, 14, 18, 19, 20, 29], current_anim)) { is_allowed_slam = true } else { is_allowed_slam = false } // ARMOR REGENERATION LOGIC START ----------------------- // if (!armor_broken_event_triggered && !armor_regenerating_event_triggered && !armor_regenerated_event_triggered) { if (ARMOR_DAMAGE_ACCUMULATED >= 5000) { armor_broken_event_triggered = true ARMOR_BROKEN_EVENT_TIME = Time() if (!isElementInArray([6, 7, 8], self.GetSequence())) self.AddCustomAttribute("CARD: move speed bonus", 0.35, 1.125) local hExplodingArmor = SpawnEntityFromTable("info_particle_system", { origin = self.GetOrigin() + Vector(0, 0, 150) effect_name = "cinefx_goldrush" start_active = 1 }) playSoundFromEntity(self, "misc/doomsday_missile_explosion.wav") DispatchParticleEffect("fluidSmokeExpl_ring", self.GetCenter(), Vector(0, 0, 0)) EntFireByHandle(hExplodingArmor, "Stop", null, 3.5, null, null) EntFireByHandle(hExplodingArmor, "Kill", null, 4.5, null, null) self.SetCustomModelWithClassAnimations("models/doom_eternal/demons/unarmoredbaron_new.mdl") foreach (blade in bladeAttachments) { DispatchParticleAttached(self, "buildingdamage_dispenser_fire0", blade) } DispatchParticleAttached(self, "h2013_corpse_flame", "lblade2") DispatchParticleAttached(self, "h2013_corpse_flame", "rblade2") } } if (armor_broken_event_triggered && !armor_regenerating_event_triggered) { if ((Time() - ARMOR_BROKEN_EVENT_TIME) >= 10) { armor_regenerating_event_triggered = true ARMOR_REGENERATING_EVENT_TIME = Time() self.AddCondEx(TF_COND_RUNE_RESIST, 5.5, null) playSoundFromEntity(self, "ptx/sfx/baron_armor_regenerating.wav") DispatchParticleAttached(self, "eyeboss_vortex_blue", "center") DispatchParticleAttached(self, "dxhr_lightningball_parent_blue", "center") DispatchParticleAttached(self, "eyeboss_doorway_vortex", "center") if (!isElementInArray([6, 7, 8], self.GetSequence())) self.AddCustomAttribute("CARD: move speed bonus", 0.75, 5.5) } } if (armor_regenerating_event_triggered && !armor_regenerated_event_triggered) { if ((Time() - ARMOR_REGENERATING_EVENT_TIME) >= 5) { armor_regenerated_event_triggered = true playSoundFromEntity(self, "ptx/sfx/baron_armor_regenerated.wav") self.SetCustomModelWithClassAnimations("models/doom_eternal/demons/armoredbaron_new.mdl") DispatchParticleAttached(self, "h2013_corpse_flame", "mace") DispatchParticleEffect("bombinomicon_flash_halloween", self.GetCenter(), Vector(0, 0, 0)) DispatchParticleEffect("drg_cow_explosioncore_charged_blue", self.GetCenter(), Vector(0, 0, 0)) DispatchParticleEffect("drg_cow_explosion_sparkles_charged_blue", self.GetCenter(), Vector(0, 0, 0)) ARMOR_DAMAGE_ACCUMULATED = 0 armor_broken_event_triggered = false armor_regenerating_event_triggered = false armor_regenerated_event_triggered = false } } // ARMOR REGENERATION LOGIC END ----------------------- // local currHp = self.GetHealth() if (PREVIOUS_HP != currHp) { local iHpPercentile = CONST_MAX_HP / currHp local result = CalculateRange(iHpPercentile) COOLDOWN_MIN = result[0] COOLDOWN_MAX = result[1] } // SEE PLAYER ---------------------------------------------------- SLAM LOGIC if (find_next_victim && NEXT_VICTIM_TARGET_TIME < Time() && is_allowed_slam) { for(local i = 1; i <= MAX_PLAYERS; i++) { local hPlayer = PlayerInstanceFromIndex(i) if (hPlayer != null && IsInFieldOfView(self, hPlayer)) { if (hPlayer.GetTeam() == self.GetTeam()) return -1 local trace = { start = self.EyePosition(), end = hPlayer.EyePosition(), mask = MASK_OPAQUE, ignore = self } TraceLineEx(trace) if (!trace.hit) { setup_jump_think = true find_next_victim = false local playerToGround = { start = hPlayer.GetOrigin() end = hPlayer.GetOrigin() - Vector(0, 0, 1000) mask = MASK_VISIBLE_AND_NPCS & ~(CONTENTS_MONSTER) } TraceLineEx(playerToGround) slam_target = CorrectTargetPos(self, playerToGround.pos) break } } } } // TRAVERSAL SLAM LOGIC if (setup_jump_think) { SetPropFloat(self.GetActiveWeapon(), "m_flNextPrimaryAttack", 6) execute_jump_think = true setup_jump_think = false local t = 0 local leap_index = 1 self.AddCustomAttribute("CARD: move speed bonus", 0.01, -1) local distance = (self.GetOrigin() - slam_target).Length() slam_damage = 75 if (distance > 1800) { t = 0.833 duration = 0.5667 wait_after_duration = 1.3336 } else if (distance > 650 && distance <= 1800) { t = 0.8334 duration = 0.8 leap_index = 3 wait_after_duration = 1.2 slam_damage += 35 slam_radius += 75 } else { t = 0.5667 duration = 0.6 leap_index = 2 wait_after_duration = 2.4333 slam_damage += 75 slam_radius += 125 } self.AcceptInput("$PlaySequence", "idle_leapattack" + leap_index, self, self) time_before_jump = Time() + t } if (execute_jump_think && time_before_jump < Time()) { playSoundFromEntity(self, "Baron.HandWave") LookAt(self, slam_target, 2147483647, 2147483647) startPos = self.GetOrigin() endPos = slam_target duration += 0.2 elapsedTime = 0.0; totalDistance = 0.0; currentDistance = 0.0; p1 = VectorLerp(startPos, endPos, 0.5); p1.z = Max(startPos.z, endPos.z) + 150.0; p2 = VectorLerp(startPos, endPos, 0.75); p2.z = (startPos.z + endPos.z) / 2.0 + 75.0; for (local t = 0.0; t <= 1.0; t += 0.01) { totalDistance += (Bezier(t + 0.01, startPos, p1, p2, endPos) - Bezier(t, startPos, p1, p2, endPos)).Length(); } local velocity = totalDistance / duration; local initialVerticalVelocity = velocity * 0.5; start_curve = true execute_jump_think = false } if (start_curve) { elapsedTime += FrameTime(); if (elapsedTime >= duration) { self.SetAbsOrigin(endPos); start_curve = false; NEXT_VICTIM_TARGET_TIME = Time() + RandomInt(COOLDOWN_MIN, COOLDOWN_MAX) BossSlamRegular(self, slam_damage, slam_radius) self.AddCustomAttribute("CARD: move speed bonus", 0.01, wait_after_duration) self.AddCustomAttribute("no_attack", 1, wait_after_duration) self.AddCustomAttribute("CARD: damage bonus", 0.001, wait_after_duration) playSoundFromEntity(self, "Baron.GroundPound") find_next_victim = true return -1; } local t = elapsedTime / duration; // Normalize time for curve local newPos = Bezier(t, startPos, p1, p2, endPos); self.SetAbsOrigin(newPos); } return -1 } __CollectGameEventCallbacks(baronCallbacks)