//////////////////////////BUSTER PrecacheModel("models/player/marauder.mdl") PrecacheModel("models/weapons/c_models/c_argent_axe/c_argent_axe.mdl") function PrecacheParticle(name) { PrecacheEntityFromTable({ classname = "info_particle_system", effect_name = name }) } PrecacheParticle("merasmus_zap_flash") PrecacheParticle("ping_circle") ::MarauderThink <- function() { local origin = self.GetOrigin() local primary = PopExtUtil.GetItemInSlot(self, 0) local secondary = PopExtUtil.GetItemInSlot(self, 1) local melee = PopExtUtil.GetItemInSlot(self, 2) local marauder_buttons = NetProps.GetPropInt(self, "m_nButtons"); local marauder_buttons_changed = marauder_buttons_last ^ marauder_buttons; local marauder_buttons_pressed = marauder_buttons_changed & marauder_buttons; local marauder_buttons_released = marauder_buttons_changed & (~marauder_buttons); local forwardvelo = self.EyePosition()+self.EyeAngles().Forward()*150 local eyelook = self.EyeAngles() ///Setup if (projectile_check == false) { if(!("projectile" in getroottable()) || !projectile.IsValid()) { //grenade launcher has compatibility with mangler projectile projectile <- Entities.CreateByClassname("TF_WEAPON_GRENADELAUNCHER"); NetProps.SetPropInt(projectile, "m_AttributeManager.m_Item.m_iItemDefinitionIndex", 206); NetProps.SetPropInt(projectile, "m_AttributeManager.m_Item.m_bInitialized", 1); projectile.DispatchSpawn(); projectile.AddAttribute("override projectile type", 12, -1) //projectile.AddAttribute("Blast radius decreased", 0.01, -1) projectile.AddAttribute("blast dmg to self increased", 0, -1) projectile.AddAttribute("self dmg push force decreased", 0, -1) projectile.AddAttribute("projectile speed increased", 2, -1) projectile.AddAttribute("energy weapon no deflect", 1, -1) } projectile_check = true } function LookAt(target_pos, min_rate, max_rate) { local cur_eye_pos = self.EyePosition() local cur_eye_fwd = self.EyeAngles().Forward() local cur_eye_ang = self.EyeAngles() local dt = FrameTime() local dir = target_pos - cur_eye_pos dir.Norm() local dot = cur_eye_fwd.Dot(dir) local desired_angles = PopExtUtil.VectorAngles(dir) local rate_x = PopExtUtil.RemapValClamped(fabs(PopExtUtil.NormalizeAngle(cur_eye_ang.x) - PopExtUtil.NormalizeAngle(desired_angles.x)), 0.0, 180.0, min_rate, max_rate) local rate_y = PopExtUtil.RemapValClamped(fabs(PopExtUtil.NormalizeAngle(cur_eye_ang.y) - PopExtUtil.NormalizeAngle(desired_angles.y)), 0.0, 180.0, min_rate, max_rate) if (dot > 0.7) { local t = PopExtUtil.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 = PopExtUtil.NormalizeAngle(PopExtUtil.ApproachAngle(desired_angles.x, cur_eye_ang.x, rate_x * dt)) cur_eye_ang.y = PopExtUtil.NormalizeAngle(PopExtUtil.ApproachAngle(desired_angles.y, cur_eye_ang.y, rate_y * dt)) self.SnapEyeAngles(cur_eye_ang) } melee.DisableDraw() melee.SetModelSimple("models/empty.mdl") SetPropInt(melee, "m_fEffects", 32) //EF_NODRAW //Shield //Not meant to outrage mitigate all damage, just extend longetivity to encourage waiting for him to strike if (marauder_buttons & Constants.FButtons.IN_ATTACK2 && self.GetActiveWeapon() != primary) { if (shield == null) { shield = SpawnEntityFromTable("entity_medigun_shield", { //targetname = "shield" teamnum = self.GetTeam() skin = self.GetTeam() == TF_TEAM_RED ? 0 : 1 }) DispatchSpawn(shield) } shield.AddEFlags(Constants.FEntityEFlags.EFL_NO_THINK_FUNCTION); shield.SetModelSimple("models/props_mvm/mvm_comically_small_player_shield.mdl") self.AddCustomAttribute("no_attack", 1, -1) if (shield.IsValid()) { shield.SetOrigin(forwardvelo + Vector(0, 0, -75)) shield.SetAbsAngles(eyelook) } } else { if (shield != null) { shield.Kill() shield = null self.RemoveCustomAttribute("no_attack") } } for (local projectile; projectile = FindByClassnameWithin(projectile, "tf_projectile_*", origin, 400);) { if (NetProps.GetPropBool(projectile, "m_bTouched") == true) continue if (projectile.GetTeam() != self.GetTeam()) { local holdshield = RandomInt(1, 75) if (holdshield == 1) { self.PressAltFireButton(0.5) self.AddCondEx(47, 0.5, null) } if (self.InCond(47)) { local enemy_projectile = projectile.GetOrigin() LookAt(enemy_projectile, INT_MAX, INT_MAX) } } } //Hide weapon model here by checking if melee is active //If melee is not active, look for all tf_wearables owned by self, then fire Kill input if (self.GetActiveWeapon() == melee) { if (wepaxe == null) { wepaxe = CreateByClassname("tf_wearable") PopExtUtil.CreatePlayerWearable(self, "models/weapons/c_models/c_argent_axe/c_argent_axe.mdl", true, "effect_hand_r", true) } } else { for (local ent; ent = FindByClassname(ent, "tf_wearable");) { if (ent.GetOwner() == self) { ent.Kill() wepaxe = null } } } //AI Script //if the bot somehow taunts, prevent it here, otherwise it may momentarily fuck up the script self.StopTaunt(true) if (self.InCond(51)) { self.AddCustomAttribute("no_jump", 1, -1) return } tryDodge() //if bot is stunned, remove heavy armor if (self.IsControlStunned()) { self.RemoveCustomAttribute("dmg taken increased") self.RemoveCustomAttribute("health regen") } else { self.AddCustomAttribute("dmg taken increased", 0.01, -1) self.AddCustomAttribute("health regen", 15, -1) } if (!(self.GetFlags() & FL_ONGROUND) && willdodge == true) { local whichway = RandomInt(1, 4) DispatchParticleEffect("doublejump_puff_alt", self.GetOrigin(), Vector(0, 0, 0)) if (whichway == 1) { self.SetVelocity(Vector(0, 800, 30)) willdodge = false } else if (whichway == 2) { self.SetVelocity(Vector(0, -800, 30)) willdodge = false } else if (whichway == 3) { self.SetVelocity(Vector(-800, 0, 30)) willdodge = false } else if (whichway == 4) { self.SetVelocity(Vector(800, 0, 30)) willdodge = false } } //axe local eyepos_sword_start = self.EyePosition()+self.EyeAngles().Forward()*100 local eyepos_sword_end = self.EyePosition()+self.EyeAngles().Forward()*375 local eyetrace_sword = { start = eyepos_sword_start, end = eyepos_sword_end ignore = self } TraceLineEx(eyetrace_sword) //shotgun local eyepos_shotgun_start = self.EyePosition()+self.EyeAngles().Forward() local eyepos_shotgun_end = self.EyePosition()+self.EyeAngles().Forward()*100 local eyetrace_shotgun = { start = eyepos_shotgun_start, end = eyepos_shotgun_end ignore = self } TraceLineEx(eyetrace_shotgun) //projectile local eyepos_proj_start = self.EyePosition()+self.EyeAngles().Forward()*375 local eyepos_proj_end = self.EyePosition()+self.EyeAngles().Forward()*99999 local eyetrace_proj = { start = eyepos_proj_start, end = eyepos_proj_end ignore = self } TraceLineEx(eyetrace_proj) //using two seperate if statements causes buggy switch behavior //I dont care if im wrong, this works and that makes me happy if (eyetrace_shotgun.hit && "enthit" in eyetrace_shotgun && eyetrace_shotgun.enthit.GetClassname() == "player") { local hitPlayer = eyetrace_shotgun.enthit if (hitPlayer == null) return if (hitPlayer.GetTeam() == self.GetTeam()) return local enemy = hitPlayer.GetOrigin() + Vector(50, 0, 0) melee.RemoveAttribute("disable weapon switch") melee.RemoveAttribute("provide on active") //auto reload upon pulling out the shotgun if (self.GetActiveWeapon() != primary) { primary.SetClip1(2) } self.Weapon_Switch(primary) //force ability to reload if (melee.GetMaxClip1() == 0) { primary.AddAttribute("no_attack", 1, -1) } else { primary.RemoveAttribute("no_attack") } } else if (eyetrace_sword.hit && "enthit" in eyetrace_sword && eyetrace_sword.enthit.GetClassname() == "player") { local hitPlayer = eyetrace_sword.enthit if (hitPlayer.GetTeam() == self.GetTeam()) return if (hitPlayer == null) return use_projectile = false if (axe == null) { bottle = null melee.Kill() axe = PopExtUtil.GiveWeapon(self, "tf_weapon_sword", 132) // eyelander axe.AddAttribute("melee range multiplier", 2.35, -1) // lower to give players space to stun the guy axe.AddAttribute("fire rate penalty", 3.5, -1) axe.AddAttribute("damage bonus", 2.154, -1) axe.AddAttribute("hand scale", 1.5, -1) } local enemy = hitPlayer.GetOrigin() self.Weapon_Switch(melee) if (melee.IsValid()) { melee.AddAttribute("disable weapon switch", 1, -1) melee.AddAttribute("provide on active", 1, -1) } LookAt(enemy + Vector(0, 0, 100), INT_MAX, INT_MAX) } else if (eyetrace_proj.hit && "enthit" in eyetrace_proj && eyetrace_proj.enthit.GetClassname() == "player") { local hitPlayer = eyetrace_proj.enthit if (hitPlayer.GetTeam() == self.GetTeam()) return if (hitPlayer == null) return use_projectile = true if (bottle == null) { axe = null melee.Kill() bottle = PopExtUtil.GiveWeapon(self, "TF_WEAPON_BOTTLE", 191) // bottle bottle.AddAttribute("damage penalty", 0, -1) bottle.AddAttribute("hand scale", 1.5, -1) } if (melee.IsValid()) { melee.AddAttribute("disable weapon switch", 1, -1) melee.AddAttribute("provide on active", 1, -1) } self.Weapon_Switch(melee) self.PressFireButton(0.1) } if (NetProps.GetPropInt(self, "m_Shared.m_iNextMeleeCrit") == 0) { if (self.GetActiveWeapon() == melee && use_projectile == false) { if (!self.InCond(12)) { self.AddCondEx(65, 0.3, null) DispatchParticleEffect("merasmus_zap_flash", origin + Vector(0, 0, 100), Vector(0, 0, 0)) DispatchParticleEffect("ping_circle", origin + Vector(0, 0, 100), Vector(0, 0, 0)) } } if (self.GetActiveWeapon() == melee && use_projectile == true) { NetProps.SetPropEntity(projectile, "m_hOwner", self); NetProps.SetPropFloat(projectile, "m_flNextPrimaryAttack", 0); projectile.SetClip1(-1) projectile.PrimaryAttack(); //stop the sound on the player fixes the playing sound on shoot issue self.StopSound("Weapon_GrenadeLauncher.Single") } // continue smack detection NetProps.SetPropInt(self, "m_Shared.m_iNextMeleeCrit", -2); } marauder_buttons_last = marauder_buttons; return -1 } ::MarauderEnable <- function() { ////printl(self) local playerScope = self.GetScriptScope() local wep = PopExtUtil.GetItemInSlot(self, 2) local getwepID = NetProps.GetPropInt(wep, "m_AttributeManager.m_Item.m_iItemDefinitionIndex") if (self != null && self.IsBotOfType(TF_BOT_TYPE)) { self.ValidateScriptScope() if (!("PlayerThinkTable" in self.GetScriptScope())) self.GetScriptScope().PlayerThinkTable <- {} if (self.HasBotTag("bot_marauder")) { self.ValidateScriptScope(); self.SetCustomModelWithClassAnimations("models/player/marauder.mdl") self.SetForcedTauntCam(2) local shotgun = PopExtUtil.GiveWeapon(self, "TF_WEAPON_SHOTGUN_PRIMARY", 199) shotgun.AddAttribute("clip size penalty", 0.25, -1) shotgun.AddAttribute("bullets per shot bonus", 3, -1) shotgun.AddAttribute("mod ammo per shot", 2, -1) shotgun.AddAttribute("spread penalty", 1.5, -1) shotgun.AddAttribute("faster reload rate", 0.55, -1) shotgun.AddAttribute("damage causes airblast", 1, -1) shotgun.SetClip1(2) shotgun.SetModelScale(1.25, 0) // local axe = PopExtUtil.GiveWeapon(self, "tf_weapon_sword", 266) // // local model = CreateByClassname("tf_wearable") // // PopExtUtil.CreatePlayerWearable(self, "models/weapons/c_models/c_argent_axe/c_argent_axe.mdl", true, "effect_hand_r", true) // axe.AddAttribute("melee range multiplier", 2.75, -1) // axe.AddAttribute("fire rate penalty", 1.5, -1) // axe.AddAttribute("hand scale", 1.5, -1) NetProps.SetPropInt(self, "m_Shared.m_iNextMeleeCrit", -2); playerScope.dodgeTime <- 3 playerScope.serverTime <- 0 playerScope.willdodge <- false playerScope.tryDodge <- function() { //caberCountTime acts as time if (dodgeTime == null) return local time = floor(Time()) if (time != serverTime) { // Once every second serverTime = time //printl(dodgeTime) if (dodgeTime > 0) { self.AddCustomAttribute("no_jump", 1, -1) willdodge = false dodgeTime-- } if (dodgeTime == 0) { local checkdodge = RandomInt(1, 4) if (checkdodge == 1) { self.RemoveCustomAttribute("no_jump") willdodge = true } dodgeTime = 3 } //printl(caberTimer) } } playerScope.wepaxe <- null playerScope.axe <- null playerScope.bottle <- null playerScope.projectile_check <- false playerScope.use_projectile <- false playerScope.marauder_buttons_last <- 0; playerScope.shield <- null PopExtUtil.AddThinkToEnt(self, "MarauderThink"); } } } //////////////////////////ON GAME EVENTS function OnScriptHook_OnTakeDamage(params) { // if (params.attacker == null || params.attacker.GetClassname() == "worldspawn") return; // if (params.const_entity.GetClassname() != "player" || params.attacker.GetClassname() != "player") return; local victim = params.const_entity if (victim.GetClassname() == "player") { if (victim.IsBotOfType(TF_BOT_TYPE)) { if (victim.HasBotTag("bot_marauder")) { if (NetProps.GetPropInt(victim, "m_Shared.m_iNextMeleeCrit") == 0 || victim.InCond(65)) { PopExtUtil.StunPlayer(victim, 3, 1, 0, 0.5) victim.AddCondEx(12, 9, null) } } } } } function OnGameEvent_player_spawn(params) { local player = GetPlayerFromUserID(params.userid); local playerScope = player.GetScriptScope() local wep = PopExtUtil.GetItemInSlot(player, 2) local getwepID = NetProps.GetPropInt(wep, "m_AttributeManager.m_Item.m_iItemDefinitionIndex") if (player != null && player.IsBotOfType(TF_BOT_TYPE)) { EntFireByHandle(player, "CallScriptFunction", "MarauderEnable", 0.1, null, null); } } function MarauderTutorial1() { for (local player; player = FindByClassname(player, "player");) { EntFireByHandle(player, "RunScriptCode", ClientPrint(player, 4, "Marauders have HEAVY ARMOR, regular attacks WON'T do much!"), 0, player, player) } } function MarauderTutorial2() { for (local player; player = FindByClassname(player, "player");) { EntFireByHandle(player, "RunScriptCode", ClientPrint(player, 4, "BREAK the armor when their EYE glows GREEN"), 0, player, player) } } function MarauderTutorial3() { for (local player; player = FindByClassname(player, "player");) { EntFireByHandle(player, "RunScriptCode", ClientPrint(player, 4, "Some may remember fighting it..."), 0, player, player) } } // WaveSpawn // Dummy // { // WaitForAllSpawned "boss" // TotalCount 1 // SpawnCount 1 // WaitBeforeStarting 0 // Support Limited // FirstSpawnOutput // { // Target gamerules // Action CallScriptFunction // Param "MarauderTutorial1" // } // } // WaveSpawn // Dummy // { // WaitForAllSpawned "boss" // TotalCount 1 // SpawnCount 1 // WaitBeforeStarting 5 // Support Limited // FirstSpawnOutput // { // Target gamerules // Action CallScriptFunction // Param "MarauderTutorial2" // } // } // WaveSpawn // Dummy // { // WaitForAllSpawned "boss" // TotalCount 1 // SpawnCount 1 // WaitBeforeStarting 10 // Support Limited // FirstSpawnOutput // { // Target gamerules // Action CallScriptFunction // Param "MarauderTutorial3" // } // }