From ed1fc759333c80dbf30dd6731bdae11787e80a46 Mon Sep 17 00:00:00 2001 From: LinGe <35224561+Lin515@users.noreply.github.com> Date: Sun, 5 Jun 2022 16:26:45 +0800 Subject: [PATCH] =?UTF-8?q?=E7=8E=A9=E5=AE=B6=E7=8A=B6=E6=80=81=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E5=8A=9F=E8=83=BD=E5=9F=BA=E6=9C=AC=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vscripts/LinGe/Hint.nut | 247 +++++++++++++++++++++++++++++----------- 1 file changed, 181 insertions(+), 66 deletions(-) diff --git a/vscripts/LinGe/Hint.nut b/vscripts/LinGe/Hint.nut index 6544776..c0dd6a3 100644 --- a/vscripts/LinGe/Hint.nut +++ b/vscripts/LinGe/Hint.nut @@ -7,23 +7,23 @@ printl("[LinGe] Hint 正在载入"); ::LinGe.Hint <- {}; ::LinGe.Hint.Config <- { - limit = 4, // 队友状态与普通标记提示的显示数量上限,若设置为<=0则彻底关闭 + limit = 4, // 队友状态与普通标记提示的总数量上限,若设置为<=0则彻底关闭提示系统 + offscreenShow = true, // 提示在画面之外是否也要显示 friend = { // 队友需要帮助时出现提示 包括 倒地、挂边、黑白、被控 duration = 15, // 提示持续时间,若<=0则彻底关闭所有队友需要帮助的提示 - dominatedDelay = 0, // 队友被特感控时(不包括倒地和挂边),出现提示的延迟时间,0即立即显示,<0则关闭被控时的提示 + dominateDelay = 2, // 被控延迟,玩家被控多少秒后才会出现提示,若设置为0则无延迟立即显示 <0则不显示被控 }, normal = { - + duration = 15, // 提示持续时间,若<=0则彻底关闭所有普通类型的提示 }, deadHint = true, // 死亡时不会出现标记提示,不过会在聊天窗输出提示 若设置为 false 则关闭该提示 // 该提示对BOT不生效 deadChat = "再见了大家,我会想念你们的", // 若这里设置为 "" 或者 null 则以服务器式提示输出 }; ::LinGe.Config.Add("Hint", ::LinGe.Hint.Config); -::LinGe.Cache.Hint_Config <- ::LinGe.Hint.Config; +// ::LinGe.Cache.Hint_Config <- ::LinGe.Hint.Config; // 生还者玩家死亡时输出提示 -if (::LinGe.Hint.Config.deadHint) { ::LinGe.Hint.OnGameEvent_player_death <- function (params) { if (!params.rawin("userid")) @@ -33,38 +33,34 @@ if (::LinGe.Hint.Config.deadHint) { local dierEntity = GetPlayerFromUserID(dier); if (dierEntity && dierEntity.IsSurvivor()) { + if (this.rawin("EndHint")) + EndHint(dierEntity); // 自杀时伤害类型为0 if (params.type == 0) return; if (Config.deadHint && (!IsPlayerABot(dierEntity)||::LinGe.Debug)) - VSLib.Timers.AddTimerByName(dier, 0.1, false, Timer_CheckPlayerDead, dierEntity); + { + if (null == Config.deadChat || "" == Config.deadChat) + ClientPrint(null, 3, "\x03" + dierEntity.GetPlayerName() + "\x04 牺牲了"); + else + Say(dierEntity, "\x03" + Config.deadChat, false); + } } } ::LinEventHook("OnGameEvent_player_death", ::LinGe.Hint.OnGameEvent_player_death, ::LinGe.Hint); -::LinGe.Hint.Timer_CheckPlayerDead <- function (player) -{ - if (!::LinGe.IsAlive(player)) - { - if (null == Config.deadChat || "" == Config.deadChat) - ClientPrint(null, 3, "\x03" + player.GetPlayerName() + "\x04 牺牲了"); - else - Say(player, "\x03" + Config.deadChat, false); - } -}.bindenv(::LinGe.Hint); -} // if (::LinGe.Hint.Config.deadHint) { - // 数量限制不大于0时不加载标记提示功能 if (::LinGe.Hint.Config.limit > 0) { // 当前提示列表 包含三个键 // key=level 信息提示等级,等级越高越重要 // key=ent value为env_instructor_hint实体 -// key=targetname value为目标实体名 +// key=targetname` value为目标实体名 local CurrentHint = []; getconsttable()["HELP_ICON"] <- "icon_shield"; if (::LinGe.Hint.Config.friend.duration > 0) { + // 事件:玩家倒地 ::LinGe.Hint.OnGameEvent_player_incapacitated <- function (params) { @@ -74,44 +70,45 @@ if (::LinGe.Hint.Config.friend.duration > 0) { local player = GetPlayerFromUserID(params.userid); if (player.IsSurvivor()) { - VSLib.Timers.AddTimerByName(params.userid, 0.1, false, Timer_CheckPlayerIncap, player); + EndHint(player); + VSLib.Timers.AddTimerByName(params.userid, 0.1, false, ShowPlayerIncap, player); } } ::LinEventHook("OnGameEvent_player_incapacitated", ::LinGe.Hint.OnGameEvent_player_incapacitated, ::LinGe.Hint); - -::LinGe.Hint.Timer_CheckPlayerIncap <- function (player) +::LinGe.Hint.ShowPlayerIncap <- function (player) { if (player.IsIncapacitated()) { // 倒地状态提示 - local activators = clone ::pyinfo.survivorIdx; - if (::LinGe.RemoveInArray(player.GetEntityIndex(), activators)) + local showTo = clone ::pyinfo.survivorIdx; + if (::LinGe.RemoveInArray(player.GetEntityIndex(), showTo) != null) { - ShowHint("帮助" + player.GetPlayerName(), 2, ::LinGe.GetEntityTargetname(player), - activators, Config.friend.duration, HELP_ICON); + ShowHint(player.GetPlayerName() + "倒地了", 2, player, + showTo, Config.friend.duration, HELP_ICON); } } }.bindenv(::LinGe.Hint); +// 玩家挂边 ::LinGe.Hint.OnGameEvent_player_ledge_grab <- function (params) { if (!params.rawin("userid")) return; local player = GetPlayerFromUserID(params.userid); - if (player.IsHangingFromLedge()) + ShowPlayerLedge(player); +} +::LinEventHook("OnGameEvent_player_ledge_grab", ::LinGe.Hint.OnGameEvent_player_ledge_grab, ::LinGe.Hint); +::LinGe.Hint.ShowPlayerLedge <- function (player) +{ + local showTo = clone ::pyinfo.survivorIdx; + if (::LinGe.RemoveInArray(player.GetEntityIndex(), showTo) != null) { - // 挂边状态提示 - local activators = clone ::pyinfo.survivorIdx; - if (::LinGe.RemoveInArray(player.GetEntityIndex(), activators)) - { - ShowHint("帮助" + player.GetPlayerName(), 2, ::LinGe.GetEntityTargetname(player), - activators, Config.friend.duration, HELP_ICON); - } + ShowHint("帮助" + player.GetPlayerName(), 2, player, + showTo, Config.friend.duration, HELP_ICON); } } -::LinEventHook("OnGameEvent_player_ledge_grab", ::LinGe.Hint.OnGameEvent_player_ledge_grab, ::LinGe.Hint); -// 成功拉起队友 +// 成功救助队友 (倒地拉起、挂边拉起、治疗都会触发该事件) ::LinGe.Hint.OnGameEvent_revive_success <- function (params) { if (!params.rawin("subject")) @@ -119,26 +116,128 @@ if (::LinGe.Hint.Config.friend.duration > 0) { local player = GetPlayerFromUserID(params.subject); if (!player.IsSurvivor()) return; - EndHint(::LinGe.GetEntityTargetname(player)); // 去除其身上的标志 + EndHint(player); // 去除其身上的标志 if (::LinGe.GetReviveCount(player) >= 2) + ShowPlayerDying(player); +} +::LinEventHook("OnGameEvent_revive_success", ::LinGe.Hint.OnGameEvent_revive_success, ::LinGe.Hint); +::LinGe.Hint.ShowPlayerDying <- function (player) +{ + // 黑白状态提示 + local showTo = ::pyinfo.survivorIdx; + if (::LinGe.RemoveInArray(player.GetEntityIndex(), showTo) != null) { - // 黑白状态提示 - local activators = clone ::pyinfo.survivorIdx; - if (::LinGe.RemoveInArray(player.GetEntityIndex(), activators)) - { - ShowHint("治疗" + player.GetPlayerName(), 1, ::LinGe.GetEntityTargetname(player), - activators, Config.friend.duration, HELP_ICON); - } + ShowHint(player.GetPlayerName() + "濒死", 1, player, + showTo, Config.friend.duration, HELP_ICON); + } +} + +// 玩家被控 +if (::LinGe.Hint.Config.friend.dominateDelay >= 0) { +::LinGe.Hint.PlayerBeDominating <- function (params) +{ + if (!params.rawin("victim")) + return; + local player = GetPlayerFromUserID(params.victim); + if (Config.friend.dominateDelay > 0) + ::VSLib.Timers.AddTimerByName(::LinGe.GetEntityTargetname(player), + Config.friend.dominateDelay, false, ShowPlayerBeDominating, player); + else + ShowPlayerBeDominating(player); +} +::LinEventHook("OnGameEvent_lunge_pounce", ::LinGe.Hint.PlayerBeDominating, ::LinGe.Hint); // Hunter +::LinEventHook("OnGameEvent_tongue_grab", ::LinGe.Hint.PlayerBeDominating, ::LinGe.Hint); // Smoker +::LinEventHook("OnGameEvent_charger_pummel_start", ::LinGe.Hint.PlayerBeDominating, ::LinGe.Hint); // Charger +::LinEventHook("OnGameEvent_jockey_ride", ::LinGe.Hint.PlayerBeDominating, ::LinGe.Hint); // Jockey + +// 被控解除 +::LinGe.Hint.PlayerDominateEnd <- function (params) +{ + if (!params.rawin("victim")) + return; + local player = GetPlayerFromUserID(params.victim); + EndHint(player); +} +::LinEventHook("OnGameEvent_pounce_stopped", ::LinGe.Hint.PlayerDominateEnd, ::LinGe.Hint); +::LinEventHook("OnGameEvent_tongue_release", ::LinGe.Hint.PlayerDominateEnd, ::LinGe.Hint); +::LinEventHook("OnGameEvent_charger_pummel_end", ::LinGe.Hint.PlayerDominateEnd, ::LinGe.Hint); +::LinEventHook("OnGameEvent_jockey_ride_end", ::LinGe.Hint.PlayerDominateEnd, ::LinGe.Hint); + +::LinGe.Hint.ShowPlayerBeDominating <- function (player) +{ + local showTo = clone ::pyinfo.survivorIdx; + if (::LinGe.RemoveInArray(player.GetEntityIndex(), showTo) != null) + { + ShowHint(player.GetPlayerName() + "被控了", 3, player, + showTo, Config.friend.duration, HELP_ICON); } } -::LinEventHook("OnGameEvent_revive_success", ::LinGe.Hint.OnGameEvent_revive_success, ::LinGe.Hint); + +} // if (::LinGe.Hint.Config.friend.dominateDelay >= 0) { + +// 玩家队伍变更,当某生还者出现队伍变更时,重置其身上的提示状态 +::LinGe.Hint.OnGameEvent_player_team <- function (params) +{ + if (!params.rawin("userid")) + return; + local player = GetPlayerFromUserID(params.userid); + + // 如果是离开生还者队伍,则移除其身上当前的提示 + if (2 == params.oldteam) + EndHint(player); +} +::LinEventHook("OnGameEvent_player_team", ::LinGe.Hint.OnGameEvent_player_team, ::LinGe.Hint); + +// BOT与玩家的交换,将状态进行转移 +// BOT取代玩家 +::LinGe.Hint.OnGameEvent_player_bot_replace <- function (params) +{ + local bot = GetPlayerFromUserID(params.bot); + local player = GetPlayerFromUserID(params.player); + if (::LinGe.GetPlayerTeam(bot) == 2 && FindHintIndex(player)!=null) + { + ::VSLib.Timers.AddTimerByName(::LinGe.GetEntityTargetname(bot), + 0.1, false, Timer_CheckPlayer, bot); + } +} +::LinEventHook("OnGameEvent_player_bot_replace", ::LinGe.Hint.OnGameEvent_player_bot_replace, ::LinGe.Hint); + +// 玩家取代BOT +::LinGe.Hint.OnGameEvent_bot_player_replace <- function (params) +{ + local bot = GetPlayerFromUserID(params.bot); + local player = GetPlayerFromUserID(params.player); + if (::LinGe.GetPlayerTeam(player) == 2 && FindHintIndex(bot)!=null) + { + ::VSLib.Timers.AddTimerByName(::LinGe.GetEntityTargetname(player), + 0.1, false, Timer_CheckPlayer, player); + } +} +::LinEventHook("OnGameEvent_bot_player_replace", ::LinGe.Hint.OnGameEvent_bot_player_replace, ::LinGe.Hint); + +::LinGe.Hint.Timer_CheckPlayer <- function (player) +{ + if (!::LinGe.IsAlive(player)) + return; + else if (player.IsIncapacitated()) + ShowPlayerIncap(player); + else if (player.IsHangingFromLedge()) + ShowPlayerLedge(player); + else if (player.GetSpecialInfectedDominatingMe()) + ShowPlayerBeDominating(player); + else if (::LinGe.GetReviveCount(player) >= 2) + ShowPlayerDying(player); +}.bindenv(::LinGe.Hint); } // if (::LinGe.Hint.Config.friend.duration > 0) -::LinGe.Hint.ShowHint <- function ( text, level=0, target = "", activators = null, +::LinGe.Hint.ShowHint <- function ( text, level=0, target = "", showTo = null, duration = 0.0, icon = "icon_tip", color = "255 255 255") { + ::LinGe.DebugPrintl("ShowHint : " + text); + if (typeof target == "instance") + target = ::LinGe.GetEntityTargetname(target); EndHint(target); // 不允许同一目标上存在两个提示 if (!AtLeastOne(level)) return false; @@ -156,14 +255,15 @@ if (::LinGe.Hint.Config.friend.duration > 0) { hint_icon_offset = "0", hint_icon_onscreen = icon, hint_instance_type = "0", - hint_nooffscreen = "0", + hint_nooffscreen = Config.offscreenShow ? "0" : "1", hint_alphaoption = level>2 ? 1 : 0, // alphapulse 图标会变透明和可见的速度 0~3 hint_pulseoption = level>2 ? 1 : 0, // 图标效果,图标收缩的速度 0~3 hint_shakeoption = 0, // shaking 图标会抖动 0~2 hint_range = "0", hint_static = "0", // 跟随实体目标 hint_target = target, - hint_timeout = duration.tofloat(), // 持续时间,若为0则需要通过EndHint来关闭 + hint_timeout = 0.0, // 持续时间,若为0则需要通过EndHint来关闭 + // 不设置其为 duration 提示的关闭统一由本脚本用EndHint来控制 origin = Vector(0, 0, 0), angles = QAngle(0, 0, 0), targetname = "LinGe_" + UniqueString(), @@ -177,56 +277,71 @@ if (::LinGe.Hint.Config.friend.duration > 0) { } ent.ValidateScriptScope(); - if (null == activators || activators.len() == 0) + if (null == showTo || showTo.len() == 0) { DoEntFire("!self", "ShowHint", "", 0, null, ent); } else { - foreach (val in activators) + foreach (val in showTo) + { DoEntFire("!self", "ShowHint", "", 0, PlayerInstanceFromIndex(val), ent); + ::LinGe.DebugPrintl("显示给 " + PlayerInstanceFromIndex(val).GetPlayerName()); + } } CurrentHint.push({ level=level, ent=ent, targetname=target }); - if (hinttbl.hint_timeout > 0.0) + if (duration > 0.0 && !::LinGe.Debug) { - ::VSLib.Timers.AddTimerByName("EndHint_" + hinttbl.targetname, - hinttbl.hint_timeout, false, Timer_EndHint, CurrentHint.len()-1); + ::VSLib.Timers.AddTimerByName("EndHint_" + target, + duration, false, EndHint, target); } return true; } -// EndHint 去除提示 -::LinGe.Hint.EndHint <- function (params) +::LinGe.Hint.FindHintIndex <- function (params) { - local hintIdx = null; + local index = null; + if (typeof params == "instance") + params = params.GetName(); + if (typeof params == "integer") { - hintIdx = params; - if (hintIdx < 0 || hintIdx >= CurrentHint.len()) - throw "hintIdx 越界"; + index = params; + if (index < 0 || index >= CurrentHint.len()) + throw "索引越界"; } else if (typeof params == "string") { + if (params == "") + return null; foreach (idx, val in CurrentHint) { if (val.targetname == params) { - hintIdx = idx; + index = idx; break; } } - if (null == hintIdx) - return; + return index; } else throw "不能识别的参数类型"; - local hint = CurrentHint[hintIdx]; - ::VSLib.Timers.RemoveTimerByName("EndHint_" + hint.ent.GetName()); + return index; +} + +// EndHint 去除提示 +::LinGe.Hint.EndHint <- function (params) +{ + local idx = FindHintIndex(params); + if (null == idx) + return; + local hint = CurrentHint[idx]; + ::VSLib.Timers.RemoveTimerByName("EndHint_" + hint.targetname); // DoEntFire("!self", "EndHint", "", 0, null, hint.ent); DoEntFire("!self", "Kill", "", 0, null, hint.ent); - CurrentHint.remove(hintIdx); -} + CurrentHint.remove(idx); +}.bindenv(::LinGe.Hint); // 清理一个空位出来 若空位不足,则返回 false ::LinGe.Hint.AtLeastOne <- function (level)