Initial commit - RefoselBots
This commit is contained in:
29
README.md
Normal file
29
README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# RefoselBots
|
||||
|
||||
Bot system designed specifically for RefoselTeamWork gamemodes.
|
||||
|
||||
## Features
|
||||
|
||||
- Team-based AI bots for Team Deathmatch
|
||||
- NextBot navigation system
|
||||
- Quota system (auto-balance bot count)
|
||||
- VJ Base weapon support
|
||||
|
||||
## Console Commands
|
||||
|
||||
- `refoselbots_add [amount]` - Add bots
|
||||
- `refoselbots_kick [name/all]` - Kick bots
|
||||
- `refoselbots_quota [number]` - Auto-balance bots
|
||||
|
||||
## Installation
|
||||
|
||||
1. Copy `refoselbots` folder to `garrysmod/addons`
|
||||
2. Ensure navmesh is generated on your map (`nav_generate`)
|
||||
3. Add bots with `refoselbots_add` or set quota
|
||||
|
||||
---
|
||||
|
||||
## Credits
|
||||
|
||||
### Original Code
|
||||
**LeadBot** - https://github.com/LeadKiller/leadbot
|
||||
15
lua/autorun/client/refoselbots.lua
Normal file
15
lua/autorun/client/refoselbots.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
--if game.SinglePlayer() or SERVER then return end
|
||||
|
||||
-- Modules
|
||||
|
||||
local _, dir = file.Find("refoselbots/modules/*", "LUA")
|
||||
|
||||
for k, v in pairs(dir) do
|
||||
local f = table.Add(file.Find("refoselbots/modules/" .. v .. "/cl_*.lua", "LUA"), file.Find("refoselbots/modules/" .. v .. "/sh_*.lua", "LUA"))
|
||||
|
||||
for i, o in pairs(f) do
|
||||
local file = "refoselbots/modules/" .. v .. "/" .. o
|
||||
|
||||
include(file)
|
||||
end
|
||||
end
|
||||
59
lua/autorun/server/refoselbots.lua
Normal file
59
lua/autorun/server/refoselbots.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
--if game.SinglePlayer() or CLIENT then return end
|
||||
|
||||
LeadBot = {}
|
||||
LeadBot.NoNavMesh = {}
|
||||
LeadBot.Models = {} -- Models, leave as {} if random is desired
|
||||
|
||||
--[[-----
|
||||
|
||||
CONFIG START CONFIG START
|
||||
CONFIG START CONFIG START
|
||||
CONFIG START CONFIG START
|
||||
|
||||
--]]-----
|
||||
|
||||
-- Name Prefix
|
||||
|
||||
LeadBot.Prefix = ""
|
||||
|
||||
--[[-----
|
||||
|
||||
CONFIG END CONFIG END
|
||||
CONFIG END CONFIG END
|
||||
CONFIG END CONFIG END
|
||||
|
||||
--]]-----
|
||||
|
||||
include("refoselbots/base.lua")
|
||||
|
||||
-- Modules
|
||||
|
||||
local _, dir = file.Find("refoselbots/modules/*", "LUA")
|
||||
|
||||
for k, v in pairs(dir) do
|
||||
local f = table.Add(file.Find("refoselbots/modules/" .. v .. "/sv_*.lua", "LUA"), file.Find("refoselbots/modules/" .. v .. "/sh_*.lua", "LUA"))
|
||||
f = table.Add(f, file.Find("refoselbots/modules/" .. v .. "/cl_*.lua", "LUA"))
|
||||
for i, o in pairs(f) do
|
||||
local file = "refoselbots/modules/" .. v .. "/" .. o
|
||||
|
||||
if string.StartWith(o, "cl_") then
|
||||
AddCSLuaFile(file)
|
||||
else
|
||||
include(file)
|
||||
if string.StartWith(o, "sh_") then
|
||||
AddCSLuaFile(file)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Configs
|
||||
|
||||
local map = game.GetMap()
|
||||
local gamemode = engine.ActiveGamemode()
|
||||
|
||||
if file.Find("refoselbots/gamemodes/" .. map .. ".lua", "LUA")[1] then
|
||||
include("refoselbots/gamemodes/" .. map .. ".lua")
|
||||
elseif file.Find("refoselbots/gamemodes/" .. gamemode .. ".lua", "LUA")[1] then
|
||||
include("refoselbots/gamemodes/" .. gamemode .. ".lua")
|
||||
end
|
||||
125
lua/entities/refoselbots_navigator.lua
Normal file
125
lua/entities/refoselbots_navigator.lua
Normal file
@@ -0,0 +1,125 @@
|
||||
if SERVER then AddCSLuaFile() end
|
||||
|
||||
ENT.Base = "base_nextbot"
|
||||
ENT.Type = "nextbot"
|
||||
|
||||
function ENT:Initialize()
|
||||
if CLIENT then return end
|
||||
|
||||
self:SetModel("models/player.mdl")
|
||||
self:SetNoDraw(!GetConVar("developer"):GetBool())
|
||||
self:SetSolid(SOLID_NONE)
|
||||
|
||||
local fov_convar = GetConVar("refoselbots_fov")
|
||||
|
||||
self:SetFOV((fov_convar:GetBool() and math.Clamp(fov_convar:GetInt(), 75, 100)) or 90)
|
||||
self.PosGen = nil
|
||||
self.NextJump = -1
|
||||
self.NextDuck = 0
|
||||
self.cur_segment = 2
|
||||
self.Target = nil
|
||||
self.LastSegmented = 0
|
||||
self.ForgetTarget = 0
|
||||
self.NextCenter = 0
|
||||
self.LookAt = Angle(0, 0, 0)
|
||||
self.LookAtTime = 0
|
||||
self.goalPos = Vector(0, 0, 0)
|
||||
self.strafeAngle = 0
|
||||
self.nextStuckJump = 0
|
||||
|
||||
if RefoselBots.AddControllerOverride then
|
||||
RefoselBots.AddControllerOverride(self)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ChasePos()
|
||||
self.P = Path("Follow")
|
||||
self.P:SetMinLookAheadDistance(10)
|
||||
self.P:SetGoalTolerance(20)
|
||||
self.P:Compute(self, self.PosGen)
|
||||
|
||||
if !self.P:IsValid() then return end
|
||||
|
||||
while self.P:IsValid() do
|
||||
if self.PosGen then
|
||||
self.P:Compute(self, self.PosGen)
|
||||
self.cur_segment = 2
|
||||
end
|
||||
|
||||
coroutine.wait(1)
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnInjured()
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:OnKilled()
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:IsNPC()
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:Health()
|
||||
return nil
|
||||
end
|
||||
|
||||
-- remade this in lua so we can finally ignore the controller's bot
|
||||
-- for some reason it's not really possible to overwrite IsAbleToSee
|
||||
local function PointWithinViewAngle(pos, targetpos, lookdir, fov)
|
||||
pos = targetpos - pos
|
||||
local diff = lookdir:Dot(pos)
|
||||
if diff < 0 then return false end
|
||||
local len = pos:LengthSqr()
|
||||
return diff * diff > len * fov * fov
|
||||
end
|
||||
|
||||
function ENT:InFOV(pos, fov)
|
||||
local owner = self:GetOwner()
|
||||
|
||||
if IsEntity(pos) then
|
||||
-- we must check eyepos and worldspacecenter
|
||||
-- maybe in the future add more points
|
||||
|
||||
if PointWithinViewAngle(owner:EyePos(), pos:WorldSpaceCenter(), owner:GetAimVector(), fov) then
|
||||
return true
|
||||
end
|
||||
|
||||
return PointWithinViewAngle(owner:EyePos(), pos:EyePos(), owner:GetAimVector(), fov)
|
||||
else
|
||||
return PointWithinViewAngle(owner:EyePos(), pos, owner:GetAimVector(), fov)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:CanSee(ply, fov)
|
||||
if ply:GetPos():DistToSqr(self:GetPos()) > self:GetMaxVisionRange() * self:GetMaxVisionRange() then
|
||||
return false
|
||||
end
|
||||
|
||||
-- TODO: check fog farz and compare with distance
|
||||
|
||||
-- half fov or something
|
||||
-- probably should move this to a variable
|
||||
fov = fov or true
|
||||
|
||||
if fov and !self:InFOV(ply, math.cos(0.5 * (self:GetFOV() or 90) * math.pi / 180)) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- TODO: we really should check worldspacecenter too
|
||||
local owner = self:GetOwner()
|
||||
return util.QuickTrace(owner:EyePos(), ply:EyePos() - owner:EyePos(), {owner, self}).Entity == ply
|
||||
end
|
||||
|
||||
function ENT:RunBehaviour()
|
||||
while (true) do
|
||||
if self.PosGen then
|
||||
self:ChasePos({})
|
||||
end
|
||||
|
||||
coroutine.yield()
|
||||
end
|
||||
end
|
||||
632
lua/refoselbots/base.lua
Normal file
632
lua/refoselbots/base.lua
Normal file
@@ -0,0 +1,632 @@
|
||||
RefoselBots.RespawnAllowed = true -- allows bots to respawn automatically when dead
|
||||
RefoselBots.PlayerColor = true -- disable this to get the default gmod style players
|
||||
RefoselBots.NoNavMesh = false -- disable the nav mesh check
|
||||
RefoselBots.TeamPlay = false -- don't hurt players on the bots team
|
||||
RefoselBots.LerpAim = true -- interpolate aim (smooth aim)
|
||||
RefoselBots.AFKBotOverride = false -- allows for gamemodes such as Dogfight which use IsBot() to pass real humans as bots
|
||||
RefoselBots.SuicideAFK = false -- kill the player when entering/exiting afk
|
||||
RefoselBots.NoFlashlight = false -- disable flashlight being enabled in dark areas
|
||||
RefoselBots.Strategies = 1 -- how many strategies can the bot pick from
|
||||
|
||||
--[[ COMMANDS ]]--
|
||||
|
||||
concommand.Add("refoselbots_add", function(ply, _, args) if IsValid(ply) and !ply:IsSuperAdmin() then return end local amount = 1 if tonumber(args[1]) then amount = tonumber(args[1]) end for i = 1, amount do timer.Simple(i * 0.1, function() RefoselBots.AddBot() end) end end, nil, "Adds a RefoselBots")
|
||||
concommand.Add("refoselbots_kick", function(ply, _, args) if !args[1] or IsValid(ply) and !ply:IsSuperAdmin() then return end if args[1] ~= "all" then for k, v in pairs(player.GetBots()) do if string.find(v:GetName(), args[1]) then v:Kick() return end end else for k, v in pairs(player.GetBots()) do v:Kick() end end end, nil, "Kicks RefoselBotss (all is avaliable!)")
|
||||
CreateConVar("refoselbots_strategy", "1", {FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Enables the strategy system for newly created bots.")
|
||||
CreateConVar("refoselbots_names", "", {FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Bot names, seperated by commas.")
|
||||
CreateConVar("refoselbots_models", "", {FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Bot models, seperated by commas.")
|
||||
CreateConVar("refoselbots_name_prefix", "", {FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Bot name prefix")
|
||||
CreateConVar("refoselbots_fov", "0", {FCVAR_ARCHIVE, FCVAR_NOTIFY}, "RefoselBots FOV\nSet to 0 to use the preset FOV.")
|
||||
|
||||
--[[ FUNCTIONS ]]--
|
||||
|
||||
local name_Default = {
|
||||
alyx = "Alyx Vance",
|
||||
kleiner = "Isaac Kleiner",
|
||||
breen = "Dr. Wallace Breen",
|
||||
gman = "The G-Man",
|
||||
odessa = "Odessa Cubbage",
|
||||
eli = "Eli Vance",
|
||||
monk = "Father Grigori",
|
||||
mossman = "Judith Mossman",
|
||||
mossmanarctic = "Judith Mossman",
|
||||
barney = "Barney Calhoun",
|
||||
|
||||
|
||||
dod_american = "American Soldier",
|
||||
dod_german = "German Soldier",
|
||||
|
||||
css_swat = "GIGN",
|
||||
css_leet = "Elite Crew",
|
||||
css_arctic = "Artic Avengers",
|
||||
css_urban = "SEAL Team Six",
|
||||
css_riot = "GSG-9",
|
||||
css_gasmask = "SAS",
|
||||
css_phoenix = "Phoenix Connexion",
|
||||
css_guerilla = "Guerilla Warfare",
|
||||
|
||||
hostage01 = "Art",
|
||||
hostage02 = "Sandro",
|
||||
hostage03 = "Vance",
|
||||
hostage04 = "Cohrt",
|
||||
|
||||
police = "Civil Protection",
|
||||
policefem = "Civil Protection",
|
||||
|
||||
chell = "Chell",
|
||||
|
||||
combine = "Combine Soldier",
|
||||
combineprison = "Combine Prison Guard",
|
||||
combineelite = "Elite Combine Soldier",
|
||||
stripped = "Stripped Combine Soldier",
|
||||
|
||||
zombie = "Zombie",
|
||||
zombiefast = "Fast Zombie",
|
||||
zombine = "Zombine",
|
||||
corpse = "Corpse",
|
||||
charple = "Charple",
|
||||
skeleton = "Skeleton",
|
||||
|
||||
male01 = "Van",
|
||||
male02 = "Ted",
|
||||
male03 = "Joe",
|
||||
male04 = "Eric",
|
||||
male05 = "Art",
|
||||
male06 = "Sandro",
|
||||
male07 = "Mike",
|
||||
male08 = "Vance",
|
||||
male09 = "Erdin",
|
||||
male10 = "Van",
|
||||
male11 = "Ted",
|
||||
male12 = "Joe",
|
||||
male13 = "Eric",
|
||||
male14 = "Art",
|
||||
male15 = "Sandro",
|
||||
male16 = "Mike",
|
||||
male17 = "Vance",
|
||||
male18 = "Erdin",
|
||||
female01 = "Joey",
|
||||
female02 = "Kanisha",
|
||||
female03 = "Kim",
|
||||
female04 = "Chau",
|
||||
female05 = "Naomi",
|
||||
female06 = "Lakeetra",
|
||||
female07 = "Joey",
|
||||
female08 = "Kanisha",
|
||||
female09 = "Kim",
|
||||
female10 = "Chau",
|
||||
female11 = "Naomi",
|
||||
female12 = "Lakeetra",
|
||||
|
||||
medic01 = "Van",
|
||||
medic02 = "Ted",
|
||||
medic03 = "Joe",
|
||||
medic04 = "Eric",
|
||||
medic05 = "Art",
|
||||
medic06 = "Sandro",
|
||||
medic07 = "Mike",
|
||||
medic08 = "Vance",
|
||||
medic09 = "Erdin",
|
||||
medic10 = "Joey",
|
||||
medic11 = "Kanisha",
|
||||
medic12 = "Kim",
|
||||
medic13 = "Chau",
|
||||
medic14 = "Naomi",
|
||||
medic15 = "Lakeetra",
|
||||
|
||||
refugee01 = "Ted",
|
||||
refugee02 = "Eric",
|
||||
refugee03 = "Sandro",
|
||||
refugee04 = "Vance",
|
||||
}
|
||||
|
||||
function RefoselBots.AddBot()
|
||||
if !FindMetaTable("NextBot").GetFOV then
|
||||
ErrorNoHalt("You must be using the dev version of Garry's mod!\nhttps://wiki.facepunch.com/gmod/Dev_Branch\n")
|
||||
return
|
||||
end
|
||||
|
||||
if !navmesh.IsLoaded() and !RefoselBots.NoNavMesh then
|
||||
ErrorNoHalt("There is no navmesh! Generate one using \"nav_generate\"!\n")
|
||||
return
|
||||
end
|
||||
|
||||
if player.GetCount() == game.MaxPlayers() then
|
||||
MsgN("[RefoselBots] Player limit reached!")
|
||||
return
|
||||
end
|
||||
|
||||
local original_name
|
||||
local generated = "Leadbot #" .. #player.GetBots() + 1
|
||||
local model = ""
|
||||
local color = Vector(-1, -1, -1)
|
||||
local weaponcolor = Vector(0.30, 1.80, 2.10)
|
||||
local strategy = 0
|
||||
|
||||
if GetConVar("refoselbots_names"):GetString() ~= "" then
|
||||
generated = table.Random(string.Split(GetConVar("refoselbots_names"):GetString(), ","))
|
||||
elseif GetConVar("refoselbots_models"):GetString() == "" then
|
||||
local name, _ = table.Random(player_manager.AllValidModels())
|
||||
local translate = player_manager.TranslateToPlayerModelName(name)
|
||||
name = translate
|
||||
|
||||
for _, ply in pairs(player.GetBots()) do
|
||||
if ply.OriginalName == name or string.lower(ply:Nick()) == name or name_Default[name] and ply:Nick() == name_Default[name] then
|
||||
name = ""
|
||||
end
|
||||
end
|
||||
|
||||
if name == "" then
|
||||
local i = 0
|
||||
while name == "" do
|
||||
i = i + 1
|
||||
local str = player_manager.TranslateToPlayerModelName(table.Random(player_manager.AllValidModels()))
|
||||
for _, ply in pairs(player.GetBots()) do
|
||||
if ply.OriginalName == str or string.lower(ply:Nick()) == str or name_Default[str] and ply:Nick() == name_Default[str] then
|
||||
str = ""
|
||||
end
|
||||
end
|
||||
|
||||
if str == "" and i < #player_manager.AllValidModels() then continue end
|
||||
name = str
|
||||
end
|
||||
end
|
||||
|
||||
original_name = name
|
||||
model = name
|
||||
name = string.lower(name)
|
||||
name = name_Default[name] or name
|
||||
|
||||
local name_Generated = string.Split(name, "/")
|
||||
name_Generated = name_Generated[#name_Generated]
|
||||
name_Generated = string.Split(name_Generated, " ")
|
||||
|
||||
for i, namestr in pairs(name_Generated) do
|
||||
name_Generated[i] = string.upper(string.sub(namestr, 1, 1)) .. string.sub(namestr, 2)
|
||||
end
|
||||
|
||||
name_Generated = table.concat(name_Generated, " ")
|
||||
generated = name_Generated
|
||||
end
|
||||
|
||||
if RefoselBots.PlayerColor == "default" then
|
||||
generated = "Kleiner"
|
||||
end
|
||||
|
||||
generated = GetConVar("refoselbots_name_prefix"):GetString() .. generated
|
||||
|
||||
local name = RefoselBots.Prefix .. generated
|
||||
local bot = player.CreateNextBot(name)
|
||||
|
||||
if !IsValid(bot) then
|
||||
MsgN("[RefoselBots] Unable to create bot!")
|
||||
return
|
||||
end
|
||||
|
||||
if GetConVar("refoselbots_strategy"):GetBool() then
|
||||
strategy = math.random(0, RefoselBots.Strategies)
|
||||
end
|
||||
|
||||
if RefoselBots.PlayerColor ~= "default" then
|
||||
if model == "" then
|
||||
if GetConVar("refoselbots_models"):GetString() ~= "" then
|
||||
model = table.Random(string.Split(GetConVar("refoselbots_models"):GetString(), ","))
|
||||
else
|
||||
model = player_manager.TranslateToPlayerModelName(table.Random(player_manager.AllValidModels()))
|
||||
end
|
||||
end
|
||||
|
||||
if color == Vector(-1, -1, -1) then
|
||||
local botcolor = ColorRand()
|
||||
local botweaponcolor = ColorRand()
|
||||
color = Vector(botcolor.r / 255, botcolor.g / 255, botcolor.b / 255)
|
||||
weaponcolor = Vector(botweaponcolor.r / 255, botweaponcolor.g / 255, botweaponcolor.b / 255)
|
||||
end
|
||||
else
|
||||
model = "kleiner"
|
||||
color = Vector(0.24, 0.34, 0.41)
|
||||
end
|
||||
|
||||
bot.RefoselBots_Config = {model, color, weaponcolor, strategy}
|
||||
|
||||
-- for legacy purposes, will be removed soon when gamemodes are updated
|
||||
bot.BotStrategy = strategy
|
||||
bot.OriginalName = original_name
|
||||
bot.ControllerBot = ents.Create("refoselbots_navigator")
|
||||
bot.ControllerBot:Spawn()
|
||||
bot.ControllerBot:SetOwner(bot)
|
||||
bot.RefoselBots = true
|
||||
RefoselBots.AddBotOverride(bot)
|
||||
RefoselBots.AddBotControllerOverride(bot, bot.ControllerBot)
|
||||
MsgN("[RefoselBots] Bot " .. name .. " with strategy " .. bot.BotStrategy .. " added!")
|
||||
end
|
||||
|
||||
--[[ DEFAULT DM AI ]]--
|
||||
|
||||
function RefoselBots.AddBotOverride(bot)
|
||||
if math.random(2) == 1 then
|
||||
timer.Simple(math.random(1, 4), function()
|
||||
RefoselBots.TalkToMe(bot, "join")
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function RefoselBots.AddBotControllerOverride(bot, controller)
|
||||
end
|
||||
|
||||
function RefoselBots.PlayerSpawn(bot)
|
||||
end
|
||||
|
||||
function RefoselBots.Think()
|
||||
for _, bot in pairs(player.GetBots()) do
|
||||
if bot:IsLBot() then
|
||||
if RefoselBots.RespawnAllowed and bot.NextSpawnTime and !bot:Alive() and bot.NextSpawnTime < CurTime() then
|
||||
bot:Spawn()
|
||||
return
|
||||
end
|
||||
|
||||
local wep = bot:GetActiveWeapon()
|
||||
if IsValid(wep) then
|
||||
local ammoty = wep:GetPrimaryAmmoType() or wep.Primary.Ammo
|
||||
bot:SetAmmo(999, ammoty)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function RefoselBots.PostPlayerDeath(bot)
|
||||
end
|
||||
|
||||
function RefoselBots.PlayerHurt(ply, bot, hp, dmg)
|
||||
if bot:IsPlayer() then
|
||||
if hp <= dmg and math.random(3) == 1 and bot:IsLBot() then
|
||||
RefoselBots.TalkToMe(bot, "taunt")
|
||||
end
|
||||
|
||||
local controller = ply:GetController()
|
||||
|
||||
controller.LookAtTime = CurTime() + 2
|
||||
controller.LookAt = ((bot:GetPos() + VectorRand() * 128) - ply:GetPos()):Angle()
|
||||
end
|
||||
end
|
||||
|
||||
function RefoselBots.StartCommand(bot, cmd)
|
||||
local buttons = IN_SPEED
|
||||
local botWeapon = bot:GetActiveWeapon()
|
||||
local controller = bot.ControllerBot
|
||||
local target = controller.Target
|
||||
|
||||
if !IsValid(controller) then return end
|
||||
|
||||
if RefoselBots.NoSprint then
|
||||
buttons = 0
|
||||
end
|
||||
|
||||
if IsValid(botWeapon) and (botWeapon:Clip1() == 0 or !IsValid(target) and botWeapon:Clip1() <= botWeapon:GetMaxClip1() / 2) then
|
||||
buttons = buttons + IN_RELOAD
|
||||
end
|
||||
|
||||
if IsValid(target) and math.random(2) == 1 then
|
||||
buttons = buttons + IN_ATTACK
|
||||
end
|
||||
|
||||
if bot:GetMoveType() == MOVETYPE_LADDER then
|
||||
local pos = controller.goalPos
|
||||
local ang = ((pos + bot:GetCurrentViewOffset()) - bot:GetShootPos()):Angle()
|
||||
|
||||
if pos.z > controller:GetPos().z then
|
||||
controller.LookAt = Angle(-30, ang.y, 0)
|
||||
else
|
||||
controller.LookAt = Angle(30, ang.y, 0)
|
||||
end
|
||||
|
||||
controller.LookAtTime = CurTime() + 0.1
|
||||
controller.NextJump = -1
|
||||
buttons = buttons + IN_FORWARD
|
||||
end
|
||||
|
||||
if controller.NextDuck > CurTime() then
|
||||
buttons = buttons + IN_DUCK
|
||||
elseif controller.NextJump == 0 then
|
||||
controller.NextJump = CurTime() + 1
|
||||
buttons = buttons + IN_JUMP
|
||||
end
|
||||
|
||||
if !bot:IsOnGround() and controller.NextJump > CurTime() then
|
||||
buttons = buttons + IN_DUCK
|
||||
end
|
||||
|
||||
bot:SelectWeapon((IsValid(controller.Target) and controller.Target:GetPos():DistToSqr(controller:GetPos()) < 129000 and "weapon_shotgun") or "weapon_smg1")
|
||||
cmd:ClearButtons()
|
||||
cmd:ClearMovement()
|
||||
cmd:SetButtons(buttons)
|
||||
end
|
||||
|
||||
function RefoselBots.PlayerMove(bot, cmd, mv)
|
||||
local controller = bot.ControllerBot
|
||||
|
||||
if !IsValid(controller) then
|
||||
bot.ControllerBot = ents.Create("refoselbots_navigator")
|
||||
bot.ControllerBot:Spawn()
|
||||
bot.ControllerBot:SetOwner(bot)
|
||||
controller = bot.ControllerBot
|
||||
end
|
||||
|
||||
--[[local min, max = controller:GetModelBounds()
|
||||
debugoverlay.Box(controller:GetPos(), min, max, 0.1, Color(255, 0, 0, 0), true)]]
|
||||
|
||||
-- force a recompute
|
||||
if controller.PosGen and controller.P and controller.TPos ~= controller.PosGen then
|
||||
controller.TPos = controller.PosGen
|
||||
controller.P:Compute(controller, controller.PosGen)
|
||||
end
|
||||
|
||||
if controller:GetPos() ~= bot:GetPos() then
|
||||
controller:SetPos(bot:GetPos())
|
||||
end
|
||||
|
||||
if controller:GetAngles() ~= bot:EyeAngles() then
|
||||
controller:SetAngles(bot:EyeAngles())
|
||||
end
|
||||
|
||||
mv:SetForwardSpeed(1200)
|
||||
|
||||
if (bot.NextSpawnTime and bot.NextSpawnTime + 1 > CurTime()) or !IsValid(controller.Target) or controller.ForgetTarget < CurTime() or controller.Target:Health() < 1 then
|
||||
controller.Target = nil
|
||||
end
|
||||
|
||||
if !IsValid(controller.Target) then
|
||||
for _, ply in ipairs(player.GetAll()) do
|
||||
if ply ~= bot and ((ply:IsPlayer() and (!RefoselBots.TeamPlay or (RefoselBots.TeamPlay and (ply:Team() ~= bot:Team())))) or ply:IsNPC()) and ply:GetPos():DistToSqr(bot:GetPos()) < 2250000 then
|
||||
--[[local targetpos = ply:EyePos() - Vector(0, 0, 10)
|
||||
local trace = util.TraceLine({
|
||||
start = bot:GetShootPos(),
|
||||
endpos = targetpos,
|
||||
filter = function(ent) return ent == ply end
|
||||
})]]
|
||||
|
||||
if ply:Alive() and controller:CanSee(ply) then
|
||||
controller.Target = ply
|
||||
controller.ForgetTarget = CurTime() + 2
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif controller.ForgetTarget < CurTime() and controller:CanSee(controller.Target) then
|
||||
controller.ForgetTarget = CurTime() + 2
|
||||
end
|
||||
|
||||
local dt = util.QuickTrace(bot:EyePos(), bot:GetForward() * 45, bot)
|
||||
|
||||
if IsValid(dt.Entity) and dt.Entity:GetClass() == "prop_door_rotating" then
|
||||
dt.Entity:Fire("OpenAwayFrom", bot, 0)
|
||||
end
|
||||
|
||||
if !IsValid(controller.Target) and (!controller.PosGen or bot:GetPos():DistToSqr(controller.PosGen) < 1000 or controller.LastSegmented < CurTime()) then
|
||||
-- find a random spot on the map, and in 10 seconds do it again!
|
||||
controller.PosGen = controller:FindSpot("random", {radius = 12500})
|
||||
controller.LastSegmented = CurTime() + 10
|
||||
elseif IsValid(controller.Target) then
|
||||
-- move to our target
|
||||
local distance = controller.Target:GetPos():DistToSqr(bot:GetPos())
|
||||
controller.PosGen = controller.Target:GetPos()
|
||||
|
||||
-- back up if the target is really close
|
||||
-- TODO: find a random spot rather than trying to back up into what could just be a wall
|
||||
-- something like controller.PosGen = controller:FindSpot("random", {pos = bot:GetPos() - bot:GetForward() * 350, radius = 1000})?
|
||||
if distance <= 90000 then
|
||||
mv:SetForwardSpeed(-1200)
|
||||
end
|
||||
end
|
||||
|
||||
-- movement also has a similar issue, but it's more severe...
|
||||
if !controller.P then
|
||||
return
|
||||
end
|
||||
|
||||
local segments = controller.P:GetAllSegments()
|
||||
|
||||
if !segments then return end
|
||||
|
||||
local cur_segment = controller.cur_segment
|
||||
local curgoal = segments[cur_segment]
|
||||
|
||||
-- got nowhere to go, why keep moving?
|
||||
if !curgoal then
|
||||
mv:SetForwardSpeed(0)
|
||||
return
|
||||
end
|
||||
|
||||
-- think every step of the way!
|
||||
if segments[cur_segment + 1] and Vector(bot:GetPos().x, bot:GetPos().y, 0):DistToSqr(Vector(curgoal.pos.x, curgoal.pos.y)) < 100 then
|
||||
controller.cur_segment = controller.cur_segment + 1
|
||||
curgoal = segments[controller.cur_segment]
|
||||
end
|
||||
|
||||
local goalpos = curgoal.pos
|
||||
|
||||
-- waaay too slow during gamplay
|
||||
--[[if bot:GetVelocity():Length2DSqr() <= 225 and controller.NextCenter == 0 and controller.NextCenter < CurTime() then
|
||||
controller.NextCenter = CurTime() + math.Rand(0.5, 0.65)
|
||||
end
|
||||
|
||||
if controller.NextCenter ~= 0 and controller.NextCenter < CurTime() then
|
||||
if bot:GetVelocity():Length2DSqr() <= 225 then
|
||||
controller.strafeAngle = ((controller.strafeAngle == 1 and 2) or 1)
|
||||
end
|
||||
|
||||
controller.NextCenter = 0
|
||||
end]]
|
||||
|
||||
if bot:GetVelocity():Length2DSqr() <= 225 then
|
||||
if controller.NextCenter < CurTime() then
|
||||
controller.strafeAngle = ((controller.strafeAngle == 1 and 2) or 1)
|
||||
controller.NextCenter = CurTime() + math.Rand(0.3, 0.65)
|
||||
elseif controller.nextStuckJump < CurTime() then
|
||||
if !bot:Crouching() then
|
||||
controller.NextJump = 0
|
||||
end
|
||||
controller.nextStuckJump = CurTime() + math.Rand(1, 2)
|
||||
end
|
||||
end
|
||||
|
||||
if controller.NextCenter > CurTime() then
|
||||
if controller.strafeAngle == 1 then
|
||||
mv:SetSideSpeed(1500)
|
||||
elseif controller.strafeAngle == 2 then
|
||||
mv:SetSideSpeed(-1500)
|
||||
else
|
||||
mv:SetForwardSpeed(-1500)
|
||||
end
|
||||
end
|
||||
|
||||
-- jump
|
||||
if controller.NextJump ~= 0 and curgoal.type > 1 and controller.NextJump < CurTime() then
|
||||
controller.NextJump = 0
|
||||
end
|
||||
|
||||
-- duck
|
||||
if curgoal.area:GetAttributes() == NAV_MESH_CROUCH then
|
||||
controller.NextDuck = CurTime() + 0.1
|
||||
end
|
||||
|
||||
controller.goalPos = goalpos
|
||||
|
||||
if GetConVar("developer"):GetBool() then
|
||||
controller.P:Draw()
|
||||
end
|
||||
|
||||
-- eyesight
|
||||
local lerp = FrameTime() * math.random(8, 10)
|
||||
local lerpc = FrameTime() * 8
|
||||
|
||||
if !RefoselBots.LerpAim then
|
||||
lerp = 1
|
||||
lerpc = 1
|
||||
end
|
||||
|
||||
local mva = ((goalpos + bot:GetCurrentViewOffset()) - bot:GetShootPos()):Angle()
|
||||
|
||||
mv:SetMoveAngles(mva)
|
||||
|
||||
if IsValid(controller.Target) then
|
||||
bot:SetEyeAngles(LerpAngle(lerp, bot:EyeAngles(), (controller.Target:EyePos() - bot:GetShootPos()):Angle()))
|
||||
return
|
||||
else
|
||||
if controller.LookAtTime > CurTime() then
|
||||
local ang = LerpAngle(lerpc, bot:EyeAngles(), controller.LookAt)
|
||||
bot:SetEyeAngles(Angle(ang.p, ang.y, 0))
|
||||
else
|
||||
local ang = LerpAngle(lerpc, bot:EyeAngles(), mva)
|
||||
bot:SetEyeAngles(Angle(ang.p, ang.y, 0))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[ HOOKS ]]--
|
||||
|
||||
hook.Add("PlayerDisconnected", "RefoselBots_Disconnect", function(bot)
|
||||
if IsValid(bot.ControllerBot) then
|
||||
bot.ControllerBot:Remove()
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("SetupMove", "RefoselBots_Control", function(bot, mv, cmd)
|
||||
if bot:IsLBot() then
|
||||
RefoselBots.PlayerMove(bot, cmd, mv)
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("StartCommand", "RefoselBots_Control", function(bot, cmd)
|
||||
if bot:IsLBot() then
|
||||
RefoselBots.StartCommand(bot, cmd)
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("PostPlayerDeath", "RefoselBots_Death", function(bot)
|
||||
if bot:IsLBot() then
|
||||
RefoselBots.PostPlayerDeath(bot)
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("EntityTakeDamage", "RefoselBots_Hurt", function(ply, dmgi)
|
||||
local bot = dmgi:GetAttacker()
|
||||
local hp = ply:Health()
|
||||
local dmg = dmgi:GetDamage()
|
||||
|
||||
if IsValid(ply) and ply:IsPlayer() and ply:IsLBot() then
|
||||
RefoselBots.PlayerHurt(ply, bot, hp, dmg)
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("Think", "RefoselBots_Think", function()
|
||||
RefoselBots.Think()
|
||||
end)
|
||||
|
||||
hook.Add("PlayerSpawn", "RefoselBots_Spawn", function(bot)
|
||||
if bot:IsLBot() then
|
||||
RefoselBots.PlayerSpawn(bot)
|
||||
end
|
||||
end)
|
||||
|
||||
--[[ META ]]--
|
||||
|
||||
local player_meta = FindMetaTable("Player")
|
||||
local oldInfo = player_meta.GetInfo
|
||||
|
||||
function player_meta.IsLBot(self, realbotsonly)
|
||||
if realbotsonly == true then
|
||||
return self.RefoselBots and self:IsBot() or false
|
||||
end
|
||||
|
||||
return self.RefoselBots or false
|
||||
end
|
||||
|
||||
function player_meta.LBGetStrategy(self)
|
||||
if self.RefoselBots_Config then
|
||||
return self.RefoselBots_Config[4]
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function player_meta.LBGetModel(self)
|
||||
if self.RefoselBots_Config then
|
||||
return self.RefoselBots_Config[1]
|
||||
else
|
||||
return "kleiner"
|
||||
end
|
||||
end
|
||||
|
||||
function player_meta.LBGetColor(self, weapon)
|
||||
if self.RefoselBots_Config then
|
||||
if weapon == true then
|
||||
return self.RefoselBots_Config[3]
|
||||
else
|
||||
return self.RefoselBots_Config[2]
|
||||
end
|
||||
else
|
||||
return Vector(0, 0, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function player_meta.GetInfo(self, convar)
|
||||
if self:IsBot() and self:IsLBot() then
|
||||
if convar == "cl_playermodel" then
|
||||
return self:LBGetModel() --self.RefoselBots_Config[1]
|
||||
elseif convar == "cl_playercolor" then
|
||||
return self:LBGetColor() --self.RefoselBots_Config[2]
|
||||
elseif convar == "cl_weaponcolor" then
|
||||
return self:LBGetColor(true) --self.RefoselBots_Config[3]
|
||||
else
|
||||
return ""
|
||||
end
|
||||
else
|
||||
return oldInfo(self, convar)
|
||||
end
|
||||
end
|
||||
|
||||
function player_meta.GetController(self)
|
||||
if self:IsLBot() then
|
||||
return self.ControllerBot
|
||||
end
|
||||
end
|
||||
6
lua/refoselbots/gamemodes/cod_custom.lua
Normal file
6
lua/refoselbots/gamemodes/cod_custom.lua
Normal file
@@ -0,0 +1,6 @@
|
||||
LeadBot.RespawnAllowed = true
|
||||
LeadBot.SetModel = false
|
||||
LeadBot.Gamemode = "cod_custom"
|
||||
LeadBot.TeamPlay = true
|
||||
LeadBot.LerpAim = true
|
||||
LeadBot.NoFlashlight = true
|
||||
139
lua/refoselbots/modules/afk/cl_afk.lua
Normal file
139
lua/refoselbots/modules/afk/cl_afk.lua
Normal file
@@ -0,0 +1,139 @@
|
||||
surface.CreateFont("LeadBot_AFK", {
|
||||
font = "Roboto",
|
||||
size = 34,
|
||||
weight = 500
|
||||
})
|
||||
|
||||
surface.CreateFont("LeadBot_AFK2", {
|
||||
font = "Roboto",
|
||||
size = 30,
|
||||
weight = 500
|
||||
})
|
||||
|
||||
hook.Add("HUDPaint", "AFKT", function()
|
||||
if LocalPlayer():GetNWBool("LeadBot_AFK") then
|
||||
draw.SimpleTextOutlined("You are AFK.", "LeadBot_AFK", ScrW() / 2, ScrH() / 2.85, Color(255, 255, 255, 235), TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, 1, Color(0, 0, 0, 255))
|
||||
draw.SimpleTextOutlined("Press any key to rejoin.", "LeadBot_AFK2", ScrW() / 2, ScrH() / 2.675, Color(255, 255, 255, 235), TEXT_ALIGN_CENTER, TEXT_ALIGN_BOTTOM, 1, Color(0, 0, 0, 255))
|
||||
end
|
||||
end)
|
||||
|
||||
local tp = false
|
||||
local last_TP = false
|
||||
local newangle = Angle(0, 0, 0)
|
||||
local scroll = 0
|
||||
local lastsend = CurTime()
|
||||
local tp_Gamemodes = {}
|
||||
local NoAFKCamera = {}
|
||||
tp_Gamemodes["sandbox"] = true
|
||||
tp_Gamemodes["darkestdays"] = true
|
||||
NoAFKCamera["assassins"] = true
|
||||
NoAFKCamera["cavefight"] = true
|
||||
|
||||
hook.Add("CreateMove", "LeadBot_AFK", function(cmd)
|
||||
local ply = LocalPlayer()
|
||||
|
||||
if ply:GetNWBool("LeadBot_AFK") then
|
||||
if lastsend < CurTime() and cmd:GetButtons() ~= 0 and !cmd:KeyDown(IN_ATTACK) and !cmd:KeyDown(IN_WALK) and !cmd:KeyDown(IN_SCORE) then
|
||||
net.Start("LeadBot_AFK_Off")
|
||||
net.SendToServer()
|
||||
lastsend = CurTime() + 0.1
|
||||
end
|
||||
|
||||
if cmd:KeyDown(IN_ATTACK) and tp_Gamemodes[engine.ActiveGamemode()] then
|
||||
if !last_TP then
|
||||
tp = !tp
|
||||
last_TP = true
|
||||
end
|
||||
else
|
||||
last_TP = false
|
||||
end
|
||||
|
||||
if input.WasMousePressed(MOUSE_WHEEL_DOWN) then
|
||||
scroll = math.Clamp(scroll + 4, -35, 45)
|
||||
elseif input.WasMousePressed(MOUSE_WHEEL_UP) then
|
||||
scroll = math.Clamp(scroll - 4, -35, 45)
|
||||
end
|
||||
|
||||
if tp then
|
||||
local s = GetConVar("m_pitch"):GetFloat()
|
||||
newangle.pitch = math.Clamp(newangle.pitch + cmd:GetMouseY() * s, -90, 90)
|
||||
newangle.yaw = newangle.yaw - cmd:GetMouseX() * s
|
||||
end
|
||||
|
||||
cmd:ClearButtons()
|
||||
cmd:ClearMovement()
|
||||
cmd:SetImpulse(0)
|
||||
|
||||
cmd:SetMouseX(0)
|
||||
cmd:SetMouseY(0)
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("InputMouseApply", "LeadBot_AFK", function(cmd)
|
||||
if LocalPlayer():GetNWBool("LeadBot_AFK") then
|
||||
cmd:SetMouseX(0)
|
||||
cmd:SetMouseY(0)
|
||||
return true
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("HUDShouldDraw", "LeadBot_AFK", function(hud)
|
||||
if hud == "CHudWeaponSelection" and LocalPlayer():GetNWBool("LeadBot_AFK") then
|
||||
return false
|
||||
end
|
||||
end)
|
||||
|
||||
local ang
|
||||
local lerp = 0
|
||||
|
||||
hook.Add("CalcView", "LeadBot_AFK", function(ply, origin, angles)
|
||||
if !ang then ang = angles end
|
||||
|
||||
if ply:ShouldDrawLocalPlayer() or !ply:GetNWBool("LeadBot_AFK") or NoAFKCamera[engine.ActiveGamemode()] then return end
|
||||
|
||||
local view = {}
|
||||
|
||||
if tp or lerp ~= 0 then
|
||||
if tp then
|
||||
lerp = math.Clamp(lerp + FrameTime() * 5, 0, 1)
|
||||
else
|
||||
lerp = math.Clamp(lerp - FrameTime() * 5, 0, 1)
|
||||
end
|
||||
|
||||
local pos = ply:EyePos()
|
||||
local trace = util.TraceHull({
|
||||
start = pos + newangle:Forward() * Lerp(lerp, 0, -5),
|
||||
endpos = pos + newangle:Forward() * Lerp(lerp, 0, -75 - scroll),
|
||||
filter = ply,
|
||||
mins = Vector(-8, -8, -8),
|
||||
maxs = Vector(8, 8, 8),
|
||||
})
|
||||
|
||||
view.angles = newangle
|
||||
view.origin = trace.HitPos
|
||||
view.drawviewer = true
|
||||
else
|
||||
ang = LerpAngle(FrameTime() * 16, ang, angles)
|
||||
ang = Angle(ang.p, ang.y, 0)
|
||||
newangle = ang
|
||||
view.angles = ang
|
||||
end
|
||||
|
||||
return view
|
||||
end)
|
||||
|
||||
hook.Add("CalcViewModelView", "LeadBot_AFK", function(wep, vm, oldpos, oldang, newpos, newang)
|
||||
local ply = LocalPlayer()
|
||||
|
||||
if ply:ShouldDrawLocalPlayer() or !ply:GetNWBool("LeadBot_AFK") or NoAFKCamera[engine.ActiveGamemode()] then return end
|
||||
|
||||
if wep.GetViewModelPosition then
|
||||
newpos, newang = wep:GetViewModelPosition(newpos, newang)
|
||||
end
|
||||
|
||||
if wep.CalcViewModelView then
|
||||
newpos, newang = wep:CalcViewModelView(vm, oldpos, oldang, newpos, newang)
|
||||
end
|
||||
|
||||
return newpos, ang
|
||||
end)
|
||||
73
lua/refoselbots/modules/afk/sv_afk.lua
Normal file
73
lua/refoselbots/modules/afk/sv_afk.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
concommand.Add("refoselbots_afk", function(ply, _, args) RefoselBots.Botize(ply) end, nil, "Adds a RefoselBots ;)")
|
||||
|
||||
local time = CreateConVar("refoselbots_afk_timetoafk", "300", {FCVAR_ARCHIVE})
|
||||
local meta = FindMetaTable("Player")
|
||||
local oldFunc = meta.IsBot
|
||||
|
||||
util.AddNetworkString("RefoselBots_AFK_Off")
|
||||
|
||||
net.Receive("RefoselBots_AFK_Off", function(_, ply)
|
||||
RefoselBots.Botize(ply, false)
|
||||
ply.LastAFKCheck = CurTime() + time:GetFloat()
|
||||
end)
|
||||
|
||||
hook.Add("PlayerTick", "RefoselBots_AFK", function(ply)
|
||||
if !time:GetBool() then return end
|
||||
|
||||
ply.LastAFKCheck = ply.LastAFKCheck or CurTime() + time:GetFloat()
|
||||
|
||||
if ply:KeyDown(IN_FORWARD) or ply:KeyDown(IN_BACK) or ply:KeyDown(IN_MOVELEFT) or ply:KeyDown(IN_MOVERIGHT) or ply:KeyDown(IN_ATTACK) then
|
||||
ply.LastAFKCheck = CurTime() + time:GetFloat()
|
||||
end
|
||||
|
||||
if ply.LastAFKCheck < CurTime() and !ply:IsBot() and !ply:GetNWBool("RefoselBots_AFK") then
|
||||
RefoselBots.Botize(ply, true)
|
||||
end
|
||||
end)
|
||||
|
||||
function RefoselBots.Botize(ply, togg)
|
||||
if togg == nil then togg = !ply.RefoselBots end
|
||||
|
||||
if ((!togg and ply:IsLBot()) or (togg and !ply:IsLBot())) and RefoselBots.SuicideAFK and ply:Alive() then
|
||||
ply:Kill()
|
||||
end
|
||||
|
||||
if !togg then
|
||||
ply:SetNWBool("RefoselBots_AFK", false)
|
||||
ply.RefoselBots = false
|
||||
if IsValid(ply.ControllerBot) then
|
||||
ply.ControllerBot:Remove()
|
||||
end
|
||||
ply.LastSegmented = CurTime()
|
||||
ply.CurSegment = 2
|
||||
else
|
||||
ply:SetNWBool("RefoselBots_AFK", true)
|
||||
ply.RefoselBots = true
|
||||
ply.BotColor = ply:GetPlayerColor()
|
||||
ply.BotSkin = ply:GetSkin()
|
||||
ply.BotModel = ply:GetModel()
|
||||
ply.BotWColor = ply:GetWeaponColor()
|
||||
ply.ControllerBot = ents.Create("refoselbots_navigator")
|
||||
ply.ControllerBot:Spawn()
|
||||
ply.ControllerBot:SetOwner(ply)
|
||||
ply.ControllerBot:SetFOV(ply:GetFOV())
|
||||
ply.LastSegmented = CurTime()
|
||||
ply.CurSegment = 2
|
||||
if GetConVar("refoselbots_strategy"):GetBool() then
|
||||
ply.BotStrategy = math.random(0, RefoselBots.Strategies)
|
||||
end
|
||||
ply.RefoselBots_Config = {}
|
||||
ply.RefoselBots_Config[1] = ply.BotModel
|
||||
ply.RefoselBots_Config[2] = ply.BotColor
|
||||
ply.RefoselBots_Config[3] = ply.BotWColor
|
||||
ply.RefoselBots_Config[4] = ply.BotStrategy
|
||||
end
|
||||
end
|
||||
|
||||
function meta:IsBot()
|
||||
if self:IsLBot() and RefoselBots.AFKBotOverride then
|
||||
return true
|
||||
else
|
||||
return oldFunc(self)
|
||||
end
|
||||
end
|
||||
111
lua/refoselbots/modules/avatar/cl_avatar.lua
Normal file
111
lua/refoselbots/modules/avatar/cl_avatar.lua
Normal file
@@ -0,0 +1,111 @@
|
||||
-- TODO: store avatar in dhtml png images or something, alpha fade out is weird with dmodelpanel
|
||||
|
||||
local meta = FindMetaTable("Panel")
|
||||
local oldfunc = meta.SetPlayer
|
||||
local disabledGamemodes = {}
|
||||
disabledGamemodes["assassins"] = true
|
||||
|
||||
function meta:SetPlayer(ply, size)
|
||||
if !IsValid(ply) or !ply:IsPlayer() then return end
|
||||
if disabledGamemodes[engine.ActiveGamemode()] then return oldfunc(self, ply, size) end
|
||||
|
||||
if ply:IsBot() and ply:GetNWString("LeadBot_AvatarModel", "none") ~= "none" then
|
||||
function self:Paint(w, h)
|
||||
draw.RoundedBox(0, 0, 0, w, h, Color(255, 255, 255))
|
||||
end
|
||||
|
||||
local background = vgui.Create("DPanel", self)
|
||||
background:Dock(FILL)
|
||||
-- background.Texture = Material("entities/monster_scientist.png")
|
||||
|
||||
function background:Paint(w, h)
|
||||
if !ispanel(self:GetParent()) then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
draw.RoundedBox(0, 0, 0, w, h, Color(255, 255, 255))
|
||||
|
||||
--[[surface.SetMaterial(self.Texture)
|
||||
surface.SetDrawColor(255, 255, 255)
|
||||
surface.DrawTexturedRect(0, 0, w, h)]]
|
||||
end
|
||||
|
||||
local model = vgui.Create("DModelPanel", self)
|
||||
model:SetModel("models/player.mdl")
|
||||
model:Dock(FILL)
|
||||
model.Player = ply
|
||||
|
||||
if !ply.AvatarSeq then
|
||||
ply.AvatarSeq = table.Random({"death_01", "death_02", "death_03", "death_04"})
|
||||
ply.AvatarCycle = math.Rand(0.025, (ply.AvatarSeq == "death_04" and 0.06) or (ply.AvatarSeq == "death_01" and 0.3) or 0.1)
|
||||
end
|
||||
|
||||
local playermodel = ply:GetNWString("LeadBot_AvatarModel", ply:GetModel())
|
||||
|
||||
function model:LayoutEntity(ent)
|
||||
if !ispanel(self:GetParent()) then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
if !IsValid(self.Player) or !IsValid(ent) or !self.Player:IsPlayer() then return end
|
||||
|
||||
self.ModelCache = self.ModelCache or ""
|
||||
|
||||
if !ent.GetPlayerColor then
|
||||
ent.Player = self.Player
|
||||
function ent:GetPlayerColor()
|
||||
if !IsValid(self.Player) then return Vector(1, 1, 1) end
|
||||
return self.Player:GetNWVector("LeadBot_AvatarColor", self.Player:GetPlayerColor())
|
||||
end
|
||||
end
|
||||
|
||||
ent:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
ent:SetLOD(0)
|
||||
|
||||
-- voicechat fix
|
||||
local alpha = 255
|
||||
if ispanel(self:GetParent()) and ispanel(self:GetParent():GetParent()) then
|
||||
alpha = self:GetParent():GetParent():GetAlpha()
|
||||
end
|
||||
|
||||
self:SetColor(Color(255, 255, 255, alpha))
|
||||
|
||||
if self.ModelCache ~= playermodel then
|
||||
self:SetModel(playermodel)
|
||||
|
||||
ent = self:GetEntity()
|
||||
|
||||
local seq_name = self.Player.AvatarSeq
|
||||
local seq = ent:LookupSequence(seq_name or 0) -- "menu_walk")
|
||||
if seq < 0 then
|
||||
seq = ent:LookupSequence("menu_walk") -- "reload_dual_original")
|
||||
end
|
||||
|
||||
ent:SetSequence(seq) -- table.Random({"swimming_duel", "zombie_slump_idle_02"})))
|
||||
ent:SetCycle(self.Player.AvatarCycle)
|
||||
|
||||
local att = ent:LookupAttachment("eyes")
|
||||
|
||||
if att > 0 then
|
||||
att = ent:GetAttachment(att)
|
||||
if seq_name ~= "death_05" then
|
||||
self:SetFOV(23)
|
||||
self:SetCamPos(att.Pos + att.Ang:Forward() * 36 + att.Ang:Up() * 2)
|
||||
self:SetLookAt(att.Pos - Vector(0, 0, 1))
|
||||
else
|
||||
self:SetFOV(27)
|
||||
self:SetCamPos(att.Pos + att.Ang:Forward() * 36)
|
||||
self:SetLookAt(att.Pos - Vector(0, 0, 3))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
self.ModelCache = self.Player:GetModel()
|
||||
end
|
||||
end
|
||||
else
|
||||
oldfunc(self, ply, size)
|
||||
end
|
||||
end
|
||||
12
lua/refoselbots/modules/avatar/sv_avatar.lua
Normal file
12
lua/refoselbots/modules/avatar/sv_avatar.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
local oldAddBot = LeadBot.AddBotOverride
|
||||
|
||||
function LeadBot.AddBotOverride(bot)
|
||||
oldAddBot(bot)
|
||||
|
||||
timer.Simple(0, function()
|
||||
if IsValid(bot) then
|
||||
bot:SetNWString("LeadBot_AvatarModel", player_manager.TranslatePlayerModel(bot:LBGetModel()))
|
||||
bot:SetNWVector("LeadBot_AvatarColor", bot:LBGetColor())
|
||||
end
|
||||
end)
|
||||
end
|
||||
10
lua/refoselbots/modules/flashlight/cl_flashlight.lua
Normal file
10
lua/refoselbots/modules/flashlight/cl_flashlight.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
net.Receive("refoselbots_Flashlight", function()
|
||||
local flashlights = {}
|
||||
for _, ply in pairs(player.GetAll()) do
|
||||
flashlights[ply] = render.GetLightColor(ply:EyePos())
|
||||
end
|
||||
|
||||
net.Start("refoselbots_Flashlight")
|
||||
net.WriteTable(flashlights)
|
||||
net.SendToServer()
|
||||
end)
|
||||
52
lua/refoselbots/modules/flashlight/sv_flashlight.lua
Normal file
52
lua/refoselbots/modules/flashlight/sv_flashlight.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
util.AddNetworkString("refoselbots_Flashlight")
|
||||
|
||||
local convar = CreateConVar("refoselbots_flashlight", "1", {FCVAR_ARCHIVE}, "Flashlight for bots")
|
||||
local updateply
|
||||
local updatetime
|
||||
local updatetime_2 = 0
|
||||
|
||||
hook.Add("Think", "refoselbots_Flashlight", function()
|
||||
if !convar:GetBool() or RefoselBots.NoFlashlight then return end
|
||||
|
||||
local tab = player.GetHumans()
|
||||
if updatetime_2 < CurTime() and #tab > 0 then
|
||||
local ply = table.Random(tab)
|
||||
|
||||
updateply = ply
|
||||
updatetime = CurTime() + 0.5
|
||||
|
||||
net.Start("refoselbots_Flashlight")
|
||||
net.Send(ply)
|
||||
|
||||
updatetime_2 = CurTime() + 0.5
|
||||
end
|
||||
end)
|
||||
|
||||
net.Receive("refoselbots_Flashlight", function(_, ply)
|
||||
if ply ~= updateply then return end
|
||||
if updatetime < CurTime() then return end
|
||||
|
||||
local tab = net.ReadTable()
|
||||
if !istable(tab) then return end
|
||||
|
||||
for bot, light in pairs(tab) do
|
||||
bot.LastLight2 = bot.LastLight2 or 0
|
||||
light = Vector(math.Round(light.x, 2), math.Round(light.y, 2), math.Round(light.z, 2))
|
||||
|
||||
local lighton = light == Vector(0, 0, 0)
|
||||
|
||||
if lighton then
|
||||
bot.LastLight2 = math.Clamp(bot.LastLight2 + 1, 0, 3)
|
||||
else
|
||||
bot.LastLight2 = 0
|
||||
end
|
||||
|
||||
bot.FlashlightOn = lighton and bot.LastLight2 == 3
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("StartCommand", "refoselbots_Flashlight", function(ply, cmd)
|
||||
if ply:IsLBot() and updatetime_2 - 0.1 < CurTime() and (ply.FlashlightOn and !ply:FlashlightIsOn() or !ply.FlashlightOn and ply:FlashlightIsOn()) then
|
||||
cmd:SetImpulse(100)
|
||||
end
|
||||
end)
|
||||
30
lua/refoselbots/modules/ping/sh_ping.lua
Normal file
30
lua/refoselbots/modules/ping/sh_ping.lua
Normal file
@@ -0,0 +1,30 @@
|
||||
local meta = FindMetaTable("Player")
|
||||
local oldFunc = meta.Ping
|
||||
local ping = 0
|
||||
local fakeping = true
|
||||
local convar = CreateConVar("refoselbots_fakeping", "0", {FCVAR_ARCHIVE, FCVAR_NOTIFY, FCVAR_REPLICATED}, "Enables fakeping (Do not use this in public servers!)\n2 to make it say BOT")
|
||||
|
||||
function meta:Ping()
|
||||
if convar:GetBool() and self:IsBot() then
|
||||
if fakeping then
|
||||
self.FakePing = self.FakePing or math.random(35, 105)
|
||||
self.OFakePing = self.OFakePing or self.FakePing
|
||||
|
||||
if math.random(125) == 1 then
|
||||
self.FakePing = self.OFakePing + math.random(3)
|
||||
elseif math.random(125) == 1 then
|
||||
self.FakePing = self.OFakePing - math.random(3)
|
||||
end
|
||||
|
||||
if convar:GetInt() == 2 then
|
||||
self.FakePing = "BOT"
|
||||
end
|
||||
|
||||
return self.FakePing
|
||||
end
|
||||
|
||||
return ping
|
||||
else
|
||||
return oldFunc(self)
|
||||
end
|
||||
end
|
||||
46
lua/refoselbots/modules/quota/sv_quota.lua
Normal file
46
lua/refoselbots/modules/quota/sv_quota.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
local convar1 = CreateConVar("refoselbots_quota", "0", {FCVAR_ARCHIVE}, "TF2 Style Quota for bots\nUse refoselbots_add if you want unkickable bots")
|
||||
local nextCheck = 0
|
||||
|
||||
cvars.AddChangeCallback("refoselbots_quota", function(_, oldval, val)
|
||||
oldval = tonumber(oldval)
|
||||
val = tonumber(val)
|
||||
|
||||
if oldval and val and oldval > 0 and val < 1 then
|
||||
RunConsoleCommand("refoselbots_kick", "all")
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("Think", "RefoselBots_Quota", function()
|
||||
if !convar1:GetBool() or RefoselBots.AFKBotOverride then return end
|
||||
|
||||
if nextCheck < CurTime() then
|
||||
local bots = {}
|
||||
local max = convar1:GetInt() - #player.GetHumans()
|
||||
|
||||
for _, ply in pairs(player.GetBots()) do
|
||||
if ply:IsLBot(true) then
|
||||
table.insert(bots, ply)
|
||||
end
|
||||
end
|
||||
|
||||
for i = 1, #bots do
|
||||
if i >= convar1:GetInt() then
|
||||
bots[i]:Kick()
|
||||
end
|
||||
end
|
||||
|
||||
if #bots < max then
|
||||
nextCheck = CurTime() + 0.5
|
||||
|
||||
for i = 1, max - #bots do
|
||||
timer.Simple(0.1 + (i * 0.5), function()
|
||||
RefoselBots.AddBot()
|
||||
end)
|
||||
|
||||
nextCheck = nextCheck + 0.5
|
||||
end
|
||||
else
|
||||
nextCheck = CurTime() + 1
|
||||
end
|
||||
end
|
||||
end)
|
||||
67
lua/refoselbots/modules/voice/cl_voice.lua
Normal file
67
lua/refoselbots/modules/voice/cl_voice.lua
Normal file
@@ -0,0 +1,67 @@
|
||||
net.Receive("botVoiceStart", function()
|
||||
local ply = net.ReadEntity()
|
||||
local soundn = net.ReadString()
|
||||
local time = SoundDuration(soundn) -- - 0.1
|
||||
|
||||
if !IsValid(ply) or !ply:IsBot() or (IsValid(ply.ChattingS) and ply.ChattingS:GetState() == GMOD_CHANNEL_PLAYING) then return end
|
||||
|
||||
-- tts tests
|
||||
-- sound.PlayURL([[https://translate.google.com/translate_tts?ie=UTF-8&tl=en-us&client=tw-ob&q="]] .. voiceline .. [["]], "mono", function(station)
|
||||
sound.PlayFile("sound/" .. soundn, "mono", function(station)
|
||||
if IsValid(station) then
|
||||
ply.ChattingS = station
|
||||
station:SetPlaybackRate(math.random(95, 105) * 0.01)
|
||||
station:Play()
|
||||
hook.Call("PlayerStartVoice", gmod.GetGamemode(), ply)
|
||||
|
||||
timer.Simple(time, function()
|
||||
if IsValid(ply) then
|
||||
hook.Call("PlayerEndVoice", gmod.GetGamemode(), ply)
|
||||
station:Stop()
|
||||
--ply.ChattingB = false
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end)
|
||||
|
||||
local voice = Material("voice/icntlk_pl")
|
||||
-- is there no way to force this on?
|
||||
hook.Add("PostPlayerDraw", "LeadBot_VoiceIcon", function(ply)
|
||||
if !IsValid(ply) or !ply:IsPlayer() or !ply:IsBot() or !IsValid(ply.ChattingS) or !GetConVar("mp_show_voice_icons"):GetBool() then return end
|
||||
|
||||
local ang = EyeAngles()
|
||||
local pos = ply:GetPos() + ply:GetCurrentViewOffset() + Vector(0, 0, 14)
|
||||
ang:RotateAroundAxis(ang:Up(), -90)
|
||||
ang:RotateAroundAxis(ang:Forward(), 90)
|
||||
|
||||
cam.Start3D2D(pos, ang, 1)
|
||||
surface.SetMaterial(voice)
|
||||
surface.SetDrawColor(255, 255, 255)
|
||||
surface.DrawTexturedRect(-8, -8, 16, 16)
|
||||
cam.End3D2D()
|
||||
end)
|
||||
|
||||
local meta = FindMetaTable("Player")
|
||||
local oldFunc = meta.VoiceVolume
|
||||
local oldFunc2 = meta.IsSpeaking
|
||||
|
||||
function meta:VoiceVolume()
|
||||
if self:IsBot() then
|
||||
if IsValid(self.ChattingS) then
|
||||
return self.ChattingS:GetLevel() * 0.6
|
||||
else
|
||||
return 0
|
||||
end
|
||||
else
|
||||
return oldFunc(self)
|
||||
end
|
||||
end
|
||||
|
||||
function meta:IsSpeaking()
|
||||
if self:IsBot() then
|
||||
return IsValid(self.ChattingS) or false
|
||||
else
|
||||
return oldFunc2(self)
|
||||
end
|
||||
end
|
||||
171
lua/refoselbots/modules/voice/sv_voice.lua
Normal file
171
lua/refoselbots/modules/voice/sv_voice.lua
Normal file
@@ -0,0 +1,171 @@
|
||||
util.AddNetworkString("botVoiceStart")
|
||||
|
||||
RefoselBots.VoicePreset = {}
|
||||
RefoselBots.VoiceModels = {}
|
||||
|
||||
local convar = CreateConVar("refoselbots_voice", "random", {FCVAR_ARCHIVE}, "Voice Preset.\nOptions are: \n- \"random\"\n- \"" .. table.concat(table.GetKeys(RefoselBots.VoicePreset), "\"\n- \"") .. "\"")
|
||||
|
||||
function RefoselBots.TalkToMe(ply, type)
|
||||
if !ply:IsLBot(true) then return end
|
||||
|
||||
local hear = {}
|
||||
local sound = ""
|
||||
local selectedvoice = "metropolice"
|
||||
local voice = convar:GetString()
|
||||
|
||||
if voice == "random" then
|
||||
if !ply.RefoselBots_Voice then
|
||||
local model = ply:Nick()
|
||||
if RefoselBots.VoiceModels[model] then
|
||||
ply.RefoselBots_Voice = RefoselBots.VoiceModels[model]
|
||||
else
|
||||
local _, selectedplyvoice = table.Random(RefoselBots.VoicePreset)
|
||||
ply.RefoselBots_Voice = selectedplyvoice
|
||||
end
|
||||
end
|
||||
|
||||
if !RefoselBots.VoicePreset[ply.RefoselBots_Voice] then
|
||||
ply.RefoselBots_Voice = "metropolice"
|
||||
end
|
||||
|
||||
selectedvoice = ply.RefoselBots_Voice
|
||||
elseif RefoselBots.VoicePreset[voice] then
|
||||
selectedvoice = voice
|
||||
elseif voice == "" then
|
||||
return
|
||||
end
|
||||
|
||||
for k, v in pairs(player.GetAll()) do
|
||||
if hook.Call("PlayerCanHearPlayersVoice", gmod.GetGamemode(), v, ply) then
|
||||
table.insert(hear, v)
|
||||
end
|
||||
end
|
||||
|
||||
if type and RefoselBots.VoicePreset[selectedvoice][type] then
|
||||
sound = table.Random(RefoselBots.VoicePreset[selectedvoice][type])
|
||||
end
|
||||
|
||||
net.Start("botVoiceStart")
|
||||
net.WriteEntity(ply)
|
||||
net.WriteString(sound)
|
||||
net.Send(hear)
|
||||
end
|
||||
|
||||
-- Valve Games
|
||||
|
||||
if IsMounted("cstrike") then
|
||||
RefoselBots.VoicePreset["css"] = {}
|
||||
RefoselBots.VoicePreset["css"]["join"] = {"bot/its_a_party.wav", "bot/oh_boy2.wav", "bot/whoo.wav"}
|
||||
RefoselBots.VoicePreset["css"]["taunt"] = {"bot/do_not_mess_with_me.wav", "bot/i_am_dangerous.wav", "bot/i_am_on_fire.wav", "bot/i_wasnt_worried_for_a_minute.wav", "bot/nice2.wav", "bot/owned.wav", "bot/made_him_cry.wav", "bot/they_never_knew_what_hit_them.wav", "bot/who_wants_some_more.wav", "bot/whos_the_man.wav", "bot/yea_baby.wav", "bot/wasted_him.wav"}
|
||||
RefoselBots.VoicePreset["css"]["help"] = {"bot/help.wav", "bot/i_could_use_some_help.wav", "bot/i_could_use_some_help_over_here.wav", "bot/im_in_trouble.wav", "bot/need_help.wav", "bot/need_help2.wav", "bot/the_actions_hot_here.wav"}
|
||||
RefoselBots.VoicePreset["css"]["downed"] = RefoselBots.VoicePreset["css"]["help"]
|
||||
end
|
||||
|
||||
-- Citizens
|
||||
|
||||
RefoselBots.VoicePreset["male"] = {}
|
||||
RefoselBots.VoicePreset["male"]["join"] = {"vo/npc/male01/hi01.wav", "vo/npc/male01/hi02.wav", "vo/npc/male01/yeah02.wav", "vo/npc/male01/squad_reinforce_single04.wav", "vo/npc/male01/squad_affirm06.wav", "vo/npc/male01/readywhenyouare01.wav", "vo/npc/male01/okimready03.wav", "vo/npc/male01/letsgo02.wav"}
|
||||
RefoselBots.VoicePreset["male"]["taunt"] = {"vo/coast/odessa/male01/nlo_cheer03.wav", "vo/npc/male01/gotone02.wav", "vo/npc/male01/likethat.wav", "vo/npc/male01/nice01.wav", "vo/npc/male01/question17.wav", "vo/npc/male01/yeah02.wav", "vo/npc/male01/vquestion01.wav"}
|
||||
RefoselBots.VoicePreset["male"]["pain"] = {"vo/npc/male01/help01.wav", "vo/npc/male01/startle01.wav", "vo/npc/male01/startle02.wav", "vo/npc/male01/uhoh.wav"}
|
||||
|
||||
RefoselBots.VoicePreset["female"] = {}
|
||||
RefoselBots.VoicePreset["female"]["join"] = {"vo/npc/female01/hi01.wav", "vo/npc/female01/hi02.wav", "vo/npc/female01/yeah02.wav", "vo/npc/female01/squad_reinforce_single04.wav", "vo/npc/female01/squad_affirm06.wav", "vo/npc/female01/readywhenyouare01.wav", "vo/npc/female01/okimready03.wav", "vo/npc/female01/letsgo02.wav"}
|
||||
RefoselBots.VoicePreset["female"]["taunt"] = {"vo/coast/odessa/female01/nlo_cheer03.wav", "vo/npc/female01/gotone02.wav", "vo/npc/female01/likethat.wav", "vo/npc/female01/nice01.wav", "vo/npc/female01/question17.wav", "vo/npc/female01/yeah02.wav", "vo/npc/female01/vquestion01.wav"}
|
||||
RefoselBots.VoicePreset["female"]["pain"] = {"vo/npc/female01/help01.wav", "vo/npc/female01/startle01.wav", "vo/npc/female01/startle02.wav", "vo/npc/female01/uhoh.wav"}
|
||||
|
||||
-- Main Characters
|
||||
|
||||
RefoselBots.VoicePreset["alyx"] = {}
|
||||
RefoselBots.VoicePreset["alyx"]["join"] = {"vo/npc/alyx/al_excuse03.wav", "vo/npc/alyx/getback01.wav", "vo/npc/alyx/lookout01.wav", "vo/npc/alyx/getback02.wav"}
|
||||
RefoselBots.VoicePreset["alyx"]["taunt"] = {"vo/npc/alyx/al_excuse03.wav", "vo/npc/alyx/lookout01.wav", "vo/npc/alyx/lookout03.wav", "vo/npc/alyx/brutal02.wav", "vo/npc/alyx/youreload02.wav"}
|
||||
RefoselBots.VoicePreset["alyx"]["pain"] = {"vo/npc/alyx/gasp03.wav", "vo/npc/alyx/ohgod01.wav", "vo/npc/alyx/ohno_startle01.wav"}
|
||||
|
||||
RefoselBots.VoicePreset["barney"] = {}
|
||||
RefoselBots.VoicePreset["barney"]["join"] = {"vo/npc/barney/ba_ohyeah.wav", "vo/npc/barney/ba_yell.wav", "vo/npc/barney/ba_bringiton.wav"}
|
||||
RefoselBots.VoicePreset["barney"]["taunt"] = {"vo/npc/barney/ba_downyougo.wav", "vo/npc/barney/ba_losttouch.wav", "vo/npc/barney/ba_yell.wav", "vo/npc/barney/ba_getaway.wav"}
|
||||
RefoselBots.VoicePreset["barney"]["help"] = {"vo/npc/barney/ba_no01.wav", "vo/npc/barney/ba_no02.wav", "vo/npc/barney/ba_damnit.wav"}
|
||||
|
||||
RefoselBots.VoicePreset["grigori"] = {}
|
||||
RefoselBots.VoicePreset["grigori"]["join"] = {"vo/ravenholm/monk_death07.wav", "vo/ravenholm/exit_nag02.wav", "vo/ravenholm/engage04.wav", "vo/ravenholm/engage05.wav", "vo/ravenholm/engage06.wav", "vo/ravenholm/engage07.wav", "vo/ravenholm/engage08.wav", "vo/ravenholm/engage09.wav"}
|
||||
RefoselBots.VoicePreset["grigori"]["taunt"] = {"vo/ravenholm/madlaugh01.wav", "vo/ravenholm/madlaugh02.wav", "vo/ravenholm/madlaugh03.wav", "vo/ravenholm/madlaugh04.wav", "vo/ravenholm/monk_kill01.wav", "vo/ravenholm/monk_kill02.wav", "vo/ravenholm/monk_kill03.wav", "vo/ravenholm/monk_kill04.wav", "vo/ravenholm/monk_kill05.wav", "vo/ravenholm/monk_kill06.wav", "vo/ravenholm/monk_kill07.wav", "vo/ravenholm/monk_kill08.wav", "vo/ravenholm/monk_kill09.wav", "vo/ravenholm/firetrap_vigil.wav"}
|
||||
RefoselBots.VoicePreset["grigori"]["pain"] = {"vo/ravenholm/monk_pain12.wav", "vo/ravenholm/monk_rant13.wav", "vo/ravenholm/monk_pain06.wav", "vo/ravenholm/engage08.wav"}
|
||||
|
||||
-- Enemies
|
||||
|
||||
RefoselBots.VoicePreset["metropolice"] = {}
|
||||
RefoselBots.VoicePreset["metropolice"]["join"] = {"npc/metropolice/vo/lookingfortrouble.wav", "npc/metropolice/vo/pickupthecan1.wav", "npc/metropolice/vo/youwantamalcomplianceverdict.wav", "npc/metropolice/vo/unitisonduty10-8.wav", "npc/metropolice/vo/unitis10-8standingby.wav", "npc/metropolice/vo/readytoamputate.wav", "npc/metropolice/vo/prepareforjudgement.wav", "npc/metropolice/vo/readytoprosecutefinalwarning.wav"}
|
||||
RefoselBots.VoicePreset["metropolice"]["taunt"] = {"npc/metropolice/vo/finalverdictadministered.wav", "npc/metropolice/vo/firstwarningmove.wav", "npc/metropolice/vo/isaidmovealong.wav", "npc/metropolice/vo/nowgetoutofhere.wav", "npc/metropolice/vo/pickupthecan2.wav", "npc/metropolice/vo/pickupthecan3.wav", "npc/metropolice/vo/putitinthetrash1.wav", "npc/metropolice/vo/putitinthetrash2.wav", "npc/metropolice/vo/suspectisbleeding.wav", "npc/metropolice/vo/thisisyoursecondwarning.wav"}
|
||||
RefoselBots.VoicePreset["metropolice"]["pain"] = {"npc/metropolice/vo/11-99officerneedsassistance.wav", "npc/metropolice/vo/wehavea10-108.wav", "npc/metropolice/vo/runninglowonverdicts.wav", "npc/metropolice/pain4.wav"}
|
||||
|
||||
-- Player Config
|
||||
|
||||
RefoselBots.VoiceModels["Alyx Vance"] = "alyx"
|
||||
RefoselBots.VoiceModels["Isaac Kleiner"] = "male"
|
||||
RefoselBots.VoiceModels["Dr. Wallace Breen"] = "male"
|
||||
RefoselBots.VoiceModels["The G-Man"] = "male"
|
||||
RefoselBots.VoiceModels["Odessa Cubbage"] = "male"
|
||||
RefoselBots.VoiceModels["Eli Vance"] = "male"
|
||||
RefoselBots.VoiceModels["Father Grigori"] = "grigori"
|
||||
RefoselBots.VoiceModels["Judith Mossman"] = "female"
|
||||
RefoselBots.VoiceModels["Barney Calhoun"] = "barney"
|
||||
|
||||
RefoselBots.VoiceModels["Magnusson"] = "male"
|
||||
|
||||
RefoselBots.VoiceModels["American Soldier"] = "male"
|
||||
RefoselBots.VoiceModels["German Soldier"] = "male"
|
||||
|
||||
RefoselBots.VoiceModels["GIGN"] = "css"
|
||||
RefoselBots.VoiceModels["Elite Crew"] = "css"
|
||||
RefoselBots.VoiceModels["Artic Avengers"] = "css"
|
||||
RefoselBots.VoiceModels["SEAL Team Six"] = "css"
|
||||
RefoselBots.VoiceModels["GSG-9"] = "css"
|
||||
RefoselBots.VoiceModels["SAS"] = "css"
|
||||
RefoselBots.VoiceModels["Phoenix Connexion"] = "css"
|
||||
RefoselBots.VoiceModels["Guerilla Warfare"] = "css"
|
||||
RefoselBots.VoiceModels["Cohrt"] = "male"
|
||||
|
||||
RefoselBots.VoiceModels["Chell"] = "female"
|
||||
|
||||
RefoselBots.VoiceModels["Civil Protection"] = "metropolice"
|
||||
RefoselBots.VoiceModels["Combine Soldier"] = "metropolice"
|
||||
RefoselBots.VoiceModels["Combine Prison Guard"] = "metropolice"
|
||||
RefoselBots.VoiceModels["Elite Combine Soldier"] = "metropolice"
|
||||
RefoselBots.VoiceModels["Stripped Combine Soldier"] = "metropolice"
|
||||
|
||||
RefoselBots.VoiceModels["Zombie"] = "css"
|
||||
RefoselBots.VoiceModels["Fast Zombie"] = "css"
|
||||
RefoselBots.VoiceModels["Zombine"] = "css"
|
||||
RefoselBots.VoiceModels["Corpse"] = "css"
|
||||
RefoselBots.VoiceModels["Charple"] = "css"
|
||||
RefoselBots.VoiceModels["Skeleton"] = "css"
|
||||
|
||||
RefoselBots.VoiceModels["Van"] = "male"
|
||||
RefoselBots.VoiceModels["Ted"] = "male"
|
||||
RefoselBots.VoiceModels["Joe"] = "male"
|
||||
RefoselBots.VoiceModels["Eric"] = "male"
|
||||
RefoselBots.VoiceModels["Art"] = "male"
|
||||
RefoselBots.VoiceModels["Sandro"] = "male"
|
||||
RefoselBots.VoiceModels["Mike"] = "male"
|
||||
RefoselBots.VoiceModels["Vance"] = "male"
|
||||
RefoselBots.VoiceModels["Erdin"] = "male"
|
||||
RefoselBots.VoiceModels["Van"] = "male"
|
||||
RefoselBots.VoiceModels["Ted"] = "male"
|
||||
RefoselBots.VoiceModels["Joe"] = "male"
|
||||
RefoselBots.VoiceModels["Eric"] = "male"
|
||||
RefoselBots.VoiceModels["Art"] = "male"
|
||||
RefoselBots.VoiceModels["Sandro"] = "male"
|
||||
RefoselBots.VoiceModels["Mike"] = "male"
|
||||
RefoselBots.VoiceModels["Vance"] = "male"
|
||||
RefoselBots.VoiceModels["Erdin"] = "male"
|
||||
RefoselBots.VoiceModels["Joey"] = "female"
|
||||
RefoselBots.VoiceModels["Kanisha"] = "female"
|
||||
RefoselBots.VoiceModels["Kim"] = "female"
|
||||
RefoselBots.VoiceModels["Chau"] = "female"
|
||||
RefoselBots.VoiceModels["Naomi"] = "female"
|
||||
RefoselBots.VoiceModels["Lakeetra"] = "female"
|
||||
RefoselBots.VoiceModels["Joey"] = "female"
|
||||
RefoselBots.VoiceModels["Kanisha"] = "female"
|
||||
RefoselBots.VoiceModels["Kim"] = "female"
|
||||
RefoselBots.VoiceModels["Chau"] = "female"
|
||||
RefoselBots.VoiceModels["Naomi"] = "female"
|
||||
RefoselBots.VoiceModels["Lakeetra"] = "female"
|
||||
Reference in New Issue
Block a user