//vscript by stardustspy //do not use without my credit PLEASE!!!!!!!!! ::TEAM_RED <- 2 ::TEAM_BLU <- 3 ::TF_NAV_SPAWN_ROOM_RED <- 2 ::TF_NAV_SPAWN_ROOM_BLUE <- 4 ::TF_BOT_FAKE_CLIENT <- 1337 ::MAX_COUNT_WEAPON_EQUPPED <- 8 ::TEAM_SPECTATOR <- 1 ::SOLID_NONE <- 0 ::CONTENTS_SOLID <- 1 ::CONTENTS_WINDOW <- 2 ::CONTENTS_GRATE <- 8 ::CONTENTS_MOVEABLE <- 16384 ::CONTENTS_PLAYERCLIP <- 65536 ::MASK_NPCWORLDSTATIC <- 131083 ::MASK_PLAYERSOLID <- 33636363 ::MASK_NPCSOLID <- 33701899 ::MASK_SOLID <- 33570827 ::MASK_SHOT <- 1174421507 ::MASK_SHOT_HULL <- 100679691 ::IN_ATTACK2 <- 2048 ::PI <- 3.14159265359 ::PRIMARY_FIRE <- Constants.FButtons.IN_ATTACK ::SECONDARY_FIRE <- Constants.FButtons.IN_ATTACK2 ::gamerules <- Entities.FindByClassname(null, "tf_gamerules") ::player_manager <- Entities.FindByClassname(null, "tf_player_manager") ::WORLD_SPAWN <- Entities.FindByClassname(null, "worldspawn") ::MAX_COUNT_PLAYERS <- MaxClients().tointeger() ::MASK_VISIBLE_AND_NPCS <- 33579137 ::DMG_CRITICAL <- 1048576 ::TF_DMG_CUSTOM_HEADSHOT <- 1 ::TF_DMG_CUSTOM_BACKSTAB <- 2 ::TF_DMG_CRITICAL <- 1048576 ::SND_NOFLAGS <- 0 ::SND_CHANGE_VOL <- 1 ::SND_CHANGE_PITCH <- 2 ::SND_STOP <- 4 ::SND_SPAWNING <- 8 ::SND_DELAY <- 16 ::SND_STOP_LOOPING <- 32 ::SND_SPEAKER <- 64 ::SND_SHOULDPAUSE <- 128 ::SND_IGNORE_PHONEMES <- 256 ::SND_IGNORE_NAME <- 512 ::SND_DO_NOT_OVERWRITE_EXISTING_ON_CHANNEL <- 1024 ::IGNORE_ENEMIES <- 1024 const STRING_NETPROP_ITEMDEF = "m_AttributeManager.m_Item.m_iItemDefinitionIndex" const SLOT_COUNT = 7 const EFL_USER = 1048576 // EFL_IS_BEING_LIFTED_BY_BARNACLE const EFL_USER2 = 1073741824 //EFL_NO_PHYSCANNON_INTERACTION const SINGLE_TICK = 0.015 const DMG_NO_BULLET_FALLOFF = 2097152 PrecacheSound("ambient/energy/weld1.wav") PrecacheSound("ambient/energy/weld2.wav") PrecacheSound("player/recharged.wav") PrecacheSound("npc/assassin/ball_zap1.wav") PrecacheSound("weapons/drg_wrench_teleport.wav") PrecacheSound("misc/halloween/spell_lightning_ball_cast.wav") PrecacheSound("misc/halloween/spell_meteor_impact.wav") PrecacheSound("misc/halloween/spell_spawn_boss.wav") PrecacheSound("Weapon_Revolver.Single") PrecacheSound("weapons/sniper_railgun_charged_shot_crit_02.wav") //fold ::ROOT <- getroottable(); if (!("ConstantNamingConvention" in ROOT)) // make sure folding is only done once { foreach (a,b in Constants) foreach (k,v in b) ROOT[k] <- v != null ? v : 0; } function GetItemInSlot(player, slot) { local item for (local i = 0; i < SLOT_COUNT; i++) { local wep = NetProps.GetPropEntityArray(player, "m_hMyWeapons", i) if ( wep == null || wep.GetSlot() != slot) continue item = wep break } return item } ::RailgunSMG <- { Cleanup = function() { // keep this at the end delete ::RailgunSMG } // mandatory events OnGameEvent_recalculate_holidays = function(_) { if (GetRoundState() == 3) { Cleanup() } } OnGameEvent_mvm_wave_complete = function(_) { Cleanup() } function PrintTable(table) { if (table == null) return; this.DoPrintTable(table, 0) } function DoPrintTable(table, indent) { local line = "" for (local i = 0; i < indent; i++) { line += " " } line += typeof table == "array" ? "[" : "{"; ClientPrint(null, 2, line) indent += 2 foreach(k, v in table) { line = "" for (local i = 0; i < indent; i++) { line += " " } line += k.tostring() line += " = " if (typeof v == "table" || typeof v == "array") { ClientPrint(null, 2, line) this.DoPrintTable(v, indent) } else { try { line += v.tostring() } catch (e) { line += typeof v } ClientPrint(null, 2, line) } } indent -= 2 line = "" for (local i = 0; i < indent; i++) { line += " " } line += typeof table == "array" ? "]" : "}"; ClientPrint(null, 2, line) } function CanBeHurt(entity) { local UberArray = [5, 8, 51, 52, 57] foreach(cond in UberArray) { if (entity.InCond(cond)) { return true } } return false } GetItemInSlot = function(player, slot) { local item for (local i = 0; i < SLOT_COUNT; i++) { local wep = NetProps.GetPropEntityArray(player, "m_hMyWeapons", i) if ( wep == null || wep.GetSlot() != slot) continue item = wep break } return item } StripWeapon = function(player, slot) { if (slot == -1) slot = player.GetActiveWeapon().GetSlot() for (local i = 0; i < SLOT_COUNT; i++) { local weapon = this.GetItemInSlot(player, i); if (weapon == null || weapon.GetSlot() != slot) continue; weapon.Kill(); break; } } GiveWeapon = function(player, className, itemID) { if (typeof itemID == "string" && className == "tf_wearable") { CTFBot.GenerateAndWearItem.call(player, itemID) return } local weapon = Entities.CreateByClassname(className) NetProps.SetPropInt(weapon, STRING_NETPROP_ITEMDEF, itemID) NetProps.SetPropBool(weapon, "m_AttributeManager.m_Item.m_bInitialized", true) NetProps.SetPropBool(weapon, "m_bValidatedAttachedEntity", true) weapon.SetTeam(player.GetTeam()) weapon.DispatchSpawn() // remove existing weapon in same slot for (local i = 0; i < SLOT_COUNT; i++) { local heldWeapon = NetProps.GetPropEntityArray(player, "m_hMyWeapons", i) if (heldWeapon == null || heldWeapon.GetSlot() != weapon.GetSlot()) continue heldWeapon.Destroy() NetProps.SetPropEntityArray(player, "m_hMyWeapons", null, i) break } player.Weapon_Equip(weapon) player.Weapon_Switch(weapon) // fixes bug where if a player is firing/reloading, the player has to switch weapons again to equip the weapon EntFireByHandle(gamerules, "RunScriptCode", "activator.Weapon_Switch(caller)", 0.1, player, weapon) return weapon } SniperRailSetup = function(ent) { local primary = GetItemInSlot(ent, 0) local secondary = GetItemInSlot(ent, 1) ent.ValidateScriptScope() local scope = ent.GetScriptScope() EntFireByHandle(gamerules, "runscriptcode", "activator.Regenerate(true)", 0.15, ent, ent) ::SMGRailThink <- function() { //self is the weapon here local buttons = NetProps.GetPropInt(self, "m_nButtons") local buttons_changed = buttons_last ^ buttons local buttons_pressed = buttons_changed & buttons local buttons_released = buttons_changed & (~buttons) local eyepos_start = self.EyePosition() + self.EyeAngles().Forward() local eyepos_end = self.EyePosition() + self.EyeAngles().Forward() * 99999 local origin = self.GetOrigin() local custom_wep = GetItemInSlot(self, 0) local atk_time = NetProps.GetPropFloat(custom_wep, "m_flNextPrimaryAttack") //printl(atk_time) local index_primary = custom_wep.entindex() NetProps.SetPropInt(custom_wep, "m_iPrimaryAmmoType", 1); if (index_primary != ent_index) { // The player no longer has the weapon, stop thinking local scope = self.GetScriptScope() NetProps.SetPropString(self, "m_iszScriptThinkFunction", "") AddThinkToEnt(self, null) self.Regenerate(true) // need this because the player is given jarate return -1 } local cur_time = Time() // Get the current game time // Function to calculate dmg_bonus_value based on damage_charge_altfire function CalculateDmgBonusValue(damage_charge) { // Linear interpolation between 1.01 and 3.0 local min_bonus = 1.01 local max_bonus = 9.0 local max_charge = 200.0 local min_charge = 1.0 if (damage_charge >= 200) { return max_bonus; // Maximum bonus at 200 charge } else if (damage_charge <= 1) { return min_bonus; // Minimum bonus at charge of 1 } else { // Calculate the scaling factor based on the charge return min_bonus + (damage_charge - min_charge) / (max_charge - min_charge) * (max_bonus - min_bonus) } } // Dynamically calculate dmg_bonus_value based on the current charge local dmg_bonus_value = CalculateDmgBonusValue(damage_charge_altfire) // Attributes for alt fire local alt_fire_attributes = { "revolver use hit locations" : 1, "weapon spread bonus" : 0, "damage bonus HIDDEN" : dmg_bonus_value } ClientPrint(self, 4, "Rail Charge: " + damage_charge_altfire) if (damage_charge_altfire >= 200) { damage_charge_altfire = 200 self.AddCondEx(46, -1, null) } else { self.RemoveCondEx(46, true) } // // Check for func_regenerate or upgrade station // local secondary = GetItemInSlot(self, 1) // if (secondary != null && (secondary.GetClassname() == "tf_weapon_smg" || secondary.GetClassname() == "tf_weapon_charged_smg")) // { // StripWeapon(self, 1) // GiveWeapon(self, "tf_weapon_jar", 58) // EntFireByHandle(gamerules, "runscriptcode", "activator.Weapon_Switch(caller)", 0.1, self, custom_wep) // } // if (atk_time <= Time()) // { // printl("atk") // custom_wep.StopSound("Weapon_Revolver.Single") // } // Secondary fire logic if (buttons_pressed & SECONDARY_FIRE && damage_charge_altfire > 0 && self.GetActiveWeapon() == custom_wep) { local clip = custom_wep.Clip1() // Add attributes from alt_fire_attributes to the custom weapon foreach (attr, value in alt_fire_attributes) { custom_wep.AddAttribute(attr, value, -1) } // Set next attack timing and fire weapon NetProps.SetPropFloat(custom_wep, "m_flNextPrimaryAttack", 0) custom_wep.SetClip1(custom_wep.Clip1() + 1) custom_wep.PrimaryAttack() custom_wep.StopSound("Weapon_Revolver.Single") self.EmitSound("weapons/sniper_railgun_charged_shot_crit_02.wav"); local tracer_bullet = SpawnEntityFromTable("info_particle_system", { effect_name = "sniper_dxhr_rail_red", targetname = "bolt_zap_init_", origin = self.EyePosition(), // Ensure it starts from the player's eye position angles = self.EyeAngles() // Align the bullet with the player's view angles }); // Calculate the target position based on the player's eye angles local eye_angles = self.EyeAngles(); // Get player's eye angles local forward_vector = eye_angles.Forward(); // Forward direction based on eye angles // The distance for tracer_targ can be adjusted by changing the multiplier local tracer_targ_position = self.EyePosition() + forward_vector * 1000; // Example distance of 1000 units local tracer_targ = SpawnEntityFromTable("info_target", { targetname = "zap_targ_init", // Unique name for each target spawnflags = 1, origin = tracer_targ_position, // Use the calculated forward target position angles = Vector(0, 0, 0) // Angles for the target entity can stay at (0, 0, 0) }); // Set angles and control points for the tracer bullet tracer_bullet.SetAbsAngles(self.EyeAngles()); // Align the bullet with the player's view angles NetProps.SetPropEntityArray(tracer_bullet, "m_hControlPointEnts", tracer_targ, 0); // Set the target for the tracer bullet // Fire the tracer and handle cleanup tracer_bullet.AcceptInput( "Start", "", null, null) tracer_targ.AcceptInput("setparent", "!activator", tracer_bullet, tracer_targ); // Parent the target to the bullet // Set a delay to stop and clean up the tracer and target EntFireByHandle(tracer_bullet, "Stop", "", 0.3, null, null); // Stop the effect after 0.3 seconds EntFireByHandle(tracer_bullet, "Kill", "", 0.6, null, null); // Remove the bullet after 0.6 seconds EntFireByHandle(tracer_targ, "Kill", "", 0.6, null, null); // Remove the target after 0.6 seconds damage_charge_altfire = 0 // Set the time when the attributes were added time_last_altfire = cur_time } // Remove attributes 0.25 seconds later if (time_last_altfire != null && (time_last_altfire + 0.25) <= cur_time) { foreach (attr, value in alt_fire_attributes) { custom_wep.RemoveAttribute(attr) } time_last_altfire = null // Reset the time after removing the attributes } buttons_last = buttons; return -1; } // Initial setup scope.buttons_last <- 0 scope.damage_charge_altfire <- 0 scope.GiveWeapon <- GiveWeapon scope.time_last_altfire <- null // Store the time when alt-fire attributes were added scope.Damagable_Entities_List <- { "player" : 1, "obj_teleporter" : 1, "obj_sentrygun" : 1, "obj_dispenser" : 1, "tank_boss" : 1 } // Initialize the global attack tables list scope.PrintTable <- PrintTable scope.DoPrintTable <- DoPrintTable scope.GetItemInSlot <- GetItemInSlot scope.ent_index <- primary.entindex() scope.StripWeapon <- StripWeapon AddThinkToEnt(ent, "SMGRailThink") } OnGameEvent_player_spawn = function(params) { local player = GetPlayerFromUserID(params.userid) player.ValidateScriptScope() local playerscope = player.GetScriptScope() local primary = GetItemInSlot(player, 0) local weapon_id = NetProps.GetPropInt(primary, STRING_NETPROP_ITEMDEF) //printl(primary) } OnGameEvent_post_inventory_application = function(params) { local player = GetPlayerFromUserID(params.userid) player.ValidateScriptScope() local playerscope = player.GetScriptScope() local primary = GetItemInSlot(player, 0) //printl(primary) } OnScriptHook_OnTakeDamage = function(params) { local victim = params.const_entity local weapon = params.weapon local attacker = params.attacker local entity = params.inflictor local damage = params.damage local dmgtype = params.damage_type local dmg_special = params.damage_stats local weapon_id = NetProps.GetPropInt(weapon, STRING_NETPROP_ITEMDEF) attacker.ValidateScriptScope() local attacker_scope = attacker.GetScriptScope() local script_string = NetProps.GetPropString(attacker, "m_iszScriptThinkFunction") local Damagable_Entities_List = { "player" : 1, "obj_teleporter" : 1, "obj_sentrygun" : 1, "obj_dispenser" : 1, "tank_boss" : 1 } if (victim.GetClassname() in Damagable_Entities_List && script_string == "SMGRailThink" && CanBeHurt(victim) == false) { if (attacker_scope.damage_charge_altfire < 200) { if (victim.GetClassname() == "player" && victim.IsMiniBoss() || victim.GetClassname() == "tank_boss") { attacker_scope.damage_charge_altfire = attacker_scope.damage_charge_altfire + 1 } else { attacker_scope.damage_charge_altfire = attacker_scope.damage_charge_altfire + 5 } } } } }; __CollectGameEventCallbacks(RailgunSMG)