├── .gitattributes
├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── plugin
├── CMakeLists.txt
├── LinGe_VScripts.cpp
├── LinGe_VScripts.h
├── LinGe_VScripts.vdf
├── licenses
│ ├── GPLv2.txt
│ ├── GPLv3.txt
│ └── LICENSE.txt
└── sdkapi
│ ├── MemoryUtils
│ ├── MemoryUtils.cpp
│ ├── MemoryUtils.h
│ ├── sm_platform.h
│ └── sm_symtable.h
│ ├── sdkapi.cpp
│ ├── sdkapi.h
│ └── signature.h
├── release
├── Base-addonimage.jpg
├── Base-addoninfo.txt
├── HUD-addonimage.jpg
├── HUD-addoninfo.txt
├── Hint-addonimage.jpg
├── Hint-addoninfo.txt
├── LinGe_VScripts-addonimage.jpg
├── LinGe_VScripts-addoninfo.txt
├── MoreSI-addonimage.jpg
├── MoreSI-addoninfo.txt
├── RewardHP-addonimage.jpg
├── RewardHP-addoninfo.txt
├── plugin.bat
├── vpk.bat
├── vpk
│ ├── LinGe VScripts 整合.vpk
│ ├── 击杀回血 RewardHP.vpk
│ ├── 基础库 Base.vpk
│ ├── 多特控制 MoreSI.vpk
│ ├── 排行榜、伤害统计 HUD.vpk
│ ├── 标记物资、队友倒地被控提示 Hint.vpk
│ └── 自杀指令 zs.vpk
├── zs-addonimage.jpg
└── zs-addoninfo.txt
└── vscripts
├── LinGe
├── Base.nut
├── HUD.nut
├── Hint.nut
├── MoreSI.nut
├── RewardHP.nut
├── VSLib.nut
├── VSLib
│ ├── easylogic.nut
│ ├── entity.nut
│ ├── fileio.nut
│ ├── hud.nut
│ ├── player.nut
│ ├── randomitemspawner.nut
│ ├── responserules.nut
│ ├── timer.nut
│ └── utils.nut
└── zs.nut
├── director_base_addon.nut
└── scriptedmode_addon.nut
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | !.vscode
2 | /release/*
3 | !/release/plugin.bat
4 | !/release/vpk.bat
5 | !/release/*-addoninfo.txt
6 | !/release/*-addonimage.jpg
7 |
8 | !/release/vpk/
9 | /release/vpk/*
10 | !/release/vpk/*.vpk
11 | /release/vpk/base.vpk
12 | /release/vpk/hint.vpk
13 | /release/vpk/hud.vpk
14 | /release/vpk/linge_vscripts.vpk
15 | /release/vpk/moresi.vpk
16 | /release/vpk/rewardhp.vpk
17 | /release/vpk/zs.vpk
18 |
19 | /plugin/*-build
20 |
21 | /note.txt
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cmake.sourceDirectory": "${workspaceFolder}/plugin",
3 | "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools",
4 | "cmake.buildDirectory": "${workspaceFolder}/plugin/${env.USER}-build"
5 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 LinGe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # LinGe VScripts
2 |
3 | 求生之路2使用脚本实现自定义特感数量与刷新间隔、伤害与击杀统计、友伤提示、HUD(排行榜、时间、服务器名等)、玩家状态提示、物品跟踪标记等等。最初只是用在自己服务器上的一套脚本,所以这套脚本私货挺多的,不过很多东西都做成了可配置的模式。
4 |
5 | 这是一套脚本 MOD,它是运行在服务端的。本地客户端作为房主开房会生效,并且作用于房间内所有玩家,而自己进入别人的房间是没有用的。
6 |
7 | 详细说明请阅 [GitHub-Wiki](https://github.com/Lin515/L4D2_LinGe_VScripts/wiki) 或者 [Gitee-Wiki](https://gitee.com/LinGe515/L4D2_LinGe_VScripts/wikis)
8 |
9 | ## 创意工坊
10 |
11 | 本系列脚本在创意工坊分开发布为以下多个 MOD,你可以只订阅以下所有 MOD 的[整合版](https://steamcommunity.com/sharedfiles/filedetails/?id=2587952986),也可以按自己的需求分开订阅:
12 |
13 | * [基础库](https://steamcommunity.com/sharedfiles/filedetails/?id=2819659703)
14 | 不管使用下面的哪个功能性 MOD,都必须同时订阅这个。
15 | * [HUD 伤害与击杀统计](https://steamcommunity.com/sharedfiles/filedetails/?id=2819660601)
16 | 可以在所有人的屏幕上显示排行榜、服务器名、时间等等,也可以在聊天窗输出排行榜以及友伤提示。
17 | * [多特控制](https://steamcommunity.com/sharedfiles/filedetails/?id=2819716701)
18 | 可以在游戏中随时更改特感的数量上限、刷新间隔、生成种类。
19 | * [标记与提示](https://steamcommunity.com/sharedfiles/filedetails/?edit=true&id=2819717120)
20 | 玩家可以发出标记来传递信息,几乎所有物品都可以标记。
21 | 玩家遇到倒地、黑白、被控时可以发出呼救,其他玩家可以看到显示在其身上的的提示。
22 | * [自杀指令](https://steamcommunity.com/sharedfiles/filedetails/?id=2819717317)
23 | 玩家可以通过发送 !zs 指令自杀。
24 | * [击杀回血](https://steamcommunity.com/sharedfiles/filedetails/?id=2956602969)
25 | 击杀特感或丧尸时使击杀者回血,可设置回复实血或虚血。
--------------------------------------------------------------------------------
/plugin/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.5)
2 |
3 | project(LinGe_VScripts LANGUAGES CXX)
4 |
5 | set(L4D2BIN ~/l4d2sv/bin) # 仅Linux下需要用到
6 | set(HL2SDKL4D2 ../../L4D2_Dev/hl2sdk-l4d2)
7 |
8 | set(CMAKE_INCLUDE_CURRENT_DIR ON)
9 | set(CMAKE_CXX_STANDARD 11)
10 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
11 |
12 | set(HL2PUB ${HL2SDKL4D2}/public)
13 | set(HL2GAME ${HL2SDKL4D2}/game)
14 |
15 | if(WIN32)
16 | link_directories(${HL2SDKL4D2}/lib/public)
17 | set(LINK_LIBRARY
18 | tier0
19 | vstdlib
20 | tier1
21 | tier2
22 | tier3
23 | mathlib
24 | legacy_stdio_definitions # vc++2015及以上需链接此库
25 | )
26 | add_compile_options(/source-charset:windows-1250)
27 | add_compile_options(/execution-charset:utf-8)
28 | add_compile_options(/MP)
29 | # 静态链接到CRT库
30 | string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
31 | string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
32 | string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_MINSIZEREL ${CMAKE_CXX_FLAGS_MINSIZEREL})
33 | string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
34 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:libc")
35 | set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:libcd")
36 | # set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:libcmt") # 如果动态链接到CRT库,需要忽略libcmt
37 | elseif(UNIX)
38 | link_directories(${L4D2BIN}) # 不要设置到 ${HL2SDKL4D2}/lib/linux .so需使用服务器最新
39 | get_filename_component(ABSLIB ${HL2SDKL4D2}/lib/linux ABSOLUTE)
40 | set(LINK_LIBRARY
41 | libtier0_srv.so
42 | libvstdlib_srv.so
43 | ${ABSLIB}/tier1_i486.a
44 | ${ABSLIB}/tier2_i486.a
45 | ${ABSLIB}/tier3_i486.a
46 | ${ABSLIB}/mathlib_i486.a
47 | )
48 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_LINUX -DL4D2 -m32 \
49 | -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \
50 | -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf \
51 | -D_alloca=alloca -Dstrcmpi=strcasecmp -DHAVE_STDINT_H -Wall -Wno-switch \
52 | -Wno-error=uninitialized -Wno-unused -Wno-error=delete-non-virtual-dtor \
53 | -Wno-class-memaccess -Wno-packed-not-aligned -mfpmath=sse -msse \
54 | -Wno-non-virtual-dtor -fno-rtti -fno-threadsafe-statics \
55 | -Wno-overloaded-virtual -fpermissive \
56 | -ldl -lm -static-libgcc -static-libstdc++"
57 | )
58 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -funroll-loops -pipe -fno-strict-aliasing")
59 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
60 | endif()
61 |
62 | # 创建库
63 | add_library(LinGe_VScripts SHARED)
64 |
65 | if(UNIX)
66 | set_target_properties(LinGe_VScripts PROPERTIES PREFIX "") # 去掉输出文件名的lib前缀
67 | endif()
68 |
69 | target_sources(LinGe_VScripts PRIVATE
70 | LinGe_VScripts.cpp
71 | sdkapi/MemoryUtils/MemoryUtils.cpp
72 | sdkapi/sdkapi.cpp
73 | )
74 |
75 | target_include_directories(LinGe_VScripts PRIVATE
76 | ${HL2PUB}
77 | ${HL2PUB}/tier0
78 | ${HL2PUB}/tier1
79 | ${HL2PUB}/tier2
80 | ${HL2PUB}/tier3
81 | ${HL2GAME}/shared
82 | ${HL2GAME}/server
83 | ${HL2GAME}/client
84 | ${HL2SDKL4D2}/common
85 | )
86 |
87 | target_link_libraries(LinGe_VScripts PRIVATE ${LINK_LIBRARY})
--------------------------------------------------------------------------------
/plugin/LinGe_VScripts.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * LinGe_VScripts
3 | * Copyright (C) 2021 LinGe All rights reserved.
4 | * =============================================================================
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License, version 3.0, as published by the
8 | * Free Software Foundation.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 | * details.
14 | *
15 | * You should have received a copy of the GNU General Public License along with
16 | * this program. If not, see .
17 | */
18 | #include
19 | #include
20 | #include
21 | #include "LinGe_VScripts.h"
22 | #include "sdkapi/sdkapi.h"
23 |
24 | LinGe_VScripts plugin;
25 | EXPOSE_SINGLE_INTERFACE_GLOBALVAR(LinGe_VScripts, IServerPluginCallbacks, INTERFACEVERSION_ISERVERPLUGINCALLBACKS, plugin);
26 |
27 | // ConVar
28 | ConVar cv_vscriptReturn("linge_vscript_return", "", FCVAR_HIDDEN|FCVAR_SPONLY, "Return VScript values.");
29 | ConVar cv_lookPing("linge_look_ping", "1", FCVAR_NOTIFY, "PlayerPing is executed when the 'vocalize smartlook' command is issued.", true, 0.0, true, 1.0, LinGe_VScripts::OnLookPingChanged);
30 | ConVar cv_time("linge_time", "", FCVAR_PRINTABLEONLY|FCVAR_SPONLY, "Server system time.");
31 | ConVar cv_format("linge_time_format", "%Y-%m-%d %H:%M:%S", FCVAR_NONE, "linge_time format string, see also:https://www.runoob.com/cprogramming/c-function-strftime.html", false, 0.0, false, 0.0, LinGe_VScripts::OnTimeFormatChanged);
32 | char g_sTimeFormat[50] = "%Y-%m-%d %H:%M:%S";
33 | bool g_bLookPing = true;
34 |
35 | LinGe_VScripts::LinGe_VScripts() : m_iClientCommandIndex(0), m_bPlayerPingLoaded(false)
36 | {
37 | }
38 | LinGe_VScripts::~LinGe_VScripts() {}
39 |
40 | bool LinGe_VScripts::Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory)
41 | {
42 | SDKAPI::Initialize(interfaceFactory, gameServerFactory);
43 |
44 | ConVar_Register();
45 |
46 | PL_Msg("Loaded.\n");
47 | return true;
48 | }
49 | void LinGe_VScripts::Unload(void)
50 | {
51 | SDKAPI::iGameEventManager->RemoveListener(this);
52 |
53 | ConVar_Unregister();
54 | SDKAPI::UnInitialize();
55 | }
56 |
57 | const char *LinGe_VScripts::GetPluginDescription(void) {
58 | return PLNAME " " PLVER " By LinGe";
59 | }
60 |
61 | void LinGe_VScripts::GameFrame(bool simulating)
62 | {
63 | // 每 1s 更新一次 linge_time
64 | static time_t oldTime = 0, nowTime = 0;
65 | static char buffer[50];
66 | time(&nowTime);
67 | if (nowTime - oldTime >= 1)
68 | {
69 | if (strftime(buffer, sizeof(buffer), g_sTimeFormat, localtime(&nowTime)))
70 | cv_time.SetValue(buffer);
71 | else
72 | cv_time.SetValue("ERROR");
73 | oldTime = nowTime;
74 | }
75 | }
76 |
77 | void LinGe_VScripts::LevelInit(char const *pMapName) {
78 | SDKAPI::iGameEventManager->AddListener(this, "round_start", true);
79 | }
80 | void LinGe_VScripts::LevelShutdown(void) {
81 | SDKAPI::iGameEventManager->RemoveListener(this);
82 | }
83 |
84 | void LinGe_VScripts::FireGameEvent(IGameEvent * event)
85 | {
86 | const char *name = event->GetName();
87 | if (Q_stricmp(name, "round_start") == 0)
88 | {
89 | // 验证根表下是否存在 LinPlayerPing
90 | SDKAPI::L4D2_RunScript("Convars.SetValue(\"linge_vscript_return\", getroottable().rawin(\"LinPlayerPing\"));");
91 | if (cv_vscriptReturn.GetBool())
92 | {
93 | m_bPlayerPingLoaded = true;
94 | PL_DevMsg("LinPlayerPing found.\n");
95 | }
96 | else
97 | {
98 | m_bPlayerPingLoaded = false;
99 | PL_DevMsg("LinPlayerPing not found.\n");
100 | }
101 | }
102 | }
103 |
104 | void LinGe_VScripts::ServerActivate(edict_t *pEdictList, int edictCount, int clientMax) {}
105 |
106 | // 监测 vocalize smartlook
107 | PLUGIN_RESULT LinGe_VScripts::ClientCommand(edict_t *pEntity, const CCommand &args)
108 | {
109 | if ( !pEntity || pEntity->IsFree() )
110 | return PLUGIN_CONTINUE;
111 | if (m_bPlayerPingLoaded && g_bLookPing)
112 | {
113 | if (args.ArgC() >= 2 && Q_stricmp(args[0], "vocalize") == 0
114 | && Q_stricmp(args[1], "smartlook") == 0
115 | && (args.ArgC() == 2 || Q_stricmp(args[2], "auto") != 0) )
116 | // 游戏自动让人物发出该指令时,第三个参数会为 auto
117 | {
118 | IPlayerInfo *player = SDKAPI::iPlayerInfoManager->GetPlayerInfo(pEntity);
119 | if (player->IsPlayer() && player->GetTeamIndex() == 2
120 | && !player->IsFakeClient() && !player->IsDead())
121 | {
122 | PL_DevMsg("%s PlayerPing\n", player->GetName());
123 | SDKAPI::L4D2_RunScript("::LinPlayerPing(%d);", player->GetUserID());
124 | }
125 | }
126 | }
127 |
128 | return PLUGIN_CONTINUE;
129 | }
130 |
131 | // 插件控制台变量发生改变
132 | void LinGe_VScripts::OnLookPingChanged(IConVar *var, const char *pOldValue, float flOldValue)
133 | {
134 | g_bLookPing = cv_lookPing.GetBool();
135 | }
136 | void LinGe_VScripts::OnTimeFormatChanged(IConVar *var, const char *pOldValue, float flOldValue)
137 | {
138 | strncpy(g_sTimeFormat, cv_format.GetString(), sizeof(g_sTimeFormat) - 1);
139 | g_sTimeFormat[sizeof(g_sTimeFormat) - 1] = '\0';
140 | }
141 |
142 | void LinGe_VScripts::Pause(void) {}
143 | void LinGe_VScripts::UnPause(void) {}
144 | void LinGe_VScripts::ClientActive(edict_t *pEntity) {}
145 | void LinGe_VScripts::ClientDisconnect(edict_t *pEntity) {}
146 | void LinGe_VScripts::OnQueryCvarValueFinished(QueryCvarCookie_t iCookie, edict_t *pPlayerEntity,
147 | EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue) {}
148 | void LinGe_VScripts::ClientPutInServer(edict_t *pEntity, const char *playername) {}
149 | void LinGe_VScripts::SetCommandClient(int index) {
150 | m_iClientCommandIndex = index;
151 | }
152 | void LinGe_VScripts::ClientSettingsChanged(edict_t *pEdict) {}
153 | PLUGIN_RESULT LinGe_VScripts::ClientConnect(bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen) {
154 | return PLUGIN_CONTINUE;
155 | }
156 | PLUGIN_RESULT LinGe_VScripts::NetworkIDValidated(const char *pszUserName, const char *pszNetworkID) {
157 | return PLUGIN_CONTINUE;
158 | }
159 | void LinGe_VScripts::OnEdictAllocated(edict_t *edict) {}
160 | void LinGe_VScripts::OnEdictFreed(const edict_t *edict) {}
--------------------------------------------------------------------------------
/plugin/LinGe_VScripts.h:
--------------------------------------------------------------------------------
1 | /**
2 | * LinGe_VScripts
3 | * Copyright (C) 2021 LinGe All rights reserved.
4 | * =============================================================================
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License, version 3.0, as published by the
8 | * Free Software Foundation.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 | * details.
14 | *
15 | * You should have received a copy of the GNU General Public License along with
16 | * this program. If not, see .
17 | */
18 | #pragma once
19 | #include
20 | #include
21 | #include
22 | #define PLNAME "LinGe_VScripts"
23 | #define PLVER "v2.7.0"
24 |
25 | #define PL_Msg(format, ...) Msg(PLNAME ": " format, ## __VA_ARGS__)
26 | #define PL_Warning(format, ...) Warning(PLNAME ": " format, ## __VA_ARGS__)
27 | #define PL_Error(format, ...) Error(PLNAME ": " format, ## __VA_ARGS__)
28 | #define PL_DevMsg(format, ...) DevMsg(PLNAME ": " format, ## __VA_ARGS__)
29 |
30 | class LinGe_VScripts : public IServerPluginCallbacks, public IGameEventListener2
31 | {
32 | public:
33 | LinGe_VScripts();
34 | ~LinGe_VScripts();
35 |
36 | // IServerPluginCallbacks methods
37 | virtual bool Load(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory);
38 | virtual void Unload(void);
39 | virtual void Pause(void);
40 | virtual void UnPause(void);
41 | virtual const char * GetPluginDescription(void);
42 | virtual void LevelInit(char const *pMapName);
43 | virtual void ServerActivate(edict_t *pEdictList, int edictCount, int clientMax);
44 | virtual void GameFrame(bool simulating);
45 | virtual void LevelShutdown(void);
46 | virtual void ClientActive(edict_t *pEntity);
47 | virtual void ClientDisconnect(edict_t *pEntity);
48 | virtual void ClientPutInServer(edict_t *pEntity, char const *playername);
49 | virtual void SetCommandClient(int index);
50 | virtual void ClientSettingsChanged(edict_t *pEdict);
51 | virtual PLUGIN_RESULT ClientConnect(bool *bAllowConnect, edict_t *pEntity, const char *pszName, const char *pszAddress, char *reject, int maxrejectlen);
52 | virtual PLUGIN_RESULT ClientCommand(edict_t *pEntity, const CCommand &args);
53 | virtual PLUGIN_RESULT NetworkIDValidated(const char *pszUserName, const char *pszNetworkID);
54 | virtual void OnQueryCvarValueFinished(QueryCvarCookie_t iCookie, edict_t *pPlayerEntity, EQueryCvarValueStatus eStatus, const char *pCvarName, const char *pCvarValue);
55 |
56 | // added with version 3 of the interface.
57 | virtual void OnEdictAllocated(edict_t *edict);
58 | virtual void OnEdictFreed(const edict_t *edict);
59 |
60 | // IGameEventListener Interface
61 | virtual void FireGameEvent( IGameEvent * event );
62 | virtual int GetEventDebugID() { return EVENT_DEBUG_ID_INIT; }
63 | virtual int GetCommandIndex() { return m_iClientCommandIndex; }
64 |
65 | private:
66 | int m_iClientCommandIndex;
67 | bool m_bPlayerPingLoaded;
68 |
69 | public:
70 | static void OnLookPingChanged(IConVar *var, const char *pOldValue, float flOldValue);
71 | static void OnTimeFormatChanged(IConVar *var, const char *pOldValue, float flOldValue);
72 | };
--------------------------------------------------------------------------------
/plugin/LinGe_VScripts.vdf:
--------------------------------------------------------------------------------
1 | "Plugin"
2 | {
3 | "file" "addons/LinGe_VScripts/LinGe_VScripts"
4 | }
5 |
6 |
--------------------------------------------------------------------------------
/plugin/licenses/GPLv2.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C)
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | , 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/plugin/licenses/GPLv3.txt:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/plugin/licenses/LICENSE.txt:
--------------------------------------------------------------------------------
1 | SOURCEMOD LICENSE INFORMATION
2 | VERSION: 2019-9-30
3 | -----------------------------
4 |
5 | SourceMod is licensed under the GNU General Public License, version 3.
6 |
7 | As a special exception, AlliedModders LLC gives you permission to link the code
8 | of this program (as well as its derivative works) to "Half-Life 2," the "Source
9 | Engine" and any Game MODs that run on software by the Valve Corporation.
10 | You must obey the GNU General Public License in all respects for all other code used.
11 | Additionally, AlliedModders LLC grants this exception to all derivative works.
12 |
13 | As an additional special exception to the GNU General Public License 3.0,
14 | AlliedModders LLC permits dual-licensing of DERIVATIVE WORKS ONLY (that is,
15 | SourcePawn/SourceMod Plugins and SourceMod Extensions, or any software built
16 | from the SourceMod SDK or header files) under the GNU General Public License
17 | version 2 "or any higher version." As such, you may choose for your derivative
18 | work(s) to be compatible with the GNU General Public License version 2 as long
19 | as it is also compatible with the GNU General Public License version 3, via the
20 | "or any higher version" clause. This is intended for compatibility with other
21 | software.
22 |
23 | As a final exception to the above, any derivative works created prior to this
24 | date (July 31, 2007) may be exclusively licensed under the GNU General Public
25 | License version 2 (without an "or any higher version" clause) if and only if
26 | the work was already GNU General Public License 2.0 exclusive. This clause is
27 | provided for backwards compatibility only.
28 |
29 | A copy of the GNU General Public License 2.0 is available in GPLv2.txt.
30 | A copy of the GNU General Public License 3.0 is available in GPLv3.txt.
31 |
32 | SourcePawn is Copyright (C) 2006-2008 AlliedModders LLC. All rights reserved.
33 | SourceMod is Copyright (C) 2006-2008 AlliedModders LLC. All rights reserved.
34 | Pawn and SMALL are Copyright (C) 1997-2008 ITB CompuPhase.
35 | Source is Copyright (C) Valve Corporation.
36 | All trademarks are property of their respective owners in the US and other countries.
37 |
--------------------------------------------------------------------------------
/plugin/sdkapi/MemoryUtils/MemoryUtils.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * vim: set ts=4 sw=4 tw=99 noet :
3 | * =============================================================================
4 | * SourceMod
5 | * Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved.
6 | * =============================================================================
7 | *
8 | * This program is free software; you can redistribute it and/or modify it under
9 | * the terms of the GNU General Public License, version 3.0, as published by the
10 | * Free Software Foundation.
11 | *
12 | * This program is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 | * details.
16 | *
17 | * You should have received a copy of the GNU General Public License along with
18 | * this program. If not, see .
19 | *
20 | * As a special exception, AlliedModders LLC gives you permission to link the
21 | * code of this program (as well as its derivative works) to "Half-Life 2," the
22 | * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 | * by the Valve Corporation. You must obey the GNU General Public License in
24 | * all respects for all other code used. Additionally, AlliedModders LLC grants
25 | * this exception to all derivative works. AlliedModders LLC defines further
26 | * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 | * or .
28 | */
29 | // 修改自 sourcemod/core/logic/MemoryUtils.cpp
30 | // https://github.com/alliedmodders/sourcemod
31 |
32 | #include "MemoryUtils.h"
33 | #ifdef PLATFORM_LINUX
34 | #include
35 | #include
36 | #include
37 | #include
38 |
39 | #define PAGE_SIZE 4096
40 | #define PAGE_ALIGN_UP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
41 | #endif
42 |
43 | MemoryUtils::MemoryUtils(CreateInterfaceFn factory) :
44 | isAvailable(false), factory(nullptr)
45 | {
46 | if (factory)
47 | Init(factory);
48 | }
49 |
50 | bool MemoryUtils::Init(CreateInterfaceFn factory)
51 | {
52 | this->factory = factory;
53 | isAvailable = MemoryUtils::GetLibraryInfo((void *)factory, this->lib);
54 | return isAvailable;
55 | }
56 |
57 | bool MemoryUtils::IsAvailable()
58 | {
59 | return isAvailable;
60 | }
61 |
62 | void *MemoryUtils::FindPattern(const char *pattern)
63 | {
64 | if (!this->isAvailable)
65 | return nullptr;
66 |
67 | bool found;
68 | char *ptr, *end;
69 | size_t len = strlen(pattern);
70 |
71 | ptr = reinterpret_cast(lib.baseAddress);
72 | end = ptr + lib.memorySize - len;
73 |
74 | while (ptr < end)
75 | {
76 | found = true;
77 | for (register size_t i = 0; i < len; i++)
78 | {
79 | if (pattern[i] != '\x2A' && pattern[i] != ptr[i])
80 | {
81 | found = false;
82 | break;
83 | }
84 | }
85 |
86 | if (found)
87 | return ptr;
88 |
89 | ptr++;
90 | }
91 |
92 | return nullptr;
93 | }
94 |
95 | void *MemoryUtils::ResolveSymbol(const char *symbol)
96 | {
97 | if (!this->isAvailable)
98 | return nullptr;
99 |
100 | HMODULE handle = this->lib.handle;
101 | #ifdef WIN32
102 | return GetProcAddress(handle, symbol);
103 | #elif defined PLATFORM_LINUX
104 |
105 | #ifdef PLATFORM_X86
106 | typedef Elf32_Ehdr ElfHeader;
107 | typedef Elf32_Shdr ElfSHeader;
108 | typedef Elf32_Sym ElfSymbol;
109 | #define ELF_SYM_TYPE ELF32_ST_TYPE
110 | #else
111 | typedef Elf64_Ehdr ElfHeader;
112 | typedef Elf64_Shdr ElfSHeader;
113 | typedef Elf64_Sym ElfSymbol;
114 | #define ELF_SYM_TYPE ELF64_ST_TYPE
115 | #endif
116 |
117 | struct link_map *dlmap;
118 | struct stat dlstat;
119 | int dlfile;
120 | uintptr_t map_base;
121 | ElfHeader *file_hdr;
122 | ElfSHeader *sections, *shstrtab_hdr, *symtab_hdr, *strtab_hdr;
123 | ElfSymbol *symtab;
124 | const char *shstrtab, *strtab;
125 | uint16_t section_count;
126 | uint32_t symbol_count;
127 | SymbolTable *table;
128 | Symbol *symbol_entry;
129 |
130 | dlmap = (struct link_map *)handle;
131 | symtab_hdr = nullptr;
132 | strtab_hdr = nullptr;
133 | table = nullptr;
134 |
135 | /* See if we already have a symbol table for this library */
136 | if (m_SymTable.lib_base == dlmap->l_addr)
137 | table = &m_SymTable.table;
138 |
139 | /* If we don't have a symbol table for this library, then create one */
140 | if (table == nullptr)
141 | {
142 | m_SymTable.table.Initialize();
143 | m_SymTable.lib_base = dlmap->l_addr;
144 | m_SymTable.last_pos = 0;
145 | table = &m_SymTable.table;
146 | }
147 |
148 | /* See if the symbol is already cached in our table */
149 | symbol_entry = table->FindSymbol(symbol, strlen(symbol));
150 | if (symbol_entry != nullptr)
151 | {
152 | return symbol_entry->address;
153 | }
154 |
155 | /* If symbol isn't in our table, then we have open the actual library */
156 | dlfile = open(dlmap->l_name, O_RDONLY);
157 | if (dlfile == -1 || fstat(dlfile, &dlstat) == -1)
158 | {
159 | close(dlfile);
160 | return nullptr;
161 | }
162 |
163 | /* Map library file into memory */
164 | file_hdr = (ElfHeader *)mmap(nullptr, dlstat.st_size, PROT_READ, MAP_PRIVATE, dlfile, 0);
165 | map_base = (uintptr_t)file_hdr;
166 | if (file_hdr == MAP_FAILED)
167 | {
168 | close(dlfile);
169 | return nullptr;
170 | }
171 | close(dlfile);
172 |
173 | if (file_hdr->e_shoff == 0 || file_hdr->e_shstrndx == SHN_UNDEF)
174 | {
175 | munmap(file_hdr, dlstat.st_size);
176 | return nullptr;
177 | }
178 |
179 | sections = (ElfSHeader *)(map_base + file_hdr->e_shoff);
180 | section_count = file_hdr->e_shnum;
181 | /* Get ELF section header string table */
182 | shstrtab_hdr = §ions[file_hdr->e_shstrndx];
183 | shstrtab = (const char *)(map_base + shstrtab_hdr->sh_offset);
184 |
185 | /* Iterate sections while looking for ELF symbol table and string table */
186 | for (uint16_t i = 0; i < section_count; i++)
187 | {
188 | ElfSHeader &hdr = sections[i];
189 | const char *section_name = shstrtab + hdr.sh_name;
190 |
191 | if (strcmp(section_name, ".symtab") == 0)
192 | {
193 | symtab_hdr = &hdr;
194 | }
195 | else if (strcmp(section_name, ".strtab") == 0)
196 | {
197 | strtab_hdr = &hdr;
198 | }
199 | }
200 |
201 | /* Uh oh, we don't have a symbol table or a string table */
202 | if (symtab_hdr == nullptr || strtab_hdr == nullptr)
203 | {
204 | munmap(file_hdr, dlstat.st_size);
205 | return nullptr;
206 | }
207 |
208 | symtab = (ElfSymbol *)(map_base + symtab_hdr->sh_offset);
209 | strtab = (const char *)(map_base + strtab_hdr->sh_offset);
210 | symbol_count = symtab_hdr->sh_size / symtab_hdr->sh_entsize;
211 |
212 | /* Iterate symbol table starting from the position we were at last time */
213 | for (uint32_t i = m_SymTable.last_pos; i < symbol_count; i++)
214 | {
215 | ElfSymbol &sym = symtab[i];
216 | unsigned char sym_type = ELF_SYM_TYPE(sym.st_info);
217 | const char *sym_name = strtab + sym.st_name;
218 | Symbol *cur_sym;
219 |
220 | /* Skip symbols that are undefined or do not refer to functions or objects */
221 | if (sym.st_shndx == SHN_UNDEF || (sym_type != STT_FUNC && sym_type != STT_OBJECT))
222 | {
223 | continue;
224 | }
225 |
226 | /* Caching symbols as we go along */
227 | cur_sym = table->InternSymbol(sym_name, strlen(sym_name), (void *)(dlmap->l_addr + sym.st_value));
228 | if (strcmp(symbol, sym_name) == 0)
229 | {
230 | symbol_entry = cur_sym;
231 | m_SymTable.last_pos = ++i;
232 | break;
233 | }
234 | }
235 |
236 | munmap(file_hdr, dlstat.st_size);
237 | return symbol_entry ? symbol_entry->address : nullptr;
238 |
239 | #endif
240 | }
241 |
242 | bool MemoryUtils::GetLibraryInfo(const void *libPtr, DynLibInfo &lib)
243 | {
244 | uintptr_t baseAddr;
245 |
246 | if (libPtr == nullptr)
247 | {
248 | return false;
249 | }
250 |
251 | #ifdef WIN32
252 |
253 | #ifdef PLATFORM_X86
254 | const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_I386;
255 | const WORD PE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR32_MAGIC;
256 | #else
257 | const WORD PE_FILE_MACHINE = IMAGE_FILE_MACHINE_AMD64;
258 | const WORD PE_NT_OPTIONAL_HDR_MAGIC = IMAGE_NT_OPTIONAL_HDR64_MAGIC;
259 | #endif
260 |
261 | MEMORY_BASIC_INFORMATION info;
262 | IMAGE_DOS_HEADER *dos;
263 | IMAGE_NT_HEADERS *pe;
264 | IMAGE_FILE_HEADER *file;
265 | IMAGE_OPTIONAL_HEADER *opt;
266 |
267 | if (!VirtualQuery(libPtr, &info, sizeof(MEMORY_BASIC_INFORMATION)))
268 | {
269 | return false;
270 | }
271 |
272 | baseAddr = reinterpret_cast(info.AllocationBase);
273 |
274 | /* All this is for our insane sanity checks :o */
275 | dos = reinterpret_cast(baseAddr);
276 | pe = reinterpret_cast(baseAddr + dos->e_lfanew);
277 | file = &pe->FileHeader;
278 | opt = &pe->OptionalHeader;
279 |
280 | /* Check PE magic and signature */
281 | if (dos->e_magic != IMAGE_DOS_SIGNATURE || pe->Signature != IMAGE_NT_SIGNATURE || opt->Magic != PE_NT_OPTIONAL_HDR_MAGIC)
282 | {
283 | return false;
284 | }
285 |
286 | /* Check architecture */
287 | if (file->Machine != PE_FILE_MACHINE)
288 | {
289 | return false;
290 | }
291 |
292 | /* For our purposes, this must be a dynamic library */
293 | if ((file->Characteristics & IMAGE_FILE_DLL) == 0)
294 | {
295 | return false;
296 | }
297 |
298 | /* Finally, we can do this */
299 | lib.memorySize = opt->SizeOfImage;
300 | lib.handle = (HMODULE)info.AllocationBase;
301 |
302 | #elif defined PLATFORM_LINUX
303 |
304 | #ifdef PLATFORM_X86
305 | typedef Elf32_Ehdr ElfHeader;
306 | typedef Elf32_Phdr ElfPHeader;
307 | const unsigned char ELF_CLASS = ELFCLASS32;
308 | const uint16_t ELF_MACHINE = EM_386;
309 | #else
310 | typedef Elf64_Ehdr ElfHeader;
311 | typedef Elf64_Phdr ElfPHeader;
312 | const unsigned char ELF_CLASS = ELFCLASS64;
313 | const uint16_t ELF_MACHINE = EM_X86_64;
314 | #endif
315 |
316 | Dl_info info;
317 | ElfHeader *file;
318 | ElfPHeader *phdr;
319 | uint16_t phdrCount;
320 |
321 | if (!dladdr(libPtr, &info))
322 | {
323 | return false;
324 | }
325 |
326 | if (!info.dli_fbase || !info.dli_fname)
327 | {
328 | return false;
329 | }
330 |
331 | /* This is for our insane sanity checks :o */
332 | baseAddr = reinterpret_cast(info.dli_fbase);
333 | file = reinterpret_cast(baseAddr);
334 |
335 | /* Check ELF magic */
336 | if (memcmp(ELFMAG, file->e_ident, SELFMAG) != 0)
337 | {
338 | return false;
339 | }
340 |
341 | /* Check ELF version */
342 | if (file->e_ident[EI_VERSION] != EV_CURRENT)
343 | {
344 | return false;
345 | }
346 |
347 | /* Check ELF endianness */
348 | if (file->e_ident[EI_DATA] != ELFDATA2LSB)
349 | {
350 | return false;
351 | }
352 |
353 | /* Check ELF architecture */
354 | if (file->e_ident[EI_CLASS] != ELF_CLASS || file->e_machine != ELF_MACHINE)
355 | {
356 | return false;
357 | }
358 |
359 | /* For our purposes, this must be a dynamic library/shared object */
360 | if (file->e_type != ET_DYN)
361 | {
362 | return false;
363 | }
364 |
365 | phdrCount = file->e_phnum;
366 | phdr = reinterpret_cast(baseAddr + file->e_phoff);
367 |
368 | for (uint16_t i = 0; i < phdrCount; i++)
369 | {
370 | ElfPHeader &hdr = phdr[i];
371 |
372 | /* We only really care about the segment with executable code */
373 | if (hdr.p_type == PT_LOAD && hdr.p_flags == (PF_X | PF_R))
374 | {
375 | /* From glibc, elf/dl-load.c:
376 | * c->mapend = ((ph->p_vaddr + ph->p_filesz + GLRO(dl_pagesize) - 1)
377 | * & ~(GLRO(dl_pagesize) - 1));
378 | *
379 | * In glibc, the segment file size is aligned up to the nearest page size and
380 | * added to the virtual address of the segment. We just want the size here.
381 | */
382 | lib.memorySize = PAGE_ALIGN_UP(hdr.p_filesz);
383 | break;
384 | }
385 | }
386 |
387 | // 获取句柄
388 | HMODULE handle = dlopen(info.dli_fname, RTLD_NOW);
389 | if (!handle)
390 | return false;
391 | dlclose(handle);
392 | lib.handle = handle;
393 |
394 | #endif
395 | lib.baseAddress = reinterpret_cast(baseAddr);
396 | return true;
397 | }
398 |
--------------------------------------------------------------------------------
/plugin/sdkapi/MemoryUtils/MemoryUtils.h:
--------------------------------------------------------------------------------
1 | /**
2 | * vim: set ts=4 sw=4 tw=99 noet :
3 | * =============================================================================
4 | * SourceMod
5 | * Copyright (C) 2004-2011 AlliedModders LLC. All rights reserved.
6 | * =============================================================================
7 | *
8 | * This program is free software; you can redistribute it and/or modify it under
9 | * the terms of the GNU General Public License, version 3.0, as published by the
10 | * Free Software Foundation.
11 | *
12 | * This program is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 | * details.
16 | *
17 | * You should have received a copy of the GNU General Public License along with
18 | * this program. If not, see .
19 | *
20 | * As a special exception, AlliedModders LLC gives you permission to link the
21 | * code of this program (as well as its derivative works) to "Half-Life 2," the
22 | * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 | * by the Valve Corporation. You must obey the GNU General Public License in
24 | * all respects for all other code used. Additionally, AlliedModders LLC grants
25 | * this exception to all derivative works. AlliedModders LLC defines further
26 | * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 | * or .
28 | */
29 | // 修改自 sourcemod/core/logic/MemoryUtils.h
30 | // https://github.com/alliedmodders/sourcemod
31 |
32 | #ifndef _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
33 | #define _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
34 | #include "sm_platform.h"
35 | #include
36 | #include
37 |
38 | #if defined PLATFORM_LINUX
39 | #include "sm_symtable.h"
40 | #endif
41 |
42 | struct VTableIndex {
43 | int Windows;
44 | int Linux;
45 | };
46 |
47 | // 从虚函数表获取指定的虚函数
48 | template
49 | inline Fn GetVirtualFunction(void *base, VTableIndex index)
50 | {
51 | // 将 base 对象基址直接转换为指向虚函数表的指针
52 | std::uintptr_t **pVTable = (std::uintptr_t **)base;
53 | // 从虚函数表获取对应的虚函数指针
54 | #ifdef WIN32
55 | return reinterpret_cast((*pVTable)[index.Windows]);
56 | #elif defined _LINUX
57 | return reinterpret_cast((*pVTable)[index.Linux]);
58 | #endif
59 | }
60 |
61 | struct Signature {
62 | const char *Windows;
63 | const char *Linux;
64 | };
65 |
66 | struct DynLibInfo
67 | {
68 | void *baseAddress;
69 | size_t memorySize;
70 | HMODULE handle;
71 | };
72 |
73 | #if defined PLATFORM_LINUX
74 | struct LibSymbolTable
75 | {
76 | SymbolTable table;
77 | uintptr_t lib_base;
78 | uint32_t last_pos;
79 | };
80 | #endif
81 |
82 | class MemoryUtils
83 | {
84 | public:
85 | MemoryUtils(CreateInterfaceFn factory = nullptr);
86 | bool Init(CreateInterfaceFn factory);
87 | bool IsAvailable();
88 | static bool GetLibraryInfo(const void *libPtr, DynLibInfo &lib);
89 |
90 | private:
91 | bool isAvailable;
92 | CreateInterfaceFn factory;
93 | DynLibInfo lib;
94 | #ifdef PLATFORM_LINUX
95 | LibSymbolTable m_SymTable;
96 | #endif
97 |
98 | public:
99 | void *FindPattern(const char *pattern);
100 | void *ResolveSymbol(const char *symbol);
101 |
102 | template
103 | inline Fn FindSignature(Signature signature)
104 | {
105 | #ifdef WIN32
106 | return reinterpret_cast(FindPattern(signature.Windows));
107 | #elif defined PLATFORM_LINUX
108 | if (signature.Linux[0] == '@')
109 | return reinterpret_cast(ResolveSymbol(&signature.Linux[1]));
110 | else
111 | return reinterpret_cast(FindPattern(signature.Linux));
112 | #endif
113 | }
114 | };
115 |
116 | #endif // _INCLUDE_SOURCEMOD_MEMORYUTILS_H_
117 |
--------------------------------------------------------------------------------
/plugin/sdkapi/MemoryUtils/sm_platform.h:
--------------------------------------------------------------------------------
1 | /**
2 | * vim: set ts=4 :
3 | * =============================================================================
4 | * SourceMod
5 | * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
6 | * =============================================================================
7 | *
8 | * This program is free software; you can redistribute it and/or modify it under
9 | * the terms of the GNU General Public License, version 3.0, as published by the
10 | * Free Software Foundation.
11 | *
12 | * This program is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 | * details.
16 | *
17 | * You should have received a copy of the GNU General Public License along with
18 | * this program. If not, see .
19 | *
20 | * As a special exception, AlliedModders LLC gives you permission to link the
21 | * code of this program (as well as its derivative works) to "Half-Life 2," the
22 | * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 | * by the Valve Corporation. You must obey the GNU General Public License in
24 | * all respects for all other code used. Additionally, AlliedModders LLC grants
25 | * this exception to all derivative works. AlliedModders LLC defines further
26 | * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 | * or .
28 | *
29 | * Version: $Id$
30 | */
31 |
32 | #ifndef _INCLUDE_SOURCEMOD_PLATFORM_H_
33 | #define _INCLUDE_SOURCEMOD_PLATFORM_H_
34 |
35 | /**
36 | * @file sm_platform.h
37 | * @brief Contains platform-specific macros for abstraction.
38 | */
39 |
40 | #if defined WIN32 || defined WIN64
41 | #ifndef PLATFORM_WINDOWS
42 | #define PLATFORM_WINDOWS 1
43 | #endif
44 |
45 | #if defined WIN64 || defined _WIN64
46 | #ifndef PLATFORM_X64
47 | # define PLATFORM_X64 1
48 | #endif
49 | #else
50 | #ifndef PLATFORM_X86
51 | # define PLATFORM_X86 1
52 | #endif
53 | #endif // defined WIN64 || defined _WIN64
54 |
55 | #if !defined WIN32_LEAN_AND_MEAN
56 | #define WIN32_LEAN_AND_MEAN
57 | #endif
58 | #if !defined snprintf && defined _MSC_VER && _MSC_VER < 1900
59 | #define snprintf _snprintf
60 | #endif
61 | #if !defined stat
62 | #define stat _stat
63 | #endif
64 | #define strcasecmp strcmpi
65 | #define strncasecmp strnicmp
66 | #include
67 | #include
68 | #define PLATFORM_LIB_EXT "dll"
69 | #define PLATFORM_MAX_PATH MAX_PATH
70 | #define PLATFORM_SEP_CHAR '\\'
71 | #define PLATFORM_SEP_ALTCHAR '/'
72 | #define PLATFORM_SEP "\\"
73 | #define PLATFORM_EXTERN_C extern "C" __declspec(dllexport)
74 | #elif defined __linux__ || defined __APPLE__
75 | #if defined __linux__
76 | # define PLATFORM_LINUX 1
77 | # define PLATFORM_LIB_EXT "so"
78 | #elif defined __APPLE__
79 | # define PLATFORM_APPLE 1
80 | # define PLATFORM_LIB_EXT "dylib"
81 | #endif
82 | #ifndef PLATFORM_POSIX
83 | # define PLATFORM_POSIX 1
84 | #endif
85 |
86 | #if defined __x86_64__
87 | #ifndef PLATFORM_X64
88 | # define PLATFORM_X64 1
89 | #endif
90 | #else
91 | #ifndef PLATFORM_X86
92 | # define PLATFORM_X86 1
93 | #endif
94 | #endif // defined __x86_64__
95 |
96 | #include
97 | #include
98 | #include
99 | #include
100 | #include
101 | #if defined PLATFORM_APPLE
102 | #include
103 | #endif
104 | #define PLATFORM_MAX_PATH PATH_MAX
105 | #define PLATFORM_SEP_CHAR '/'
106 | #define PLATFORM_SEP_ALTCHAR '\\'
107 | #define PLATFORM_SEP "/"
108 | #define PLATFORM_EXTERN_C extern "C" __attribute__((visibility("default")))
109 | #endif
110 |
111 | #if !defined SOURCEMOD_BUILD
112 | #define SOURCEMOD_BUILD
113 | #endif
114 |
115 | #if !defined SM_ARRAYSIZE
116 | #define SM_ARRAYSIZE(x) ((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
117 | #endif
118 |
119 | #if defined PLATFORM_X64
120 | #define PLATFORM_ARCH_FOLDER "x64" PLATFORM_SEP
121 | #ifdef PLATFORM_WINDOWS
122 | #define PLATFORM_FOLDER "win64" PLATFORM_SEP
123 | #elif defined PLATFORM_LINUX
124 | #define PLATFORM_FOLDER "linux64" PLATFORM_SEP
125 | #elif defined PLATFORM_APPLE
126 | #define PLATFORM_FOLDER "osx64" PLATFORM_SEP
127 | #endif
128 | #else
129 | #define PLATFORM_ARCH_FOLDER ""
130 | #ifdef PLATFORM_WINDOWS
131 | #define PLATFORM_FOLDER "win32" PLATFORM_SEP
132 | #elif defined PLATFORM_LINUX
133 | #define PLATFORM_FOLDER "linux32" PLATFORM_SEP
134 | #elif defined PLATFORM_APPLE
135 | #define PLATFORM_FOLDER "osx32" PLATFORM_SEP
136 | #endif
137 | #endif // defined PLATFORM_X64
138 |
139 | #endif //_INCLUDE_SOURCEMOD_PLATFORM_H_
140 |
141 |
--------------------------------------------------------------------------------
/plugin/sdkapi/MemoryUtils/sm_symtable.h:
--------------------------------------------------------------------------------
1 | /**
2 | * vim: set ts=4 sw=4 tw=99 noet :
3 | * =============================================================================
4 | * SourceMod
5 | * Copyright (C) 2004-2009 AlliedModders LLC. All rights reserved.
6 | * =============================================================================
7 | *
8 | * This program is free software; you can redistribute it and/or modify it under
9 | * the terms of the GNU General Public License, version 3.0, as published by the
10 | * Free Software Foundation.
11 | *
12 | * This program is distributed in the hope that it will be useful, but WITHOUT
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 | * details.
16 | *
17 | * You should have received a copy of the GNU General Public License along with
18 | * this program. If not, see .
19 | *
20 | * As a special exception, AlliedModders LLC gives you permission to link the
21 | * code of this program (as well as its derivative works) to "Half-Life 2," the
22 | * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
23 | * by the Valve Corporation. You must obey the GNU General Public License in
24 | * all respects for all other code used. Additionally, AlliedModders LLC grants
25 | * this exception to all derivative works. AlliedModders LLC defines further
26 | * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
27 | * or .
28 | */
29 |
30 | #ifndef _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
31 | #define _INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
32 |
33 | #include
34 | #include
35 | #include
36 |
37 | #define KESTRING_TABLE_START_SIZE 65536
38 |
39 | struct Symbol
40 | {
41 | size_t length;
42 | uint32_t hash;
43 | void *address;
44 | Symbol *tbl_next;
45 |
46 | inline char *buffer()
47 | {
48 | return reinterpret_cast(this + 1);
49 | }
50 | };
51 |
52 | class SymbolTable
53 | {
54 | public:
55 | ~SymbolTable()
56 | {
57 | for (uint32_t i = 0; i < nbuckets; i++)
58 | {
59 | Symbol *sym = buckets[i];
60 | while (sym != NULL)
61 | {
62 | Symbol *next = sym->tbl_next;
63 | free(sym);
64 | sym = next;
65 | }
66 | }
67 | free(buckets);
68 | }
69 |
70 | bool Initialize()
71 | {
72 | buckets = (Symbol **)malloc(sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
73 | if (buckets == NULL)
74 | {
75 | return false;
76 | }
77 | memset(buckets, 0, sizeof(Symbol *) * KESTRING_TABLE_START_SIZE);
78 |
79 | nbuckets = KESTRING_TABLE_START_SIZE;
80 | nused = 0;
81 | bucketmask = KESTRING_TABLE_START_SIZE - 1;
82 | return true;
83 | }
84 |
85 | static inline uint32_t HashString(const char *data, size_t len)
86 | {
87 | #undef get16bits
88 | #if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
89 | || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
90 | #define get16bits(d) (*((const uint16_t *) (d)))
91 | #endif
92 | #if !defined (get16bits)
93 | #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
94 | +(uint32_t)(((const uint8_t *)(d))[0]) )
95 | #endif
96 | uint32_t hash = len, tmp;
97 | int rem;
98 |
99 | if (len <= 0 || data == NULL)
100 | {
101 | return 0;
102 | }
103 |
104 | rem = len & 3;
105 | len >>= 2;
106 |
107 | /* Main loop */
108 | for (;len > 0; len--) {
109 | hash += get16bits (data);
110 | tmp = (get16bits (data+2) << 11) ^ hash;
111 | hash = (hash << 16) ^ tmp;
112 | data += 2 * sizeof (uint16_t);
113 | hash += hash >> 11;
114 | }
115 |
116 | /* Handle end cases */
117 | switch (rem) {
118 | case 3: hash += get16bits (data);
119 | hash ^= hash << 16;
120 | hash ^= data[sizeof (uint16_t)] << 18;
121 | hash += hash >> 11;
122 | break;
123 | case 2: hash += get16bits (data);
124 | hash ^= hash << 11;
125 | hash += hash >> 17;
126 | break;
127 | case 1: hash += *data;
128 | hash ^= hash << 10;
129 | hash += hash >> 1;
130 | }
131 |
132 | /* Force "avalanching" of final 127 bits */
133 | hash ^= hash << 3;
134 | hash += hash >> 5;
135 | hash ^= hash << 4;
136 | hash += hash >> 17;
137 | hash ^= hash << 25;
138 | hash += hash >> 6;
139 |
140 | return hash;
141 |
142 | #undef get16bits
143 | }
144 |
145 | Symbol **FindSymbolBucket(const char *str, size_t len, uint32_t hash)
146 | {
147 | uint32_t bucket = hash & bucketmask;
148 | Symbol **pkvs = &buckets[bucket];
149 |
150 | Symbol *kvs = *pkvs;
151 | while (kvs != NULL)
152 | {
153 | if (len == kvs->length && memcmp(str, kvs->buffer(), len * sizeof(char)) == 0)
154 | {
155 | return pkvs;
156 | }
157 | pkvs = &kvs->tbl_next;
158 | kvs = *pkvs;
159 | }
160 |
161 | return pkvs;
162 | }
163 |
164 | void ResizeSymbolTable()
165 | {
166 | uint32_t xnbuckets = nbuckets * 2;
167 | Symbol **xbuckets = (Symbol **)malloc(sizeof(Symbol *) * xnbuckets);
168 | if (xbuckets == NULL)
169 | {
170 | return;
171 | }
172 | memset(xbuckets, 0, sizeof(Symbol *) * xnbuckets);
173 | uint32_t xbucketmask = xnbuckets - 1;
174 | for (uint32_t i = 0; i < nbuckets; i++)
175 | {
176 | Symbol *sym = buckets[i];
177 | while (sym != NULL)
178 | {
179 | Symbol *next = sym->tbl_next;
180 | uint32_t bucket = sym->hash & xbucketmask;
181 | sym->tbl_next = xbuckets[bucket];
182 | xbuckets[bucket] = sym;
183 | sym = next;
184 | }
185 | }
186 | free(buckets);
187 | buckets = xbuckets;
188 | nbuckets = xnbuckets;
189 | bucketmask = xbucketmask;
190 | }
191 |
192 | Symbol *FindSymbol(const char *str, size_t len)
193 | {
194 | uint32_t hash = HashString(str, len);
195 | Symbol **pkvs = FindSymbolBucket(str, len, hash);
196 | return *pkvs;
197 | }
198 |
199 | Symbol *InternSymbol(const char* str, size_t len, void *address)
200 | {
201 | uint32_t hash = HashString(str, len);
202 | Symbol **pkvs = FindSymbolBucket(str, len, hash);
203 | if (*pkvs != NULL)
204 | {
205 | return *pkvs;
206 | }
207 |
208 | Symbol *kvs = (Symbol *)malloc(sizeof(Symbol) + sizeof(char) * (len + 1));
209 | kvs->length = len;
210 | kvs->hash = hash;
211 | kvs->address = address;
212 | kvs->tbl_next = NULL;
213 | memcpy(kvs + 1, str, sizeof(char) * (len + 1));
214 | *pkvs = kvs;
215 | nused++;
216 |
217 | if (nused > nbuckets && nbuckets <= INT_MAX / 2)
218 | {
219 | ResizeSymbolTable();
220 | }
221 |
222 | return kvs;
223 | }
224 | private:
225 | uint32_t nbuckets;
226 | uint32_t nused;
227 | uint32_t bucketmask;
228 | Symbol **buckets;
229 | };
230 |
231 | #endif //_INCLUDE_SOURCEMOD_CORE_SYMBOLTABLE_H_
232 |
--------------------------------------------------------------------------------
/plugin/sdkapi/sdkapi.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * SDKAPI
3 | * Copyright (C) 2021 LinGe All rights reserved.
4 | * =============================================================================
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License, version 3.0, as published by the
8 | * Free Software Foundation.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 | * details.
14 | *
15 | * You should have received a copy of the GNU General Public License along with
16 | * this program. If not, see .
17 | */
18 | #include "sdkapi.h"
19 | #include "signature.h"
20 | #include
21 | #include
22 | #include
23 |
24 | namespace SDKAPI {
25 | ICvar *iCvar = nullptr;
26 | IPlayerInfoManager *iPlayerInfoManager = nullptr;
27 | IServerGameEnts *iServerGameEnts = nullptr;
28 | IVEngineServer *iVEngineServer = nullptr;
29 | IServerTools *iServerTools = nullptr;
30 | IServerGameDLL *iServerGameDLL = nullptr;
31 | IServerPluginHelpers *iServerPluginHelpers = nullptr;
32 | IGameEventManager2 *iGameEventManager = nullptr;
33 | CGlobalVars *pGlobals = nullptr;
34 | FCGlobalEntityList *gEntList = nullptr;
35 |
36 | static MemoryUtils *mu_engine = nullptr;
37 | static MemoryUtils *mu_server = nullptr;
38 |
39 | namespace ServerSigFunc {
40 | FINDENTITYBYCLASSNAME CBaseEntity_FindEntityByClassname = nullptr;
41 |
42 | void Initialize()
43 | {
44 | CBaseEntity_FindEntityByClassname = mu_server->FindSignature(Sig_FindEntityByClassname);
45 | if (!CBaseEntity_FindEntityByClassname)
46 | SDKAPI_Warning("FindEntityByClassname signature not found!\n");
47 | }
48 | }
49 |
50 | void Initialize(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory)
51 | {
52 | ConnectTier1Libraries(&interfaceFactory, 1);
53 | ConnectTier2Libraries(&interfaceFactory, 1);
54 | // hl2sdk-l4d2 接口
55 | iCvar = reinterpret_cast(interfaceFactory(CVAR_INTERFACE_VERSION, nullptr));
56 | if (!iCvar)
57 | SDKAPI_Warning("ICvar interface initialize failed!\n");
58 |
59 | iPlayerInfoManager = reinterpret_cast(gameServerFactory(INTERFACEVERSION_PLAYERINFOMANAGER, nullptr));
60 | if (!iPlayerInfoManager)
61 | SDKAPI_Warning("IPlayerInfoManager interface initialize failed!\n");
62 |
63 | iServerGameEnts = reinterpret_cast(gameServerFactory(INTERFACEVERSION_SERVERGAMEENTS, nullptr));
64 | if (!iServerGameEnts)
65 | SDKAPI_Warning("IServerGameEnts interface initialize failed!\n");
66 |
67 | iVEngineServer = reinterpret_cast(interfaceFactory(INTERFACEVERSION_VENGINESERVER, nullptr));
68 | if (!iVEngineServer)
69 | SDKAPI_Warning("IVEngineServer interface initialize failed!\n");
70 |
71 | iServerTools = reinterpret_cast(gameServerFactory(VSERVERTOOLS_INTERFACE_VERSION, nullptr));
72 | if (!iServerTools)
73 | SDKAPI_Warning("IServerTools interface initialize failed!\n");
74 |
75 | iServerGameDLL = reinterpret_cast(gameServerFactory(INTERFACEVERSION_SERVERGAMEDLL, nullptr));
76 | if (!iServerGameDLL)
77 | SDKAPI_Warning("IServerGameDLL interface initialize failed!\n");
78 |
79 | iServerPluginHelpers = reinterpret_cast(interfaceFactory(INTERFACEVERSION_ISERVERPLUGINHELPERS, nullptr));
80 | if (!iServerPluginHelpers)
81 | SDKAPI_Warning("IServerPluginHelpers interface initialize failed!\n");
82 |
83 | iGameEventManager = reinterpret_cast(interfaceFactory(INTERFACEVERSION_GAMEEVENTSMANAGER2, nullptr));
84 | if (!iGameEventManager)
85 | SDKAPI_Warning("IGameEventManager2 interface initialize failed!\n");
86 |
87 | mu_engine = new MemoryUtils(interfaceFactory);
88 | if (!mu_engine->IsAvailable())
89 | SDKAPI_Warning("mu_engine initialize failed!\n");
90 |
91 | mu_server = new MemoryUtils(gameServerFactory);
92 | if (!mu_server->IsAvailable())
93 | SDKAPI_Warning("mu_server initialize failed!\n");
94 | else
95 | ServerSigFunc::Initialize();
96 |
97 | // 初始化 pEntList 方法参考 sourcemod/core/HalfLife2.cpp
98 | // Win32下是通过LevelShutdown函数地址再加上偏移量获得pEntityList(指向gEntList的指针)的地址
99 | // Linux下是直接通过符号查找获得gEntList的地址
100 | if (mu_server->IsAvailable())
101 | {
102 | void *ptr = mu_server->FindSignature(Sig_gEntList);
103 | if (!ptr)
104 | SDKAPI_Warning("gEntList signature not found!\n");
105 | else
106 | {
107 | #ifdef WIN32
108 | ptr = *(reinterpret_cast((char *)ptr + Offset_gEntList_windows));
109 | #endif
110 | gEntList = reinterpret_cast(ptr);
111 | }
112 | }
113 | }
114 |
115 | void UnInitialize()
116 | {
117 | delete mu_server;
118 | delete mu_engine;
119 | DisconnectTier1Libraries();
120 | DisconnectTier2Libraries();
121 | }
122 |
123 | // 通过向实体 logic_script 发送实体输入执行 vscripts 脚本代码
124 | // 代码参考 Silver https://forums.alliedmods.net/showthread.php?p=2657025
125 | bool L4D2_RunScript(const char *_Format, ...)
126 | {
127 | // 处理 _Format
128 | static char buffer[8192];
129 | va_list arg_list;
130 | va_start(arg_list, _Format);
131 | vsnprintf(buffer, sizeof(buffer), _Format, arg_list);
132 | va_end(arg_list);
133 |
134 | static variant_t var;
135 | // pScriptLogic 必须每次执行时查找 因为每局游戏它应该都会变
136 | CBaseEntity *pScriptLogic = gEntList->FindEntityByClassname(nullptr, "logic_script");
137 | edict_t *edict = iServerGameEnts->BaseEntityToEdict(pScriptLogic);
138 | if (!edict || edict->IsFree())
139 | {
140 | pScriptLogic = reinterpret_cast(iServerTools->CreateEntityByName("logic_script"));
141 | if (!pScriptLogic)
142 | return false;
143 | iServerTools->DispatchSpawn(pScriptLogic);
144 | }
145 | castable_string_t str(buffer);
146 | var.SetString(str);
147 | return reinterpret_cast(pScriptLogic)->AcceptInput("RunScriptCode", nullptr, nullptr, var, 0);
148 | }
149 | } // namespace SDKAPI
--------------------------------------------------------------------------------
/plugin/sdkapi/sdkapi.h:
--------------------------------------------------------------------------------
1 | /**
2 | * SDKAPI
3 | * Copyright (C) 2021 LinGe All rights reserved.
4 | * =============================================================================
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License, version 3.0, as published by the
8 | * Free Software Foundation.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 | * details.
14 | *
15 | * You should have received a copy of the GNU General Public License along with
16 | * this program. If not, see .
17 | */
18 | #pragma once
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include "MemoryUtils/MemoryUtils.h"
26 | #include "signature.h"
27 |
28 | #ifdef _LINUX
29 | #define __thiscall
30 | #endif
31 |
32 | #define SDKAPI_Msg(format, ...) Msg("SDKAPI: " format, ## __VA_ARGS__)
33 | #define SDKAPI_Warning(format, ...) Warning("SDKAPI: " format, ## __VA_ARGS__)
34 | #define SDKAPI_Error(format, ...) Error("SDKAPI: " format, ## __VA_ARGS__)
35 |
36 | namespace SDKAPI {
37 | // 伪 SDK 类前置声明
38 | class FCGlobalEntityList;
39 | class FCBaseEntity;
40 |
41 | // SDK API 接口
42 | extern ICvar *iCvar;
43 | extern IPlayerInfoManager *iPlayerInfoManager;
44 | extern IServerGameEnts *iServerGameEnts;
45 | extern IVEngineServer *iVEngineServer;
46 | extern IServerTools *iServerTools;
47 | extern IServerGameDLL *iServerGameDLL;
48 | extern IServerPluginHelpers *iServerPluginHelpers;
49 | extern IGameEventManager2 *iGameEventManager;
50 | extern CGlobalVars *pGlobals;
51 | extern FCGlobalEntityList *gEntList;
52 |
53 | namespace ServerSigFunc {
54 | typedef CBaseEntity *(__thiscall *FINDENTITYBYCLASSNAME)(void *, CBaseEntity *, const char *);
55 | extern FINDENTITYBYCLASSNAME CBaseEntity_FindEntityByClassname;
56 | }
57 |
58 | // 全局函数
59 | void Initialize(CreateInterfaceFn interfaceFactory, CreateInterfaceFn gameServerFactory);
60 | void UnInitialize();
61 |
62 | // 通过向实体 logic_script 发送实体输入执行 vscripts 脚本代码
63 | bool L4D2_RunScript(const char *_Format, ...);
64 |
65 | inline int IndexOfEdict(const edict_t *pEdict)
66 | {
67 | return (int)(pEdict - pGlobals->pEdicts);
68 | }
69 | inline edict_t *PEntityOfEntIndex(int iEntIndex)
70 | {
71 | if (iEntIndex >= 0 && iEntIndex < pGlobals->maxEntities)
72 | {
73 | return (edict_t *)(pGlobals->pEdicts + iEntIndex);
74 | }
75 | return nullptr;
76 | }
77 |
78 | // 通过UserID获取到实体
79 | inline edict_t *GetEntityFromUserID(int userid)
80 | {
81 | for (int i=0; imaxEntities; i++)
82 | {
83 | edict_t *pEntity = PEntityOfEntIndex(i);
84 | if (iVEngineServer->GetPlayerUserId(pEntity) == userid)
85 | return pEntity;
86 | }
87 | return nullptr;
88 | }
89 |
90 | // 伪SDK类,用于方便调用一些函数
91 | class FCGlobalEntityList
92 | {
93 | public:
94 | inline CBaseEntity *FindEntityByClassname(CBaseEntity *pStartEntity, const char *szName)
95 | {
96 | if (ServerSigFunc::CBaseEntity_FindEntityByClassname)
97 | return ServerSigFunc::CBaseEntity_FindEntityByClassname(this, pStartEntity, szName);
98 | else
99 | {
100 | SDKAPI_Error("FindEntityByClassname function pointer is nullptr!");
101 | return nullptr;
102 | }
103 | }
104 | };
105 |
106 | class FCBaseEntity
107 | {
108 | public:
109 | typedef bool(__thiscall *ACCEPTINPUT)(void *, const char *, CBaseEntity *, CBaseEntity *, variant_t, int);
110 |
111 | public:
112 | inline bool AcceptInput(const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID=0)
113 | {
114 | return GetVirtualFunction(this, VTI_AcceptInput)
115 | (this, szInputName, pActivator, pCaller, Value, outputID);
116 | }
117 | };
118 | }
119 |
--------------------------------------------------------------------------------
/plugin/sdkapi/signature.h:
--------------------------------------------------------------------------------
1 | /**
2 | * SDKAPI
3 | * Copyright (C) 2021 LinGe All rights reserved.
4 | * =============================================================================
5 | *
6 | * This program is free software; you can redistribute it and/or modify it under
7 | * the terms of the GNU General Public License, version 3.0, as published by the
8 | * Free Software Foundation.
9 | *
10 | * This program is distributed in the hope that it will be useful, but WITHOUT
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 | * details.
14 | *
15 | * You should have received a copy of the GNU General Public License along with
16 | * this program. If not, see .
17 | */
18 | #pragma once
19 | #include "MemoryUtils/MemoryUtils.h"
20 |
21 | constexpr Signature Sig_gEntList = {
22 | "\xE8\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\xE8",
23 | // 此 Windows 平台签名为 LevelShutdown 函数的签名,用于定位 pEntityList
24 | "@gEntList"
25 | };
26 | #define Offset_gEntList_windows 11 // Offset into LevelShutdown
27 |
28 | // CGlobalEntityList::FindEntityByClassname
29 | constexpr Signature Sig_FindEntityByClassname = {
30 | "\x55\x8B\xEC\x53\x56\x8B\xF1\x8B\x4D\x08\x57\x85\xC9\x74\x2A\x8B\x01\x8B\x50\x08\xFF\xD2\x8B\x00\x25\xFF\x0F\x00\x00\x40\x03\xC0\x8B\x3C\xC6\xEB\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x85\xFF\x74\x2A\x8B\x5D\x0C\x8B\x37\x85\xF6\x75\x2A\x68\x2A\x2A\x2A\x2A\xFF\x2A\x2A\x2A\x2A\x2A\x83\xC4\x04\xEB\x2A\x39",
31 | "@_ZN17CGlobalEntityList21FindEntityByClassnameEP11CBaseEntityPKc"
32 | };
33 |
34 | // CBaseEntity::AcceptInput 虚函数表索引
35 | constexpr VTableIndex VTI_AcceptInput = { 44, 45 };
--------------------------------------------------------------------------------
/release/Base-addonimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/Base-addonimage.jpg
--------------------------------------------------------------------------------
/release/Base-addoninfo.txt:
--------------------------------------------------------------------------------
1 | "AddonInfo"
2 | {
3 | addonSteamAppID 550
4 | addontitle "LinGe VScripts 基础库"
5 | addonDescription "LinGe VScripts 脚本基础库"
6 | addonauthor "LinGe"
7 | addonURL0 "https://github.com/Lin515/L4D2_LinGe_VScripts"
8 |
9 | addonContent_Script 1
10 | }
--------------------------------------------------------------------------------
/release/HUD-addonimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/HUD-addonimage.jpg
--------------------------------------------------------------------------------
/release/HUD-addoninfo.txt:
--------------------------------------------------------------------------------
1 | "AddonInfo"
2 | {
3 | addonSteamAppID 550
4 | addontitle "击杀与伤害统计、友伤提示、时间显示"
5 | addonDescription "必须同时安装 LinGe VScripts Base 基础库才可使用"
6 | addonauthor "LinGe"
7 | addonURL0 "https://github.com/Lin515/L4D2_LinGe_VScripts"
8 |
9 | addonContent_Script 1
10 | }
--------------------------------------------------------------------------------
/release/Hint-addonimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/Hint-addonimage.jpg
--------------------------------------------------------------------------------
/release/Hint-addoninfo.txt:
--------------------------------------------------------------------------------
1 | "AddonInfo"
2 | {
3 | addonSteamAppID 550
4 | addontitle "玩家状态提示与物品标记提示"
5 | addonDescription "使用 bind g +alt1 绑定快捷键可以标记物品。非对抗类模式下可用。"
6 | addonauthor "LinGe"
7 | addonURL0 "https://github.com/Lin515/L4D2_LinGe_VScripts"
8 |
9 | addonContent_Script 1
10 | }
--------------------------------------------------------------------------------
/release/LinGe_VScripts-addonimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/LinGe_VScripts-addonimage.jpg
--------------------------------------------------------------------------------
/release/LinGe_VScripts-addoninfo.txt:
--------------------------------------------------------------------------------
1 | "AddonInfo"
2 | {
3 | addonSteamAppID 550
4 | addontitle "LinGe VScripts 全功能"
5 | addonDescription "击杀统计、多特、玩家状态提示等等"
6 | addonauthor "LinGe"
7 | addonURL0 "https://github.com/Lin515/L4D2_LinGe_VScripts"
8 |
9 | addonContent_Script 1
10 | }
--------------------------------------------------------------------------------
/release/MoreSI-addonimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/MoreSI-addonimage.jpg
--------------------------------------------------------------------------------
/release/MoreSI-addoninfo.txt:
--------------------------------------------------------------------------------
1 | "AddonInfo"
2 | {
3 | addonSteamAppID 550
4 | addontitle "多特控制:修改特感生成数量、种类与刷新时间"
5 | addonDescription "仅战役类模式下可用"
6 | addonauthor "LinGe"
7 | addonURL0 "https://github.com/Lin515/L4D2_LinGe_VScripts"
8 |
9 | addonContent_Script 1
10 | }
--------------------------------------------------------------------------------
/release/RewardHP-addonimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/RewardHP-addonimage.jpg
--------------------------------------------------------------------------------
/release/RewardHP-addoninfo.txt:
--------------------------------------------------------------------------------
1 | "AddonInfo"
2 | {
3 | addonSteamAppID 550
4 | addontitle "击杀回血,可设置回复虚血或实血"
5 | addonDescription "仅战役类模式下可用"
6 | addonauthor "LinGe"
7 | addonURL0 "https://github.com/Lin515/L4D2_LinGe_VScripts"
8 |
9 | addonContent_Script 1
10 | }
--------------------------------------------------------------------------------
/release/plugin.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set main=..\plugin\
3 | set output=plugin
4 | set _7z="D:\Program Files\7-Zip\7z.exe"
5 | set linux_user=arch
6 |
7 | rd /s /q %output%
8 | mkdir %output%\addons\LinGe_VScripts
9 |
10 | :: 复制插件文件
11 | copy %main%\LinGe_VScripts.vdf %output%\addons\LinGe_VScripts.vdf
12 | copy %main%\%USER%-build\Release\LinGe_VScripts.dll %output%\addons\LinGe_VScripts\LinGe_VScripts.dll
13 | copy %main%\%linux_user%-build\Release\LinGe_VScripts.so %output%\addons\LinGe_VScripts\LinGe_VScripts.so
14 |
15 | :: 打包 zip
16 | cd %output%
17 | %_7z% a -tzip LinGe_VScripts.zip addons
18 |
19 | pause
--------------------------------------------------------------------------------
/release/vpk.bat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk.bat
--------------------------------------------------------------------------------
/release/vpk/LinGe VScripts 整合.vpk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk/LinGe VScripts 整合.vpk
--------------------------------------------------------------------------------
/release/vpk/击杀回血 RewardHP.vpk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk/击杀回血 RewardHP.vpk
--------------------------------------------------------------------------------
/release/vpk/基础库 Base.vpk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk/基础库 Base.vpk
--------------------------------------------------------------------------------
/release/vpk/多特控制 MoreSI.vpk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk/多特控制 MoreSI.vpk
--------------------------------------------------------------------------------
/release/vpk/排行榜、伤害统计 HUD.vpk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk/排行榜、伤害统计 HUD.vpk
--------------------------------------------------------------------------------
/release/vpk/标记物资、队友倒地被控提示 Hint.vpk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk/标记物资、队友倒地被控提示 Hint.vpk
--------------------------------------------------------------------------------
/release/vpk/自杀指令 zs.vpk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/vpk/自杀指令 zs.vpk
--------------------------------------------------------------------------------
/release/zs-addonimage.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Lin515/L4D2_LinGe_VScripts/1418258fe2e366fe6fadc8183877dc1b49079865/release/zs-addonimage.jpg
--------------------------------------------------------------------------------
/release/zs-addoninfo.txt:
--------------------------------------------------------------------------------
1 | "AddonInfo"
2 | {
3 | addonSteamAppID 550
4 | addontitle "自杀指令 !zs"
5 | addonDescription "仅战役类模式下可用"
6 | addonauthor "LinGe"
7 | addonURL0 "https://github.com/Lin515/L4D2_LinGe_VScripts"
8 |
9 | addonContent_Script 1
10 | }
--------------------------------------------------------------------------------
/vscripts/LinGe/Base.nut:
--------------------------------------------------------------------------------
1 | // By LinGe https://github.com/Lin515/L4D2_LinGe_VScripts
2 | // 本系列脚本编写主要参考以下文档
3 | // L4D2脚本函数清单:https://developer.valvesoftware.com/wiki/L4D2%E8%84%9A%E6%9C%AC%E5%87%BD%E6%95%B0%E6%B8%85%E5%8D%95
4 | // L4D2 EMS/Appendix:HUD:https://developer.valvesoftware.com/wiki/L4D2_EMS/Appendix:_HUD
5 | // L4D2 Events:https://wiki.alliedmods.net/Left_4_Dead_2_Events
6 | // 以及VSLib与admin_system的脚本源码
7 | printl("[LinGe] Base 正在载入");
8 | ::LinGe <- {};
9 | ::LinGe.Debug <- false;
10 |
11 | ::LinGe.hostport <- Convars.GetFloat("hostport").tointeger();
12 | printl("[LinGe] 当前服务器端口 " + ::LinGe.hostport);
13 |
14 | // 地图结束后销毁本脚本
15 | local Last_OnShutdown = g_MapScript.ScriptMode_OnShutdown.bindenv(g_MapScript);
16 | g_MapScript.ScriptMode_OnShutdown <- function (reason, nextmap)
17 | {
18 | delete ::LinGe;
19 | Last_OnShutdown(reason, nextmap);
20 |
21 | printl("[LinGe] 回合结束,脚本已卸载");
22 | }
23 |
24 | // ---------------------------全局函数START-------------------------------------------
25 | // 主要用于调试
26 | ::LinGe.DebugPrintl <- function (str)
27 | {
28 | if (::LinGe.Debug)
29 | printl(str);
30 | }
31 |
32 | ::LinGe.DebugPrintlTable <- function (table)
33 | {
34 | if (!::LinGe.Debug)
35 | return;
36 | if (typeof table != "table" && typeof table != "array")
37 | return;
38 | foreach (key, val in table)
39 | print(key + "=" + val + " ; ");
40 | print("\n");
41 | }
42 |
43 | // 递归深度克隆(只会对table或array的子项进行克隆)
44 | ::LinGe.DeepClone <- function (obj)
45 | {
46 | if (typeof obj == "table")
47 | {
48 | local table = clone obj;
49 | foreach (key, val in table)
50 | table[key] = DeepClone(val);
51 | return table;
52 | }
53 | if (typeof obj == "array")
54 | {
55 | local array = clone obj;
56 | foreach (index, val in array)
57 | array[index] = DeepClone(val);
58 | return array;
59 | }
60 | return obj;
61 | }
62 |
63 | // 尝试将一个字符串转换为int类型 eValue为出现异常时返回的值
64 | ::LinGe.TryStringToInt <- function (value, eValue=0)
65 | {
66 | local ret = eValue;
67 | try
68 | {
69 | ret = value.tointeger();
70 | }
71 | catch (e)
72 | {
73 | ret = eValue;
74 | }
75 | return ret;
76 | }
77 | // 尝试将一个字符串转换为float类型 eValue为出现异常时返回的值
78 | ::LinGe.TryStringToFloat <- function (value, eValue=0.0)
79 | {
80 | local ret = eValue;
81 | try
82 | {
83 | ret = value.tofloat();
84 | }
85 | catch (e)
86 | {
87 | ret = eValue;
88 | }
89 | return ret;
90 | }
91 |
92 | // 查找并移除找到的第一个元素 返回其索引,若未找到则返回null
93 | ::LinGe.RemoveInArray <- function (value, array)
94 | {
95 | local idx = array.find(value);
96 | if (null != idx)
97 | array.remove(idx);
98 | return idx;
99 | }
100 |
101 | // 当前模式是否是对抗模式
102 | ::LinGe.CheckVersus <- function ()
103 | {
104 | if (Director.GetGameMode() == "mutation15") // 生还者对抗
105 | return true;
106 | if ("versus" == g_BaseMode)
107 | return true;
108 | if ("scavenge" == g_BaseMode)
109 | return true;
110 | return false;
111 | }
112 | ::LinGe.isVersus <- ::LinGe.CheckVersus();
113 |
114 | // 设置某类下所有已生成实体的KeyValue
115 | ::LinGe.SetKeyValueByClassname <- function (className, key, value)
116 | {
117 | local entity = null;
118 | local func = null;
119 |
120 | switch (typeof value)
121 | {
122 | case "integer":
123 | func = @(entity, key, value) entity.__KeyValueFromInt(key, value);
124 | break;
125 | case "float":
126 | func = @(entity, key, value) entity.__KeyValueFromFloat(key, value);
127 | break;
128 | case "string":
129 | func = @(entity, key, value) entity.__KeyValueFromString(key, value);
130 | break;
131 | case "Vector":
132 | func = @(entity, key, value) entity.__KeyValueFromVector(key, value);
133 | break;
134 | default:
135 | throw "参数类型非法";
136 | }
137 |
138 | local count = 0;
139 | while ( (entity = Entities.FindByClassname(entity, className)) != null)
140 | {
141 | func(entity, key, value);
142 | count++;
143 | }
144 | return count;
145 | }
146 |
147 | ::LinGe.SteamIDCastUniqueID <- function (steamid)
148 | {
149 | local uniqueID = ::VSLib.Utils.StringReplace(steamid, "STEAM_1:", "S");
150 | uniqueID = ::VSLib.Utils.StringReplace(uniqueID, "STEAM_0:", "S");
151 | uniqueID = ::VSLib.Utils.StringReplace(uniqueID, ":", "");
152 | return uniqueID;
153 | }
154 |
155 | // 获取 targetname,并确保它在本脚本系统中独一无二
156 | ::LinGe.GetEntityTargetname <- function (entity)
157 | {
158 | local targetname = entity.GetName();
159 | if (targetname.find("LinGe_") != 0)
160 | {
161 | targetname = "LinGe_" + UniqueString();
162 | entity.__KeyValueFromString("targetname", targetname);
163 | }
164 | return targetname;
165 | }
166 |
167 | // 通过userid获得玩家实体索引
168 | ::LinGe.GetEntityIndexFromUserID <- function (userid)
169 | {
170 | local entity = GetPlayerFromUserID(userid);
171 | if (null == entity)
172 | return null;
173 | else
174 | return entity.GetEntityIndex();
175 | }
176 |
177 | // 通过userid获得steamid
178 | ::LinGe.GetSteamIDFromUserID <- function (userid)
179 | {
180 | local entity = GetPlayerFromUserID(userid);
181 | if (null == entity)
182 | return null;
183 | else
184 | return entity.GetNetworkIDString();
185 | }
186 |
187 | // 该userid是否为BOT所有
188 | ::LinGe.IsBotUserID <- function (userid)
189 | {
190 | local entity = GetPlayerFromUserID(userid);
191 | if (null == entity)
192 | return true;
193 | else
194 | return "BOT"==entity.GetNetworkIDString();
195 | }
196 |
197 | ::LinGe.GetReviveCount <- function (player)
198 | {
199 | return NetProps.GetPropInt(player, "m_currentReviveCount");
200 | }
201 |
202 | // 从网络属性判断一个实体是否存活
203 | ::LinGe.IsAlive <- function (ent)
204 | {
205 | return NetProps.GetPropInt(ent, "m_lifeState") == 0;
206 | }
207 |
208 | // 从bot生还者中获取其就位的生还者玩家实体
209 | // 须自己先检查是否是有效生还者bot 否则可能出错
210 | ::LinGe.GetHumanPlayer <- function (bot)
211 | {
212 | if (::LinGe.IsAlive(bot))
213 | {
214 | local human = GetPlayerFromUserID(NetProps.GetPropInt(bot, "m_humanSpectatorUserID"));
215 | if (null != human)
216 | {
217 | if (human.IsValid())
218 | {
219 | if ( "BOT" != human.GetNetworkIDString()
220 | && 1 == ::LinGe.GetPlayerTeam(human) )
221 | return human;
222 | }
223 | }
224 | }
225 | return null;
226 | }
227 |
228 | // 判断玩家是否处于闲置 参数可以是玩家实体也可以是实体索引
229 | ::LinGe.IsPlayerIdle <- function (player)
230 | {
231 | local entityIndex = 0;
232 | local _player = null;
233 | // 通过类名查找玩家
234 | if ("integer" == typeof player)
235 | {
236 | entityIndex = player;
237 | _player = PlayerInstanceFromIndex(entityIndex);
238 | }
239 | else if ("instance" == typeof player)
240 | {
241 | entityIndex = player.GetEntityIndex();
242 | _player = player;
243 | }
244 | else
245 | throw "参数类型非法";
246 | if (!_player.IsValid())
247 | return false;
248 | if (1 != ::LinGe.GetPlayerTeam(_player))
249 | return false;
250 |
251 | local bot = null;
252 | while ( bot = Entities.FindByClassname(bot, "player") )
253 | {
254 | // 判断搜索到的实体有效性
255 | if ( bot.IsValid() )
256 | {
257 | // 判断阵营
258 | if ( bot.IsSurvivor()
259 | && "BOT" == bot.GetNetworkIDString()
260 | && ::LinGe.IsAlive(bot) )
261 | {
262 | local human = ::LinGe.GetHumanPlayer(bot);
263 | if (human != null)
264 | {
265 | if (human.GetEntityIndex() == entityIndex)
266 | return true;
267 | }
268 | }
269 | }
270 | }
271 | return false;
272 | }
273 |
274 | // 获取所有处于闲置的玩家
275 | ::LinGe.GetIdlePlayers <- function ()
276 | {
277 | local bot = null;
278 | local players = [];
279 | while ( bot = Entities.FindByClassname(bot, "player") )
280 | {
281 | if ( bot.IsValid() )
282 | {
283 | if ( bot.IsSurvivor()
284 | && "BOT" == bot.GetNetworkIDString()
285 | && ::LinGe.IsAlive(bot) )
286 | {
287 | local human = ::LinGe.GetHumanPlayer(bot);
288 | if (human != null)
289 | {
290 | players.push(human);
291 | }
292 | }
293 | }
294 | }
295 | return players;
296 | }
297 |
298 | ::LinGe.GetIdlePlayerCount <- function ()
299 | {
300 | local bot = null;
301 | local count = 0;
302 | while ( bot = Entities.FindByClassname(bot, "player") )
303 | {
304 | if ( bot.IsValid() )
305 | {
306 | if ( bot.IsSurvivor()
307 | && "BOT" == bot.GetNetworkIDString()
308 | && ::LinGe.IsAlive(bot) )
309 | {
310 | local human = ::LinGe.GetHumanPlayer(bot);
311 | if (human != null)
312 | {
313 | count++;
314 | }
315 | }
316 | }
317 | }
318 | return count;
319 | }
320 |
321 | ::LinGe.GetMaxHealth <- function (entity)
322 | {
323 | return NetProps.GetPropInt(victim, "m_iMaxHealth");
324 | }
325 |
326 | ::LinGe.GetPlayerTeam <- function (player)
327 | {
328 | return NetProps.GetPropInt(player, "m_iTeamNum");
329 | }
330 |
331 | // 将 Vector 转换为 QAngle
332 | // hl2sdk-l4d2/mathlib/mathlib_base.cpp > line:506
333 | ::LinGe.QAngleFromVector <- function (forward)
334 | {
335 | local tmp, yaw, pitch;
336 |
337 | if (forward.y == 0 && forward.x == 0)
338 | {
339 | yaw = 0;
340 | if (forward.z > 0)
341 | pitch = 270;
342 | else
343 | pitch = 90;
344 | }
345 | else
346 | {
347 | yaw = (atan2(forward.y, forward.x) * 180 / PI);
348 | if (yaw < 0)
349 | yaw += 360;
350 |
351 | tmp = sqrt(forward.x*forward.x + forward.y*forward.y);
352 | pitch = (atan2(-forward.z, tmp) * 180 / PI);
353 | if (pitch < 0)
354 | pitch += 360;
355 | }
356 | return QAngle(pitch, yaw, 0.0);
357 | }
358 |
359 | // 玩家是否看着实体的位置或指定位置
360 | // VSLib/player.nut > line:1381 function VSLib::Player::CanSeeLocation
361 | ::LinGe.IsPlayerSeeHere <- function (player, location, tolerance = 50)
362 | {
363 | local _location = null;
364 | if (typeof location == "instance")
365 | _location = location.GetOrigin();
366 | else if (typeof location == "Vector")
367 | _location = location;
368 | else
369 | throw "location 参数类型非法";
370 |
371 | local clientPos = player.EyePosition();
372 | local clientToTargetVec = _location - clientPos;
373 | local clientAimVector = player.EyeAngles().Forward();
374 |
375 | local angToFind = acos(
376 | ::VSLib.Utils.VectorDotProduct(clientAimVector, clientToTargetVec)
377 | / (clientAimVector.Length() * clientToTargetVec.Length())
378 | ) * 360 / 2 / 3.14159265;
379 |
380 | if (angToFind < tolerance)
381 | return true;
382 | else
383 | return false;
384 | }
385 |
386 | ::LinGe.TraceToLocation <- function (origin, location, mask=MASK_SHOT_HULL & (~CONTENTS_WINDOW), ignore=null)
387 | {
388 | // 获取出发点
389 | local start = null;
390 | if (typeof origin == "instance")
391 | {
392 | if ("EyePosition" in origin)
393 | start = origin.EyePosition(); // 如果对象是有眼睛的则获取眼睛位置
394 | else
395 | start = origin.GetOrigin();
396 | }
397 | else if (typeof origin == "Vector")
398 | start = origin;
399 | else
400 | throw "origin 参数类型非法";
401 |
402 | // 获取终点
403 | local end = null;
404 | if (typeof location == "instance")
405 | {
406 | if ("EyePosition" in location)
407 | end = location.EyePosition();
408 | else
409 | end = location.GetOrigin();
410 | }
411 | else if (typeof location == "Vector")
412 | end = location;
413 | else
414 | throw "location 参数类型非法";
415 |
416 | local tr = {
417 | start = start,
418 | end = end,
419 | ignore = (ignore ? ignore : (typeof origin == "instance" ? origin : null) ),
420 | mask = mask,
421 | };
422 | TraceLine(tr);
423 | return tr;
424 | }
425 |
426 | // player 是否注意着 entity
427 | ::LinGe.IsPlayerNoticeEntity <- function (player, entity, tolerance = 50, mask=MASK_SHOT_HULL & (~CONTENTS_WINDOW), radius=0.0)
428 | {
429 | if (!IsPlayerSeeHere(player, entity, tolerance))
430 | return false;
431 | local tr = TraceToLocation(player, entity, mask);
432 | if (tr.rawin("enthit") && tr.enthit == entity)
433 | return true;
434 | if (radius <= 0.0)
435 | return false;
436 | // 如果不能看到指定实体,但指定了半径范围,则进行搜索
437 | local _entity = null, className = entity.GetClassname();
438 | while ( _entity = Entities.FindByClassnameWithin(_entity, className, tr.pos, radius) )
439 | {
440 | if (_entity == entity)
441 | return true;
442 | }
443 | return false;
444 | }
445 |
446 | // 链式射线追踪,当命中到类型为 ignoreClass 中的实体时,从其位置往前继续射线追踪
447 | // ignoreClass 中可以有 entity 的类型,判断时总会先判断定位到的是否是 entity
448 | // 如果最终能命中 entity,则返回 true
449 | ::LinGe.ChainTraceToEntity <- function (origin, entity, mask, ignoreClass, limit=4)
450 | {
451 | local tr = {
452 | start = null,
453 | end = null,
454 | ignore = null,
455 | mask = mask,
456 | };
457 |
458 | // 获取起始点
459 | if (typeof origin == "instance")
460 | {
461 | if ("EyePosition" in origin)
462 | tr.start = origin.EyePosition();
463 | else
464 | tr.start = origin.GetOrigin();
465 | tr.ignore = origin;
466 | }
467 | else if (typeof origin == "Vector")
468 | tr.start = origin;
469 | else
470 | throw "origin 参数类型非法";
471 |
472 | if ("EyePosition" in entity)
473 | tr.end = entity.EyePosition();
474 | else
475 | tr.end = entity.GetOrigin();
476 | if (limit < 1)
477 | limit = 4; // 不允许无限制的链式探测
478 | local start = tr.start; // 保留最初的起点
479 |
480 | local count = 0;
481 | while (true)
482 | {
483 | count++;
484 | TraceLine(tr);
485 | if (!tr.rawin("enthit"))
486 | break;
487 | if (tr.enthit == entity)
488 | return true;
489 | if (count >= limit)
490 | break;
491 | // 如果命中位置已经比目标位置要更远离起始点,则终止
492 | if ((tr.pos-start).Length() > (tr.end-start).Length())
493 | break;
494 | if (ignoreClass.find(tr.enthit.GetClassname()) == null)
495 | break;
496 | tr.start = tr.pos;
497 | tr.ignore = tr.enthit;
498 | }
499 | return false;
500 | }
501 |
502 | // 获取玩家实体数组
503 | // team 指定要获取的队伍 可以是数组或数字 若为null则忽略队伍
504 | // humanOrBot 机器人 0:忽略是否是机器人 1:只获取玩家 2:只获取BOT
505 | // aliveOrDead 存活 0:忽略是否存货 1:只获取存活的 2:只获取死亡的
506 | ::LinGe.GetPlayers <- function (team=null, humanOrBot=0, aliveOrDead=0)
507 | {
508 | local arr = [];
509 | // 通过类名查找玩家
510 | local player = null;
511 | while ( player = Entities.FindByClassname(player, "player") )
512 | {
513 | // 判断搜索到的实体有效性
514 | if ( player.IsValid() )
515 | {
516 | // 判断阵营
517 | if (typeof team == "array")
518 | {
519 | if (team.find(::LinGe.GetPlayerTeam(player))==null)
520 | continue;
521 | }
522 | else if (typeof team == "integer" && team != ::LinGe.GetPlayerTeam(player))
523 | continue;
524 | if (humanOrBot == 1)
525 | {
526 | if ("BOT" == player.GetNetworkIDString())
527 | continue;
528 | }
529 | else if (humanOrBot == 2 && "BOT" != player.GetNetworkIDString())
530 | continue;
531 | if (aliveOrDead == 1)
532 | {
533 | if (!::LinGe.IsAlive(player))
534 | continue;
535 | }
536 | else if (aliveOrDead == 2 && ::LinGe.IsAlive(player))
537 | continue;
538 | arr.append(player);
539 | }
540 | }
541 | return arr;
542 | }
543 | ::LinGe.GetPlayerCount <- function (team=null, humanOrBot=0, aliveOrDead=0)
544 | {
545 | local count = 0;
546 | // 通过类名查找玩家
547 | local player = null;
548 | while ( player = Entities.FindByClassname(player, "player") )
549 | {
550 | // 判断搜索到的实体有效性
551 | if ( player.IsValid() )
552 | {
553 | // 判断阵营
554 | if (typeof team == "array")
555 | {
556 | if (team.find(::LinGe.GetPlayerTeam(player))==null)
557 | continue;
558 | }
559 | else if (typeof team == "integer" && team != ::LinGe.GetPlayerTeam(player))
560 | continue;
561 | if (humanOrBot == 1)
562 | {
563 | if ("BOT" == player.GetNetworkIDString())
564 | continue;
565 | }
566 | else if (humanOrBot == 2 && "BOT" != player.GetNetworkIDString())
567 | continue;
568 | if (aliveOrDead == 1)
569 | {
570 | if (!::LinGe.IsAlive(player))
571 | continue;
572 | }
573 | else if (aliveOrDead == 2 && ::LinGe.IsAlive(player))
574 | continue;
575 | count++;
576 | }
577 | }
578 | return count;
579 | }
580 |
581 | // 如果source中某个key在dest中也存在,则将其赋值给dest中的key
582 | // 如果 reserveKey 为 true,则dest中没用该key也会被赋值
583 | // key无视大小写
584 | ::LinGe.Merge <- function (dest, source, typeMatch=true, reserveKey=false)
585 | {
586 | if ("table" == typeof dest && "table" == typeof source)
587 | {
588 | foreach (key, val in source)
589 | {
590 | local keyIsExist = true;
591 | if (!dest.rawin(key))
592 | {
593 | // 为什么有些保存到 Cache 会产生大小写转换??
594 | // HUD.Config.hurt 保存到 Cache 恢复后,hurt 居然变成了 Hurt
595 | foreach (_key, _val in dest)
596 | {
597 | if (_key.tolower() == key.tolower())
598 | {
599 | source[_key] <- source[key];
600 | key = _key;
601 | break;
602 | }
603 | }
604 | if (!dest.rawin(key))
605 | keyIsExist = false;
606 | }
607 | if (!keyIsExist)
608 | {
609 | if (reserveKey)
610 | dest.rawset(key, val);
611 | continue;
612 | }
613 | local type_dest = typeof dest[key];
614 | local type_src = typeof val;
615 | // 如果指定key也是table,则进行递归
616 | if ("table" == type_dest && "table" == type_src)
617 | ::LinGe.Merge(dest[key], val, typeMatch, reserveKey);
618 | else if (type_dest != type_src)
619 | {
620 | if (!typeMatch)
621 | dest[key] = val;
622 | else if (type_dest == "bool" && type_src == "integer") // 争对某些情况下 bool 被转换成了 integer
623 | dest[key] = (val!=0);
624 | else if (type_dest == "array" && type_src == "table") // 争对某些情况下 array 被转换成了 table 原数组的顺序可能会错乱
625 | {
626 | dest[key].clear();
627 | foreach (_val in val)
628 | dest[key].append(_val);
629 | }
630 | }
631 | else
632 | dest[key] = val;
633 | }
634 | }
635 | }
636 | // ---------------------------全局函数END-------------------------------------------
637 |
638 | // -------------------------------VSLib 改写-------------------------------------------------
639 | // 判断玩家是否为BOT时通过steamid进行判断
640 | function VSLib::Entity::IsBot()
641 | {
642 | if (!IsEntityValid())
643 | {
644 | printl("VSLib Warning: Entity " + _idx + " is invalid.");
645 | return false;
646 | }
647 | if (IsPlayer())
648 | return "BOT" == GetSteamID();
649 | else
650 | return IsPlayerABot(_ent);
651 | }
652 |
653 | // 改良原函数,使其输出的文件带有缩进
654 | function VSLib::FileIO::SerializeTable(object, predicateStart = "{\n", predicateEnd = "}\n", indice = true, indent=1)
655 | {
656 | local indstr = "";
657 | for (local i=0; i= 0)
899 | trigger[event].callback.remove(idx);
900 | return idx;
901 | }.bindenv(::LinGe.Events);
902 |
903 | // 查找函数在指定事件的函数表的索引
904 | // 事件未注册返回-1 未找到函数返回-2
905 | ::LinGe.Events.EventIndex <- function (event, func, callOf=null, reverse=true)
906 | {
907 | if (trigger.rawin(event))
908 | {
909 | local callback = trigger[event].callback;
910 | local len = callback.len();
911 | local i = 0;
912 | if (reverse)
913 | {
914 | for (i=len-1; i>-1; i--)
915 | {
916 | if (func == callback[i].func
917 | && callOf == callback[i].callOf )
918 | break;
919 | }
920 | }
921 | else
922 | {
923 | for (i=0; i 0.0)
944 | ::VSLib.Timers.AddTimer(delay, false,
945 | @(params) ::LinGe.Events.trigger[event][event](params), params);
946 | else
947 | trigger[event][event](params);
948 | }
949 | }.bindenv(::LinGe.Events);
950 |
951 | ::LinEventHook <- ::LinGe.Events.EventHook.weakref();
952 | ::LinEventUnHook <- ::LinGe.Events.EventUnHook.weakref();
953 | ::LinEventIndex <- ::LinGe.Events.EventIndex.weakref();
954 | ::LinEventTrigger <- ::LinGe.Events.EventTrigger.weakref();
955 |
956 | // 只有具有FCVAR_NOTIFY flags的变量才会触发该事件
957 | //::LinGe.Events.OnGameEvent_server_cvar <- function (params)
958 | //{
959 | // EventTrigger("cvar_" + params.cvarname, params);
960 | //}
961 | //::LinEventHook("OnGameEvent_server_cvar", ::LinGe.Events.OnGameEvent_server_cvar, ::LinGe.Events);
962 | // --------------------------事件回调函数注册END----------------------------------------
963 |
964 | // ------------------------------Admin---START--------------------------------------
965 | ::LinGe.Admin <- {};
966 | ::LinGe.Admin.Config <- {
967 | enabled = false,
968 | takeOverAdminSystem = false, // 是否接管adminsystem的权限判断
969 | adminsFile = "linge/admins_simple.ini"
970 | };
971 | ::LinGe.Config.Add("Admin", ::LinGe.Admin.Config);
972 |
973 | ::LinGe.Admin.cmdTable <- {}; // 指令表
974 | // 读取管理员列表,若文件不存在则创建
975 | ::LinGe.Admin.adminslist <- FileToString(::LinGe.Admin.Config.adminsFile);
976 | if (null == ::LinGe.Admin.adminslist)
977 | {
978 | ::LinGe.Admin.adminslist = "STEAM_1:0:64877973 // Homura Chan";
979 | StringToFile(::LinGe.Admin.Config.adminsFile, ::LinGe.Admin.adminslist);
980 | ::LinGe.Admin.adminslist = FileToString(::LinGe.Admin.Config.adminsFile);
981 | if (null == ::LinGe.Admin.adminslist)
982 | printl("[LinGe] " + adminsFile + " 文件读取失败,无法获取管理员列表");
983 | }
984 |
985 | /* 添加指令 若同名指令会覆盖旧指令
986 | string 指令名
987 | func 指令回调函数
988 | callOf 回调函数执行所在的表
989 | isAdminCmd 是否是管理员指令
990 | */
991 | ::LinGe.Admin.CmdAdd <- function (command, func, callOf=null, remarks="", isAdminCmd=true, ignoreCase=true)
992 | {
993 | local _callOf = (callOf==null) ? null : callOf.weakref();
994 | local table = { func=func.weakref(), callOf=_callOf, remarks=remarks, isAdminCmd=isAdminCmd, ignoreCase=ignoreCase };
995 | cmdTable.rawset(command.tolower(), table);
996 | }.bindenv(::LinGe.Admin);
997 |
998 | // 删除指令 成功删除返回其值 否则返回null
999 | ::LinGe.Admin.CmdDelete <- function (command)
1000 | {
1001 | return cmdTable.rawdelete(command.tolower());
1002 | }.bindenv(::LinGe.Admin);
1003 | ::LinCmdAdd <- ::LinGe.Admin.CmdAdd.weakref();
1004 | ::LinCmdDelete <- ::LinGe.Admin.CmdDelete.weakref();
1005 |
1006 | // 消息指令触发 通过 player_say
1007 | ::LinGe.Admin.OnGameEvent_player_say <- function (params)
1008 | {
1009 | local args = split(params.text, " ");
1010 | local cmd = args[0];
1011 | if (cmd.len() < 2)
1012 | return;
1013 | local player = GetPlayerFromUserID(params.userid);
1014 | if (null == player || !player.IsValid())
1015 | return;
1016 | local firstChar = cmd.slice(0, 1); // 取第一个字符
1017 | // 判断前缀有效性
1018 | if (firstChar != "!"
1019 | && firstChar != "/"
1020 | && firstChar != "." )
1021 | return;
1022 |
1023 | local text = params.text.slice(1);
1024 | args = split(text, " ");
1025 | cmd = args[0].tolower(); // 设置 args 第一个元素为指令名
1026 | if (cmdTable.rawin(cmd))
1027 | {
1028 | if (cmdTable[cmd].ignoreCase)
1029 | CmdExec(cmd, player, split(text.tolower(), " "));
1030 | else
1031 | CmdExec(cmd, player, args);
1032 | }
1033 | }
1034 | ::LinEventHook("OnGameEvent_player_say", ::LinGe.Admin.OnGameEvent_player_say, ::LinGe.Admin);
1035 |
1036 | // scripted_user_func 指令触发
1037 | ::LinGe.Admin.OnUserCommand <- function (vplayer, args, text)
1038 | {
1039 | local _args = split(text, ",");
1040 | local cmdstr = _args[0].tolower();
1041 | local cmdTable = ::LinGe.Admin.cmdTable;
1042 | if (cmdTable.rawin(cmdstr))
1043 | {
1044 | if (cmdTable[cmdstr].ignoreCase)
1045 | ::LinGe.Admin.CmdExec(cmdstr, vplayer._ent, split(text.tolower(), ","));
1046 | else
1047 | ::LinGe.Admin.CmdExec(cmdstr, vplayer._ent, _args);
1048 | }
1049 | }
1050 | ::EasyLogic.OnUserCommand.LinGeCommands <- ::LinGe.Admin.OnUserCommand.weakref();
1051 |
1052 | // 指令调用执行
1053 | ::LinGe.Admin.CmdExec <- function (command, player, args)
1054 | {
1055 | local cmd = cmdTable[command];
1056 | if (cmd.isAdminCmd && !IsAdmin(player))
1057 | { // 如果是管理员指令而用户身份不是管理员,则发送权限不足提示
1058 | ClientPrint(player, 3, "\x04此条指令仅管理员可用!");
1059 | return;
1060 | }
1061 |
1062 | if (cmd.callOf != null)
1063 | cmd.func.call(cmd.callOf, player, args);
1064 | else
1065 | cmd.func(player, args);
1066 | }
1067 |
1068 | // 判断该玩家是否是管理员
1069 | ::LinGe.Admin.IsAdmin <- function (player)
1070 | {
1071 | // 未启用权限管理则所有人视作管理员
1072 | if (!Config.enabled)
1073 | return true;
1074 | // 如果是单人游戏则直接返回true
1075 | if (Director.IsSinglePlayerGame())
1076 | return true;
1077 | // 获取steam id
1078 | local steamID = null;
1079 | local vplayer = player;
1080 | if (typeof vplayer != "VSLIB_PLAYER")
1081 | vplayer = ::VSLib.Player(player);
1082 | if ( vplayer.IsServerHost() )
1083 | return true;
1084 | steamID = vplayer.GetSteamID();
1085 | if (null == steamID)
1086 | return false;
1087 |
1088 | // 通过steamID判断是否是管理员
1089 | if (null != adminslist)
1090 | {
1091 | if (null == adminslist.find(steamID))
1092 | return false;
1093 | else
1094 | return true;
1095 | }
1096 | else
1097 | return false;
1098 | }.bindenv(::LinGe.Admin);
1099 |
1100 | // 事件:回合开始 如果启用了AdminSystem则覆盖其管理员判断指令
1101 | ::LinGe.Admin.OnGameEvent_round_start <- function (params)
1102 | {
1103 | if ("AdminSystem" in getroottable() && Config.takeOverAdminSystem)
1104 | {
1105 | ::AdminSystem.IsAdmin = ::LinGe.Admin.IsAdmin;
1106 | ::AdminSystem.IsPrivileged = ::LinGe.Admin.IsAdmin;
1107 | }
1108 | }
1109 | ::LinEventHook("OnGameEvent_round_start", ::LinGe.Admin.OnGameEvent_round_start, ::LinGe.Admin);
1110 |
1111 | ::LinGe.Admin.Cmd_setvalue <- function (player, args)
1112 | {
1113 | if (args.len() == 3)
1114 | Convars.SetValue(args[1], args[2]);
1115 | }
1116 | ::LinCmdAdd("setvalue", ::LinGe.Admin.Cmd_setvalue, ::LinGe.Admin);
1117 |
1118 | ::LinGe.Admin.Cmd_getvalue <- function (player, args)
1119 | {
1120 | if (args.len() == 2)
1121 | ClientPrint(player, 3, Convars.GetStr(args[1]));
1122 | }
1123 | ::LinCmdAdd("getvalue", ::LinGe.Admin.Cmd_getvalue, ::LinGe.Admin);
1124 |
1125 | ::LinGe.Admin.Cmd_saveconfig <- function (player, args)
1126 | {
1127 | if (args.len() == 1)
1128 | {
1129 | ::LinGe.Config.SaveAll();
1130 | ClientPrint(player, 3, "\x04已保存当前功能设定为默认设定\n");
1131 | ClientPrint(player, 3, "\x04配置文件: \x05 left4dead2/ems/" + FILE_CONFIG + ".tbl");
1132 | }
1133 | else if (args.len() == 2)
1134 | {
1135 | foreach (name, tbl in ::LinGe.Config.table)
1136 | {
1137 | if (name.tolower() == args[1])
1138 | {
1139 | ::LinGe.Config.Save(name);
1140 | ClientPrint(player, 3, "\x04已保存当前功能设定为默认设定: \x05" + name);
1141 | ClientPrint(player, 3, "\x04配置文件: \x05 left4dead2/ems/" + FILE_CONFIG + ".tbl");
1142 | return;
1143 | }
1144 | }
1145 | ClientPrint(player, 3, "\x04未找到 \x05" + args[1]);
1146 | }
1147 | }
1148 | ::LinCmdAdd("saveconfig", ::LinGe.Admin.Cmd_saveconfig, ::LinGe.Admin);
1149 | ::LinCmdAdd("save", ::LinGe.Admin.Cmd_saveconfig, ::LinGe.Admin, "保存配置到配置文件");
1150 |
1151 | ::LinGe.Admin.Cmd_lshelp <- function (player, args)
1152 | {
1153 | foreach (key, val in cmdTable)
1154 | {
1155 | if (val.remarks != "")
1156 | ClientPrint(player, 3, format("\x05!%s \x03%s", key, val.remarks));
1157 | }
1158 | }
1159 | ::LinCmdAdd("lshelp", ::LinGe.Admin.Cmd_lshelp, ::LinGe.Admin, "", false);
1160 |
1161 | ::LinGe.Admin.Cmd_config <- function (player, args)
1162 | {
1163 | if (args.len() == 2)
1164 | {
1165 | local func = compilestring("return ::LinGe.Config.table." + args[1]);
1166 | try {
1167 | ClientPrint(player, 3, "\x04" + args[1] + " = \x05" + func());
1168 | } catch (e) {
1169 | ClientPrint(player, 3, "\x04读取配置失败: \x05" + args[1]);
1170 | }
1171 | }
1172 | else if (args.len() >= 3)
1173 | {
1174 | try {
1175 | local type = compilestring("return typeof ::LinGe.Config.table." + args[1])();
1176 | switch (type)
1177 | {
1178 | case "bool":
1179 | case "integer":
1180 | case "float":
1181 | compilestring("::LinGe.Config.table." + args[1] + " = " + args[2])();
1182 | break;
1183 | case "string":
1184 | {
1185 | local str = "";
1186 | for (local i=2; i= 0);
27 | local enableTime = (Config.sitime >= 0);
28 | local enableNoci = Config.sinoci;
29 | Checksionly();
30 | local enableType = ( Config.sionly.len() > 0 );
31 | local enableInitDelay = ( Config.initDelay >= 0 );
32 |
33 |
34 | if (!Config.enabled)
35 | {
36 | enableNum = false;
37 | enableTime = false;
38 | enableType = false;
39 | enableNoci = false;
40 | enableInitDelay = false;
41 | }
42 |
43 | // 设置特感数量
44 | if (enableNum)
45 | {
46 | local autoNum = 0; // 额外特感数量
47 | if (Config.siauto > 0)
48 | autoNum = Config.siauto * ::LinGe.GetPlayerCount(2);
49 |
50 | local simax = Config.sibase + autoNum;
51 | if (simax < Config.simin)
52 | simax = Config.simin;
53 | else if (simax > 31)
54 | simax = 31;
55 |
56 | ::SessionOptions.rawset("cm_MaxSpecials", simax);
57 | ::SessionOptions.rawset("cm_BaseSpecialLimit", ceil(::SessionOptions.cm_MaxSpecials / 5.0) ); // 平均特感数量
58 | ::SessionOptions.rawset("DominatorLimit", ::SessionOptions.cm_MaxSpecials);
59 | }
60 | else
61 | {
62 | ::SessionOptions.rawdelete("cm_MaxSpecials");
63 | ::SessionOptions.rawdelete("cm_BaseSpecialLimit");
64 | ::SessionOptions.rawdelete("DominatorLimit");
65 | }
66 |
67 | // 设置特感刷新时间
68 | if (enableTime)
69 | {
70 | ::SessionOptions.rawset("cm_SpecialRespawnInterval", Config.sitime);
71 | }
72 | else
73 | {
74 | ::SessionOptions.rawdelete("cm_SpecialRespawnInterval");
75 | }
76 |
77 | // 特感种类控制
78 | if (enableType)
79 | {
80 | ::SessionOptions.rawset("BoomerLimit", 0);
81 | ::SessionOptions.rawset("SpitterLimit", 0);
82 | ::SessionOptions.rawset("SmokerLimit", 0);
83 | ::SessionOptions.rawset("HunterLimit", 0);
84 | ::SessionOptions.rawset("ChargerLimit", 0);
85 | ::SessionOptions.rawset("JockeyLimit", 0);
86 |
87 | local maxsi = enableNum ? ::SessionOptions.cm_MaxSpecials : 4;
88 | ::SessionOptions.rawset("cm_BaseSpecialLimit", ceil( 1.0*maxsi / Config.sionly.len() ) ); // 平均特感数量
89 | ::SessionOptions.rawset("DominatorLimit", maxsi);
90 | foreach (val in Config.sionly)
91 | ::SessionOptions.rawset(val + "Limit", ::SessionOptions.cm_BaseSpecialLimit);
92 | }
93 | else
94 | {
95 | ::SessionOptions.rawdelete("BoomerLimit");
96 | ::SessionOptions.rawdelete("SpitterLimit");
97 | ::SessionOptions.rawdelete("SmokerLimit");
98 | ::SessionOptions.rawdelete("HunterLimit");
99 | ::SessionOptions.rawdelete("ChargerLimit");
100 | ::SessionOptions.rawdelete("JockeyLimit");
101 | if (!enableNum)
102 | {
103 | ::SessionOptions.rawdelete("cm_BaseSpecialLimit");
104 | ::SessionOptions.rawdelete("DominatorLimit");
105 | }
106 | }
107 |
108 | // 设置无小僵尸
109 | if (enableNoci)
110 | {
111 | ::SessionOptions.rawset("cm_CommonLimit", 0);
112 | ::VSLib.Timers.AddTimerByName("AutoKillCI", 1.0, true, Timer_AutoKillCI);
113 | }
114 | else
115 | {
116 | ::SessionOptions.rawdelete("cm_CommonLimit");
117 | ::VSLib.Timers.RemoveTimerByName("AutoKillCI");
118 | }
119 |
120 | // 出门第一波特感时间
121 | if (enableInitDelay)
122 |
123 | {
124 | ::SessionOptions.rawset("SpecialInitialSpawnDelayMax", Config.initDelay);
125 | ::SessionOptions.rawset("SpecialInitialSpawnDelayMin", Config.initDelay);
126 | }
127 | else
128 | {
129 | ::SessionOptions.rawdelete("SpecialInitialSpawnDelayMax");
130 | ::SessionOptions.rawdelete("SpecialInitialSpawnDelayMin");
131 | }
132 | }
133 |
134 | // 检查数组sionly值的有效性 移除无效值
135 | ::LinGe.MoreSI.Checksionly <- function()
136 | {
137 | local str = "";
138 | local firstChar = "";
139 | if ("array" != typeof Config.sionly)
140 | Config.sionly = [];
141 | else
142 | {
143 | foreach (idx, val in Config.sionly)
144 | {
145 | // 如果找不到则将其进行字母转换,再进行查找
146 | if (null == sitypelist.find(val))
147 | {
148 | // 首字母转为大写,其它转成小写
149 | firstChar = val.slice(0, 1).toupper();
150 | str = val.slice(1).tolower();
151 | str = firstChar + str;
152 |
153 | if (null == sitypelist.find(str))
154 | Config.sionly.remove(idx);
155 | else
156 | Config.sionly[idx] = str;
157 | }
158 | }
159 | }
160 | }
161 |
162 | // 输出当前设置信息
163 | ::LinGe.MoreSI.ShowInfo <- function ()
164 | {
165 | if (!Config.enabled)
166 | {
167 | ClientPrint(null, 3, "\x04多特控制:总开关\x03 关闭");
168 | return;
169 | }
170 |
171 | local text = "\x04多特控制:";
172 | if (Config.sibase >= 0)
173 | text += "特感数量为\x03 " + ::SessionOptions.cm_MaxSpecials + " \x04,";
174 | else
175 | text += "数量控制\x03 关闭 \x04,";
176 | if (Config.sitime >= 0)
177 | text += "刷新时间为\x03 " + ::SessionOptions.cm_SpecialRespawnInterval;
178 | else
179 | text += "刷新控制为\x03 关闭";
180 | ClientPrint(null, 3, text);
181 |
182 | if (Config.sionly.len() > 0 || Config.sinoci)
183 | {
184 | text = "\x04多特控制:"
185 | if (Config.sionly.len() > 0)
186 | {
187 | local list = "";
188 | foreach (val in Config.sionly)
189 | list += val + " ";
190 | text += "限制只生成特感 \x03" + list;
191 | }
192 | else
193 | text += "限制特感生成 \x03关闭";
194 | if (Config.sinoci)
195 | text += "\x04,无小僵尸 \x03开启";
196 | else
197 | text += "\x04,无小僵尸 \x03关闭";
198 | ClientPrint(null, 3, text);
199 | }
200 | }
201 |
202 | ::LinGe.MoreSI.cache_restore <- function (params)
203 | {
204 | // 如果有有效Cache存在 则使用Cache中的配置
205 | if (params.isValidCache && ::LinGe.Cache.rawin("MoreSI_Config"))
206 | {
207 | _enabled = ::LinGe.Cache.MoreSI_Config.enabled;
208 | }
209 | Config.enabled = false;
210 | }
211 | ::LinEventHook("cache_restore", ::LinGe.MoreSI.cache_restore, ::LinGe.MoreSI);
212 |
213 | // 回合开始
214 | ::LinGe.MoreSI.OnGameEvent_round_start <- function (params)
215 | {
216 | Config.enabled = _enabled;
217 | if (Config.enabled)
218 | {
219 | ExecConfig();
220 | ShowInfo();
221 | }
222 | }
223 | ::LinEventHook("OnGameEvent_round_start", ::LinGe.MoreSI.OnGameEvent_round_start, ::LinGe.MoreSI);
224 |
225 | // 玩家队伍变更 调整特感数量
226 | ::LinGe.MoreSI.OnGameEvent_player_team <- function (params)
227 | {
228 | if (!params.rawin("userid"))
229 | return;
230 | // 根据生还者人数调整特感数量
231 | if ( Config.enabled && Config.sibase >= 0 && Config.siauto > 0 )
232 | {
233 | if (2 == params.team || 2 == params.oldteam)
234 | {
235 | local oldmax = ::SessionOptions.cm_MaxSpecials;
236 | // 延迟1.2秒再更新特感数量,避免短时间内多次数量刷新
237 | ::VSLib.Timers.AddTimerByName("SIAUTO", 1.2, false, Delay_siauto, oldmax);
238 | }
239 | }
240 | }
241 | ::LinEventHook("OnGameEvent_player_team", ::LinGe.MoreSI.OnGameEvent_player_team, ::LinGe.MoreSI);
242 |
243 | ::LinGe.MoreSI.Delay_siauto <- function (oldmax)
244 | {
245 | if (Config.enabled && Config.sibase >= 0 && Config.siauto > 0)
246 | {
247 | ExecConfig();
248 | if (oldmax != ::SessionOptions.cm_MaxSpecials)
249 | ClientPrint(null, 3, "\x04多特控制:当前特感数量已修改为\x03 " + ::SessionOptions.cm_MaxSpecials);
250 | }
251 | }.bindenv(::LinGe.MoreSI);
252 |
253 | // !si 查看当前多特控制状态
254 | ::LinGe.MoreSI.Cmd_si <- function (player, args)
255 | {
256 | ShowInfo();
257 | }
258 | ::LinCmdAdd("si", ::LinGe.MoreSI.Cmd_si, ::LinGe.MoreSI, "", false);
259 |
260 | // !sion 打开多特控制 同时可以用来一次设置多个值 sibase siauto sitime noci sionly(限制特感类型需用逗号分隔)
261 | // 不修改的数值输入 -2
262 | // 一次正确的用法: !sion 4 1 15 -2 Hunter,Jockey 设置sibase=4,siauto=1,sitime=15,noci不变,sionly=["Hunter", "Jockey"]
263 | ::LinGe.MoreSI.Cmd_sion <- function (player, args)
264 | {
265 | local sibase = -2;
266 | local siauto = -2;
267 | local sitime = -2;
268 | local noci = -2;
269 | local sionly = -2;
270 |
271 | local argc = args.len();
272 | if (argc > 1)
273 | {
274 | sibase = LinGe.TryStringToInt(args[1], -2);
275 | if (sibase > 31)
276 | sibase = 31;
277 | if (sibase != -2)
278 | Config.sibase = sibase;
279 | }
280 | if (argc > 2)
281 | {
282 | siauto = LinGe.TryStringToInt(args[2], -2);
283 | if (siauto < 0 && siauto!=-2)
284 | siauto = 0;
285 | else if (siauto > 7)
286 | siauto = 7;
287 | if (siauto != -2)
288 | Config.siauto = siauto;
289 | }
290 | if (argc > 3)
291 | {
292 | sitime = LinGe.TryStringToInt(args[3], -2);
293 | if (sitime != -2)
294 | Config.sitime = sitime;
295 | }
296 | if (argc > 4)
297 | {
298 | noci = args[4];
299 | if ("on" == noci)
300 | Config.sinoci = true;
301 | else if ("off" == noci)
302 | Config.sinoci = false;
303 | else
304 | noci = -2;
305 | }
306 | if (argc > 5)
307 | {
308 | sionly = split(args[5], ",");
309 | Config.sionly = sionly;
310 | }
311 |
312 | Config.enabled = true;
313 | ExecConfig();
314 | ShowInfo();
315 | }
316 | ::LinCmdAdd("sion", ::LinGe.MoreSI.Cmd_sion, ::LinGe.MoreSI, "打开多特控制");
317 |
318 | // !sioff 关闭多特控制
319 | ::LinGe.MoreSI.Cmd_sioff <- function (player, args)
320 | {
321 | if (args.len() == 1)
322 | {
323 | if (Config.enabled)
324 | {
325 | Config.enabled = false;
326 | ExecConfig();
327 | }
328 | ShowInfo();
329 | }
330 | }
331 | ::LinCmdAdd("sioff", ::LinGe.MoreSI.Cmd_sioff, ::LinGe.MoreSI, "关闭多特控制");
332 |
333 | // !sibase 设置基础特感数量
334 | ::LinGe.MoreSI.Cmd_sibase <- function (player, args)
335 | {
336 | if (!Config.enabled)
337 | {
338 | ClientPrint(player, 3, "\x04多特控制:总开关\x03 关闭");
339 | return;
340 | }
341 |
342 | local argsLen = args.len();
343 | if (argsLen > 2)
344 | return;
345 |
346 | if (2 == argsLen)
347 | {
348 | local num = LinGe.TryStringToInt(args[1], -1);
349 | if (num > 31)
350 | {
351 | ClientPrint(player, 3, "\x04多特控制:基础特感数量不能超过\x03 31");
352 | return;
353 | }
354 | Config.sibase = num;
355 | ExecConfig();
356 | }
357 | if (Config.sibase >= 0)
358 | {
359 | ClientPrint(null, 3, "\x04多特控制:基础特感数量\x03 " + Config.sibase);
360 | ClientPrint(null, 3, "\x04多特控制:当前特感总数为\x03 " + ::SessionOptions.cm_MaxSpecials);
361 | }
362 | else
363 | ClientPrint(null, 3, "\x04多特控制:数量控制\x03 关闭");
364 | }
365 | ::LinCmdAdd("sibase", ::LinGe.MoreSI.Cmd_sibase, ::LinGe.MoreSI, "设置基础特感数量");
366 |
367 | // !siauto 设置自动增加特感数量
368 | ::LinGe.MoreSI.Cmd_siauto <- function (player, args)
369 | {
370 | if (!Config.enabled)
371 | {
372 | ClientPrint(player, 3, "\x04多特控制:总开关\x03 关闭");
373 | return;
374 | }
375 |
376 | local argsLen = args.len();
377 | if (argsLen > 2)
378 | return;
379 |
380 | if (2 == argsLen)
381 | {
382 | local num = LinGe.TryStringToInt(args[1], -1);
383 | if (num < 0 || num > 7)
384 | {
385 | ClientPrint(player, 3, "\x04多特控制:预设自动增加特感数量只能为\x03 0~7");
386 | return;
387 | }
388 | Config.siauto = num;
389 | ExecConfig();
390 | }
391 | if (Config.siauto > 0)
392 | {
393 | ClientPrint(null, 3, "\x04多特控制:每\x03 1 \x04名生还者玩家加入将增加\x03 " + Config.siauto + " \x04个特感");
394 | ClientPrint(null, 3, "\x04多特控制:当前特感总数为\x03 " + ::SessionOptions.cm_MaxSpecials);
395 | }
396 | else
397 | ClientPrint(null, 3, "\x04多特控制:自动增加特感\x03 关闭");
398 | }
399 | ::LinCmdAdd("siauto", ::LinGe.MoreSI.Cmd_siauto, ::LinGe.MoreSI, "设置每1名生还者加入所增加的特感数量");
400 |
401 | // !sitime 设置特感刷新时间
402 | ::LinGe.MoreSI.Cmd_sitime <- function (player, args)
403 | {
404 | if (!Config.enabled)
405 | {
406 | ClientPrint(player, 3, "\x04多特控制:总开关\x03 关闭");
407 | return;
408 | }
409 |
410 | local argsLen = args.len();
411 | if (argsLen > 2)
412 | return;
413 |
414 | if (2 == argsLen)
415 | {
416 | Config.sitime = LinGe.TryStringToInt(args[1], -1);
417 | ExecConfig();
418 | }
419 | if (Config.sitime >= 0)
420 | ClientPrint(null, 3, "\x04多特控制:特感刷新时间为\x03 " + Config.sitime);
421 | else
422 | ClientPrint(null, 3, "\x04多特控制:特感刷新控制\x03 关闭");
423 | }
424 | ::LinCmdAdd("sitime", ::LinGe.MoreSI.Cmd_sitime, ::LinGe.MoreSI, "设置特感刷新时间");
425 |
426 | // !sionly 限制只生成某一种特感 只能是sitypelist中的一种
427 | // 用逗号分隔多种特感,例如 !sionly Hunter,Boomer
428 | ::LinGe.MoreSI.Cmd_sionly <- function (player, args)
429 | {
430 | if (!Config.enabled)
431 | {
432 | ClientPrint(player, 3, "\x04多特控制:总开关\x03 关闭");
433 | return;
434 | }
435 |
436 | if (args.len() > 1)
437 | {
438 | Config.sionly = split(args[1], ",");
439 | ExecConfig();
440 | }
441 |
442 | if (Config.sionly.len() > 0)
443 | {
444 | local list = "";
445 | foreach (val in Config.sionly)
446 | list += val + " ";
447 | ClientPrint(null, 3, "\x04多特控制:限制只生成特感 \x03" + list);
448 | // ClientPrint(player, 3, "\x04关闭方法:!sionly\x03 任意字符");
449 | }
450 | else
451 | {
452 | ClientPrint(null, 3, "\x04多特控制:限制特感生成 \x03关闭");
453 | // ClientPrint(player, 3, "\x04开启方法:!sionly\x03 Boomer,Spitter,Smoker,Hunter,Charger,Jockey");
454 | }
455 | }
456 | ::LinCmdAdd("sionly", ::LinGe.MoreSI.Cmd_sionly, ::LinGe.MoreSI, "限制只生成哪些特感,例:!sionly Hunter,Jockey");
457 |
458 | // !noci 是否设置无小僵尸
459 | ::LinGe.MoreSI.Cmd_noci <- function (player, args)
460 | {
461 | if (!Config.enabled)
462 | {
463 | ClientPrint(player, 3, "\x04多特控制:总开关\x03 关闭");
464 | return;
465 | }
466 |
467 | if (args.len() == 2)
468 | {
469 | if (args[1] == "on")
470 | Config.sinoci = true;
471 | else if (args[1] == "off")
472 | Config.sinoci = false;
473 | ExecConfig();
474 | }
475 | if (Config.sinoci)
476 | ClientPrint(null, 3, "\x04多特控制:无小僵尸 \x03开启");
477 | else
478 | ClientPrint(null, 3, "\x04多特控制:无小僵尸 \x03关闭");
479 | }
480 | ::LinCmdAdd("noci", ::LinGe.MoreSI.Cmd_noci, ::LinGe.MoreSI);
481 | ::LinCmdAdd("sinoci", ::LinGe.MoreSI.Cmd_noci, ::LinGe.MoreSI, "on/off 开启/关闭自动清除小僵尸");
482 |
483 | ::LinGe.MoreSI.Timer_AutoKillCI <- function (params)
484 | {
485 | if ( Director.GetCommonInfectedCount() > 0 )
486 | {
487 | local infected = null;
488 | while ( infected = Entities.FindByClassname( infected, "infected" ) )
489 | {
490 | if ( infected.IsValid() )
491 | infected.Kill();
492 | }
493 | }
494 | }.bindenv(::LinGe.MoreSI);
495 |
496 | }
--------------------------------------------------------------------------------
/vscripts/LinGe/RewardHP.nut:
--------------------------------------------------------------------------------
1 | // 仅在非对抗类模式生效
2 | if (!::LinGe.isVersus) {
3 | printl("[LinGe] 击杀回复血量 正在载入");
4 |
5 | ::LinGe.RewardHP <- {};
6 |
7 | ::LinGe.RewardHP.Config <- {
8 | mode = 0, // 0:关闭 1:回复实血 2:回复虚血 3:回复虚血,条件不满足则回复实血
9 | limit = 100, // 奖励血量上限
10 | permanent = { // 实血回复量
11 | special = 2,// 击杀一只普通特感(非Tank和Witch)回复多少实血
12 | witch = 10, // 击杀一只Witch回复多少实血
13 | common = 0,// 击杀一只丧尸回复多少实血
14 | },
15 | temporary = { // 虚血回复量
16 | special = 4,// 击杀一只普通特感(非Tank和Witch)回复多少虚血
17 | witch = 20, // 击杀一只Witch回复多少虚血
18 | common = 0,// 击杀一只丧尸回复多少虚血
19 | }
20 | };
21 | ::LinGe.Config.Add("RewardHP", ::LinGe.RewardHP.Config);
22 | ::LinGe.Cache.RewardHP_Config <- ::LinGe.RewardHP.Config;
23 |
24 | ::LinGe.RewardHP.OnGameEvent_player_death <- function (params)
25 | {
26 | if (Config.mode < 1 || Config.mode > 3)
27 | return;
28 |
29 | local victim = null;
30 | if (params.victimname == "Infected" || params.victimname == "Witch")
31 | {
32 | victim = Ent(params.entityid);
33 | if (!victim || !victim.IsValid())
34 | return;
35 | }
36 | else
37 | {
38 | if (params.victimname == "Tank")
39 | return;
40 | victim = GetPlayerFromUserID(params.userid);
41 | if (!victim || !victim.IsValid() || ::LinGe.GetPlayerTeam(victim) != 3)
42 | return;
43 | }
44 |
45 | local attacker = GetPlayerFromUserID(params.attacker);
46 | if (!attacker || !attacker.IsValid() || ::LinGe.GetPlayerTeam(attacker) != 2
47 | || attacker.IsIncapacitated())
48 | return;
49 |
50 | local hp = attacker.GetHealth();
51 | local hpbuffer = attacker.GetHealthBuffer();
52 | if (hp >= Config.limit)
53 | return;
54 |
55 | local reward_perm = 0, reward_temp = 0;
56 | switch (params.victimname)
57 | {
58 | case "Infected":
59 | reward_perm = Config.permanent.common;
60 | reward_temp = Config.temporary.common;
61 | break;
62 | case "Witch":
63 | reward_perm = Config.permanent.witch;
64 | reward_temp = Config.temporary.witch;
65 | break;
66 | default:
67 | reward_perm = Config.permanent.special;
68 | reward_temp = Config.temporary.special;
69 | break;
70 | }
71 |
72 | // 判断回复虚血条件是否满足(模式不为1 且 虚血回复量>0 且 回复后总血量<=上限)
73 | // 满足则回复虚血,否则回复实血
74 | if (Config.mode != 1 && reward_temp > 0 && hp + hpbuffer + reward_temp <= Config.limit)
75 | {
76 | attacker.SetHealthBuffer(hpbuffer + reward_temp);
77 | }
78 | else if (reward_perm > 0)
79 | {
80 | // 回复实血,但实血量不会超过上限
81 | if (hp + reward_perm > Config.limit)
82 | {
83 | attacker.SetHealth(Config.limit);
84 | }
85 | else
86 | {
87 | attacker.SetHealth(hp + reward_perm);
88 | }
89 | // 如果奖励后总血量超过上限,则扣除多余的虚血,但扣除量不会超过本次奖励的实血量
90 | // 相当于虚血转换为实血
91 | local excess = attacker.GetHealth() + hpbuffer - Config.limit;
92 | if (excess > 0)
93 | {
94 | local diff = attacker.GetHealth() - hp;
95 | if (excess > diff)
96 | excess = diff;
97 | attacker.SetHealthBuffer(hpbuffer - excess);
98 | }
99 | }
100 | }
101 | ::LinEventHook("OnGameEvent_player_death", ::LinGe.RewardHP.OnGameEvent_player_death, ::LinGe.RewardHP);
102 |
103 | ::LinGe.RewardHP.Cmd_rhp <- function (player, args)
104 | {
105 | if (2 == args.len())
106 | {
107 | local mode = ::LinGe.TryStringToInt(args[1], 0);
108 | Config.mode = mode;
109 | }
110 | switch (Config.mode)
111 | {
112 | case 1:
113 | ClientPrint(null, 3, "\x04击杀回血当前模式 \x03回复实血");
114 | break;
115 | case 2:
116 | ClientPrint(null, 3, "\x04击杀回血当前模式 \x03回复虚血");
117 | break;
118 | case 3:
119 | ClientPrint(null, 3, "\x04击杀回血当前模式 \x03回复虚血,满血后回复实血");
120 | break;
121 | default:
122 | ClientPrint(null, 3, "\x04击杀回血当前模式 \x03关闭");
123 | break;
124 | }
125 | ClientPrint(player, 3, "\x04!rhp 0:关闭 1:回复实血 2:回复虚血 3:回复虚血,条件不满足则回复实血");
126 | }
127 | ::LinCmdAdd("rhp", ::LinGe.RewardHP.Cmd_rhp, ::LinGe.RewardHP, "0:关闭 1:回复实血 2:回复虚血 3:回复虚血,条件不满足则回复实血");
128 |
129 | } // if (!::LinGe.isVersus)
--------------------------------------------------------------------------------
/vscripts/LinGe/VSLib.nut:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 LuKeM aka Neil - 119 and Rayman1103
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | * and associated documentation files (the "Software"), to deal in the Software without
6 | * restriction, including without limitation the rights to use, copy, modify, merge, publish,
7 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
8 | * Software is furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | */
20 |
21 | ::__VSLIB_VERSION__ <- 5.0;
22 | local __VSLIB_NOTIFY_VERSION__ = false;
23 |
24 | /*
25 | * Create global namespace
26 | */
27 | if (!("VSLib" in getroottable()))
28 | {
29 | ::VSLib <-
30 | {
31 | GlobalCache = {}
32 | GlobalCacheSession = {}
33 | }
34 | __VSLIB_NOTIFY_VERSION__ = true;
35 | }
36 |
37 | /*
38 | * Include sub-files
39 | */
40 | IncludeScript("LinGe/VSLib/EasyLogic.nut");
41 | IncludeScript("LinGe/VSLib/Utils.nut");
42 | IncludeScript("LinGe/VSLib/Timer.nut");
43 | IncludeScript("LinGe/VSLib/Entity.nut");
44 | IncludeScript("LinGe/VSLib/Player.nut");
45 | IncludeScript("LinGe/VSLib/FileIO.nut");
46 | IncludeScript("LinGe/VSLib/HUD.nut");
47 | IncludeScript("LinGe/VSLib/ResponseRules.nut");
48 | IncludeScript("LinGe/VSLib/RandomItemSpawner.nut");
49 |
50 | if ( __VSLIB_NOTIFY_VERSION__ )
51 | printf( "Loaded VSLib version %f", __VSLIB_VERSION__ );
--------------------------------------------------------------------------------
/vscripts/LinGe/VSLib/fileio.nut:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 LuKeM aka Neil - 119 and Rayman1103
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | * and associated documentation files (the "Software"), to deal in the Software without
6 | * restriction, including without limitation the rights to use, copy, modify, merge, publish,
7 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
8 | * Software is furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | */
20 |
21 |
22 | /**
23 | * File I/O functions that simplify the saving and loading of data.
24 | */
25 | ::VSLib.FileIO <- {};
26 |
27 |
28 | /**
29 | * Recursively serializes a table and returns the string. This command ignores all functions within
30 | * the table, saving only the primitive types (i.e. integers, floats, strings, etc with definite values).
31 | * The indexes that you use for your table need to be programmatically "clean," meaning that the index
32 | * cannot contain invalid characters like +-=!@#$%^&*() etc. Indexes that contain any kind of
33 | * invalid character is completely ignored. If you are trying to store player information,
34 | * use Player::GetUniqueID() instead of Player::GetSteamID() for the index ID.
35 | *
36 | * You probably won't need to use this function by itself. @see VSLib::FileIO::SaveTable()
37 | */
38 | function VSLib::FileIO::SerializeTable(object, predicateStart = "{\n", predicateEnd = "}\n", indice = true)
39 | {
40 | local baseString = predicateStart;
41 |
42 | foreach (idx, val in object)
43 | {
44 | local idxType = typeof idx;
45 |
46 | if (idxType == "instance" || idxType == "class" || idxType == "function")
47 | continue;
48 |
49 | // Check for invalid characters
50 | local idxStr = idx.tostring();
51 | local reg = regexp("^[a-zA-Z0-9_]*$");
52 |
53 | if (!reg.match(idxStr))
54 | {
55 | printf("VSLib Warning: Index '%s' is invalid (invalid characters found), skipping...", idxStr);
56 | continue;
57 | }
58 |
59 | // Check for numeric fields and prefix them so system can compile
60 | reg = regexp("^[0-9]+$");
61 | if (reg.match(idxStr))
62 | idxStr = "_vslInt_" + idxStr;
63 |
64 |
65 | local preCompileString = ((indice) ? (idxStr + " = ") : "");
66 |
67 | switch (typeof val)
68 | {
69 | case "table":
70 | baseString += preCompileString + ::VSLib.FileIO.SerializeTable(val);
71 | break;
72 |
73 | case "string":
74 | baseString += preCompileString + "\"" + ::VSLib.Utils.StringReplace(::VSLib.Utils.StringReplace(val, "\"", "{VSQUOTE}"), @"\\", "{VSSLASH}") + "\"\n"; // "
75 | break;
76 |
77 | case "integer":
78 | baseString += preCompileString + val + "\n";
79 | break;
80 |
81 | case "float":
82 | baseString += preCompileString + val + "\n";
83 | break;
84 |
85 | case "array":
86 | baseString += preCompileString + ::VSLib.FileIO.SerializeTable(val, "[\n", "]\n", false);
87 | break;
88 |
89 | case "bool":
90 | baseString += preCompileString + ((val) ? "true" : "false") + "\n";
91 | break;
92 | }
93 | }
94 |
95 | baseString += predicateEnd;
96 |
97 | return baseString;
98 | }
99 |
100 | /**
101 | * This function will serialize and save a table to the hard disk; useful for storing stats,
102 | * round times, and other important information.
103 | */
104 | function VSLib::FileIO::SaveTable(fileName, table)
105 | {
106 | fileName += ".tbl";
107 | return StringToFile(fileName, ::VSLib.FileIO.SerializeTable(table));
108 | }
109 |
110 | /**
111 | * This function will clean table input.
112 | */
113 | function VSLib::FileIO::DeserializeReviseTable(t)
114 | {
115 | foreach (idx, val in t)
116 | {
117 | if (typeof val == "string")
118 | t[idx] = ::VSLib.Utils.StringReplace(::VSLib.Utils.StringReplace(val, "{VSQUOTE}", "\""), "{VSSLASH}", @"\"); // "
119 | else if (typeof val == "table")
120 | t[idx] = DeserializeReviseTable(val);
121 | }
122 |
123 | return t;
124 | }
125 |
126 | /**
127 | * This function will deserialize and return the compiled table.
128 | * If the table does not exist, null is returned.
129 | */
130 | function VSLib::FileIO::LoadTable(fileName)
131 | {
132 | local contents = FileToString(fileName + ".tbl");
133 |
134 | if (!contents)
135 | return null;
136 |
137 | local t = compilestring( "return " + contents )();
138 |
139 | foreach (idx, val in t)
140 | {
141 | local idxStr = idx.tostring();
142 |
143 | if (idxStr.find("_vslInt_") != null)
144 | {
145 | idxStr = Utils.StringReplace(idxStr, "_vslInt_", "");
146 | t[idxStr.tointeger()] <- val;
147 | delete t[idx];
148 | }
149 | }
150 |
151 | t = DeserializeReviseTable(t);
152 |
153 | return t;
154 | }
155 |
156 |
157 | /**
158 | * This function will make the filename unique for each mapname.
159 | * @authors Rayman1103
160 | */
161 | function VSLib::FileIO::MakeFileName( mapname, modename )
162 | {
163 | return "VSLib_" + mapname + "_" + modename;
164 | }
165 |
166 | /**
167 | * This function will serialize and save a table to the hard disk from the current mapname; useful for storing stats,
168 | * round times, and other important information individually for every mapname.
169 | * @authors Rayman1103
170 | */
171 | function VSLib::FileIO::SaveTableFileName(mapname, modename, table)
172 | {
173 | return ::VSLib.FileIO.SaveTable(::VSLib.FileIO.MakeFileName( mapname, modename ), table);
174 | }
175 |
176 | /**
177 | * This function will deserialize and return the compiled table from the current mapname.
178 | * If the table does not exist, null is returned.
179 | * @authors Rayman1103
180 | */
181 | function VSLib::FileIO::LoadTableFileName(mapname, modename)
182 | {
183 | return ::VSLib.FileIO.LoadTable(::VSLib.FileIO.MakeFileName( mapname, modename ));
184 | }
185 |
186 |
187 |
188 | // Add a weak reference to the global table.
189 | ::FileIO <- ::VSLib.FileIO.weakref();
--------------------------------------------------------------------------------
/vscripts/LinGe/VSLib/randomitemspawner.nut:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 Rectus
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | * and associated documentation files (the "Software"), to deal in the Software without
6 | * restriction, including without limitation the rights to use, copy, modify, merge, publish,
7 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
8 | * Software is furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | */
20 |
21 |
22 | /**
23 | * \brief Spawns random items on predefined spawnpoints.
24 | *
25 | * This class can spawn items randomly selected from a predefined list onto randomly selected spawnpoints.
26 | *
27 | * @param spawnPoints Array of vectors or VSLib entities where the items can spawn.
28 | * @param items Array of item entries the spawner chooses from.
29 | * @param flags Option flags. Currently supports RANDOM_USEPARTICLES and RANDOM_ALLOWMULTIPLEITEMS.
30 | *
31 | */
32 | class ::VSLib.RandomItemSpawner
33 | {
34 | /*
35 | * This is a list of the currently supported items.
36 | *
37 | * ent: Classname of the item. The spawn list currently supports the entities specified below.
38 | * prob: This is the probability for the item to spawn. It's relative to the other items.
39 | * ammo: The ammo reserves primary weapons spawn with. Weapons spawn with double the value set.
40 | * Set to null on other items.
41 | * melee_type: Works the same way as on a weapon_melee_spawn. Set to null if not a melee weapon.
42 | */
43 | static _defaultItems =
44 | [
45 | //Entity: Probability: Ammo: Melee type:
46 | {ent = "weapon_rifle" prob = 10, ammo = 50, melee_type = null },
47 | {ent = "weapon_shotgun_spas" prob = 10, ammo = 10, melee_type = null },
48 | {ent = "weapon_sniper_military" prob = 10, ammo = 15, melee_type = null },
49 | {ent = "weapon_rifle_ak47" prob = 10, ammo = 40, melee_type = null },
50 | {ent = "weapon_autoshotgun" prob = 10, ammo = 10, melee_type = null },
51 | {ent = "weapon_rifle_desert" prob = 10, ammo = 60, melee_type = null },
52 | {ent = "weapon_hunting_rifle" prob = 15, ammo = 15, melee_type = null },
53 |
54 | {ent = "weapon_rifle_m60" prob = 2, ammo = 50, melee_type = null },
55 | {ent = "weapon_grenade_launcher" prob = 2, ammo = 50, melee_type = null },
56 |
57 | {ent = "weapon_smg_silenced" prob = 20, ammo = 50, melee_type = null },
58 | {ent = "weapon_smg" prob = 20, ammo = 50, melee_type = null },
59 | {ent = "weapon_shotgun_chrome" prob = 20, ammo = 10, melee_type = null },
60 | {ent = "weapon_pumpshotgun" prob = 20, ammo = 10, melee_type = null },
61 |
62 | {ent = "weapon_pistol_magnum" prob = 5, ammo = null, melee_type = null },
63 | {ent = "weapon_pistol" prob = 10, ammo = null, melee_type = null },
64 |
65 | {ent = "weapon_adrenaline" prob = 10, ammo = null, melee_type = null },
66 | {ent = "weapon_pain_pills" prob = 20, ammo = null, melee_type = null },
67 | {ent = "weapon_vomitjar" prob = 3, ammo = null, melee_type = null },
68 | {ent = "weapon_molotov" prob = 10, ammo = null, melee_type = null },
69 | {ent = "weapon_pipe_bomb" prob = 10, ammo = null, melee_type = null },
70 | {ent = "weapon_first_aid_kit" prob = 1, ammo = null, melee_type = null },
71 |
72 |
73 | // Note: These items don't retain their entities when spawned, and cannot be tracked.
74 | {ent = "weapon_melee_spawn" prob = 10, ammo = null, melee_type = "any" },
75 | {ent = "upgrade_spawn" prob = 3, ammo = null, melee_type = null }, // Laser sight
76 | {ent = "weapon_upgradepack_explosive" prob = 5, ammo = null, melee_type = null },
77 | {ent = "weapon_upgradepack_incendiary" prob = 7, ammo = null, melee_type = null },
78 |
79 | ];
80 | _totalProbability = 0;
81 | _numSpawns = 0;
82 | _spawnPoints = [];
83 | _items = [];
84 | _useParticleEffects = false;
85 | _allowMultipleItemsOnPoint = false;
86 |
87 | constructor(spawnPoints, items = null, flags = 0)
88 | {
89 | if(items)
90 | _items = items;
91 | else
92 | _items = _defaultItems;
93 |
94 | _useParticleEffects = (flags & RANDOM_USEPARTICLES)
95 | _allowMultipleItemsOnPoint = (flags & RANDOM_ALLOWMULTIPLEITEMS)
96 |
97 | __FindItemSpawnPoints(spawnPoints);
98 | __CalcTotalProbability();
99 | }
100 |
101 | function _typeof()
102 | {
103 | return "VSLIB_RANDOM_ITEM_SPAWNER";
104 | }
105 |
106 | }
107 |
108 | /**
109 | * Global flags.
110 | */
111 | getconsttable()["RANDOM_USEPARTICLES"] <- 1;
112 | getconsttable()["RANDOM_ALLOWMULTIPLEITEMS"] <- 2;
113 |
114 |
115 |
116 | /**
117 | * Extracts spawnpoint locations and amount from an array of vectors or entities.
118 | */
119 | function VSLib::RandomItemSpawner::__FindItemSpawnPoints(spawns)
120 | {
121 | local spawnPoints = [];
122 | local numSpawns = 0;
123 |
124 | foreach(object in spawns)
125 | {
126 | switch(typeof object)
127 | {
128 | case "Vector":
129 | spawnPoints.push(Vector(0,0,0) + object);
130 | numSpawns++;
131 | break;
132 |
133 | case "VSLIB_ENTITY":
134 | case "VSLIB_PLAYER":
135 | spawnPoints.push(object.GetLocation());
136 | numSpawns++;
137 | break;
138 |
139 | default:
140 | printl("VSLib Warning: Random item spawner: Invalid spawnpoint! " + object);
141 | }
142 | }
143 |
144 | if(numSpawns <= 0)
145 | printl("VSLib Error: Random item spawner: No item spawns found!");
146 | else
147 | printl("VSLib: Random item spawner: Found " + numSpawns
148 | + " item spawns.");
149 |
150 | _spawnPoints = spawnPoints;
151 | _numSpawns = numSpawns;
152 | }
153 |
154 | /**
155 | * Calculates the combined spawn probability of all items.
156 | */
157 | function VSLib::RandomItemSpawner::__CalcTotalProbability()
158 | {
159 | local totalProb = 0;
160 | foreach(item in _items)
161 | totalProb += item.prob;
162 |
163 | _totalProbability = totalProb;
164 | }
165 |
166 | /**
167 | * Spawns specified number of random items.
168 | *
169 | * @return Items spawned as an array of VSLib entities.
170 | */
171 | function VSLib::RandomItemSpawner::SpawnRandomItems(amount)
172 | {
173 | local spawnedItems = [];
174 | local spawnSet = clone _spawnPoints;
175 | local entity = null;
176 |
177 | for(local i = 0; i < amount; i++)
178 | {
179 | if(spawnSet.len() < 1)
180 | {
181 | printl("VSLib Warning: Random item spawner: Ran out of spawn points!");
182 | return spawnedItems;
183 | }
184 |
185 | local probCount = RandomInt(1, _totalProbability);
186 | local spawnIndex = RandomInt(0, spawnSet.len() -1);
187 |
188 | foreach(item in _items)
189 | {
190 | if((probCount -= item.prob) <= 0)
191 | {
192 | if(entity = __SpawnSingleItem(g_ModeScript.DuplicateTable(item), spawnSet[spawnIndex]))
193 | spawnedItems.push(entity);
194 |
195 | break;
196 | }
197 | }
198 | if(!_allowMultipleItemsOnPoint)
199 | spawnSet.remove(spawnIndex);
200 | }
201 |
202 | return spawnedItems;
203 | }
204 |
205 |
206 | /**
207 | * Generates an entity table and spawns an item of the specified type.
208 | */
209 | function VSLib::RandomItemSpawner::__SpawnSingleItem(item, origin)
210 | {
211 | local entTable = {};
212 |
213 | if(item.ammo != null) // Gun
214 | entTable =
215 | {
216 | targetname = "random_spawned_item"
217 | classname = item.ent
218 | ammo = item.ammo
219 | origin = origin
220 | angles = Vector(0, RandomFloat(0, 360), (RandomInt(0,1) * 180 - 90))
221 | solid = "6" // Vphysics
222 | }
223 | else if(item.melee_type != null) // Melee weapon
224 | entTable =
225 | {
226 | targetname = "random_spawned_nontrackable"
227 | classname = item.ent
228 | origin = origin
229 | angles = Vector(0, RandomFloat(0, 360), (RandomInt(0,1) * 180 - 90))
230 | solid = "6" // Vphysics
231 | melee_weapon = item.melee_type
232 | spawnflags = 3
233 | }
234 | else if(item.ent == "upgrade_spawn") // Laser upgrade
235 | {
236 | entTable =
237 | {
238 | targetname = "random_spawned_nontrackable"
239 | classname = item.ent
240 | origin = origin
241 | angles = Vector(0, RandomFloat(0, 360), 0)
242 | solid = "6" // Vphysics
243 | laser_sight = 1
244 | upgradepack_incendiary = 0
245 | upgradepack_explosive = 0
246 | }
247 | }
248 | else if((item.ent == "weapon_upgradepack_explosive") || (item.ent == "weapon_upgradepack_incendiary"))
249 | {
250 | entTable =
251 | {
252 | targetname = "random_spawned_nontrackable"
253 | classname = item.ent
254 | origin = origin
255 | angles = Vector(0, RandomFloat(0, 360), 0)
256 | solid = "6" // Vphysics
257 | }
258 | }
259 | else // Any other item
260 | entTable =
261 | {
262 | targetname = "random_spawned_item"
263 | classname = item.ent
264 | origin = origin
265 | angles = Vector(0, RandomFloat(0, 360), 0)
266 | solid = "6" // Vphysics
267 | }
268 |
269 | local itemEntity = g_ModeScript.CreateSingleSimpleEntityFromTable(entTable);
270 |
271 | if(itemEntity)
272 | {
273 | if(_useParticleEffects)
274 | g_ModeScript.CreateParticleSystemAt(itemEntity, Vector(0,0,-8), "mini_fireworks");
275 |
276 | if(entTable.targetname == "random_spawned_item")
277 | return ::VSLib.Entity(itemEntity);
278 | }
279 | return null;
280 | }
281 |
--------------------------------------------------------------------------------
/vscripts/LinGe/VSLib/timer.nut:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013 LuKeM aka Neil - 119 and Rayman1103
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
5 | * and associated documentation files (the "Software"), to deal in the Software without
6 | * restriction, including without limitation the rights to use, copy, modify, merge, publish,
7 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
8 | * Software is furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
14 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | */
20 |
21 |
22 | /**
23 | * \brief A timer system to call a function after a certain amount of time.
24 | *
25 | * The Timer table allows the developer to easily add synchronized callbacks.
26 | */
27 | if (!("Timers" in ::VSLib))
28 | {
29 | ::VSLib.Timers <-
30 | {
31 | TimersList = {}
32 | TimersID = {}
33 | ClockList = {}
34 | count = 0
35 | }
36 | }
37 |
38 | /*
39 | * Constants
40 | */
41 |
42 | // Passable constants
43 | getconsttable()["NO_TIMER_PARAMS"] <- null; /** No timer params */
44 |
45 | // Internal constants
46 | const UPDATE_RATE = 0.1; /** Fastest possible update rate */
47 |
48 | // Flags
49 | getconsttable()["TIMER_FLAG_KEEPALIVE"] <- (1 << 1); /** Keep timer alive even after RoundEnd is called */
50 | getconsttable()["TIMER_FLAG_COUNTDOWN"] <- (1 << 2); /** Fire the timer the specified number of times before the timer removes itself */
51 | getconsttable()["TIMER_FLAG_DURATION"] <- (1 << 3); /** Fire the timer each interval for the specified duration */
52 | getconsttable()["TIMER_FLAG_DURATION_VARIANT"] <- (1 << 4); /** Fire the timer each interval for the specified duration, regardless of internal function call time loss */
53 |
54 |
55 | /**
56 | * Creates a named timer that will be added to the timers list. If a named timer already exists,
57 | * it will be replaced.
58 | *
59 | * @return Name of the created timer
60 | */
61 | function VSLib::Timers::AddTimerByName(strName, delay, repeat, func, paramTable = null, flags = 0, value = {})
62 | {
63 | ::VSLib.Timers.RemoveTimerByName(strName);
64 | ::VSLib.Timers.TimersID[strName] <- ::VSLib.Timers.AddTimer(delay, repeat, func, paramTable, flags, value);
65 | return strName;
66 | }
67 |
68 | /**
69 | * Deletes a named timer.
70 | */
71 | function VSLib::Timers::RemoveTimerByName(strName)
72 | {
73 | if (strName in ::VSLib.Timers.TimersID)
74 | {
75 | ::VSLib.Timers.RemoveTimer(::VSLib.Timers.TimersID[strName]);
76 | delete ::VSLib.Timers.TimersID[strName];
77 | }
78 | }
79 |
80 | /**
81 | * Calls a function and passes the specified table to the callback after the specified delay.
82 | */
83 | function VSLib::Timers::AddTimer(delay, repeat, func, paramTable = null, flags = 0, value = {})
84 | {
85 | local TIMER_FLAG_COUNTDOWN = (1 << 2);
86 | local TIMER_FLAG_DURATION = (1 << 3);
87 | local TIMER_FLAG_DURATION_VARIANT = (1 << 4);
88 |
89 | delay = delay.tofloat();
90 | repeat = repeat.tointeger();
91 |
92 | local rep = (repeat > 0) ? true : false;
93 |
94 | if (delay < UPDATE_RATE)
95 | {
96 | printl("VSLib Warning: Timer delay cannot be less than " + UPDATE_RATE + " second(s). Delay has been reset to " + UPDATE_RATE + ".");
97 | delay = UPDATE_RATE;
98 | }
99 |
100 | if (paramTable == null)
101 | paramTable = {};
102 |
103 | if (typeof value != "table")
104 | {
105 | printf("VSLib Timer Error: Illegal parameter: 'value' parameter needs to be a table.");
106 | return -1;
107 | }
108 | else if (flags & TIMER_FLAG_COUNTDOWN && !("count" in value))
109 | {
110 | printf("VSLib Timer Error: Could not create the countdown timer because the 'count' field is missing from 'value'.");
111 | return -1;
112 | }
113 | else if ((flags & TIMER_FLAG_DURATION || flags & TIMER_FLAG_DURATION_VARIANT) && !("duration" in value))
114 | {
115 | printf("VSLib Timer Error: Could not create the duration timer because the 'duration' field is missing from 'value'.");
116 | return -1;
117 | }
118 |
119 | // Convert the flag into countdown
120 | if (flags & TIMER_FLAG_DURATION)
121 | {
122 | flags = flags & ~TIMER_FLAG_DURATION;
123 | flags = flags | TIMER_FLAG_COUNTDOWN;
124 |
125 | value["count"] <- floor(value["duration"].tofloat() / delay);
126 | }
127 |
128 | ++count;
129 | TimersList[count] <-
130 | {
131 | _delay = delay
132 | _func = func
133 | _params = paramTable
134 | _startTime = Time()
135 | _baseTime = Time()
136 | _repeat = rep
137 | _flags = flags
138 | _opval = value
139 | }
140 |
141 | return count;
142 | }
143 |
144 | /**
145 | * Removes the specified timer.
146 | */
147 | function VSLib::Timers::RemoveTimer(idx)
148 | {
149 | if (idx in TimersList)
150 | delete ::VSLib.Timers.TimersList[idx];
151 | }
152 |
153 | /**
154 | * Manages VSLib timers.
155 | */
156 | function VSLib::Timers::ManageTimer(idx, command, value = null, allowNegTimer = false)
157 | {
158 | if ( idx in ::VSLib.Timers.ClockList && value == null )
159 | {
160 | ::VSLib.Timers.ClockList[idx]._command <- command;
161 | ::VSLib.Timers.ClockList[idx]._allowNegTimer <- allowNegTimer;
162 | }
163 | else
164 | {
165 | if ( value == null )
166 | value = 0;
167 |
168 | ::VSLib.Timers.ClockList[idx] <-
169 | {
170 | _value = value
171 | _startTime = Time()
172 | _lastUpdateTime = Time()
173 | _command = command
174 | _allowNegTimer = allowNegTimer
175 | }
176 | }
177 | }
178 |
179 | /**
180 | * Returns the value of a VSLib timer.
181 | */
182 | function VSLib::Timers::ReadTimer(idx)
183 | {
184 | if ( idx in ::VSLib.Timers.ClockList )
185 | return ::VSLib.Timers.ClockList[idx]._value;
186 |
187 | return null;
188 | }
189 |
190 | /**
191 | * Returns a VSLib timer as a displayable string --:--.
192 | */
193 | function VSLib::Timers::DisplayTime(idx)
194 | {
195 | return ::VSLib.Utils.GetDisplayTime(::VSLib.Timers.ReadTimer(idx));
196 | }
197 |
198 | /**
199 | * Manages all timers and provides interface for custom updates.
200 | */
201 | ::VSLib.Timers._thinkFunc <- function()
202 | {
203 | if (!("VSLib" in getroottable()))
204 | return;
205 |
206 | local TIMER_FLAG_COUNTDOWN = (1 << 2);
207 | local TIMER_FLAG_DURATION_VARIANT = (1 << 4);
208 |
209 | // current time
210 | local curtime = Time();
211 |
212 | // Execute timers as needed
213 | foreach (idx, timer in ::VSLib.Timers.TimersList)
214 | {
215 | if ((curtime - timer._startTime) >= timer._delay)
216 | {
217 | if (timer._flags & TIMER_FLAG_COUNTDOWN)
218 | {
219 | timer._params["TimerCount"] <- timer._opval["count"];
220 |
221 | if ((--timer._opval["count"]) <= 0)
222 | timer._repeat = false;
223 | }
224 |
225 | if (timer._flags & TIMER_FLAG_DURATION_VARIANT && (curtime - timer._baseTime) > timer._opval["duration"])
226 | {
227 | delete ::VSLib.Timers.TimersList[idx];
228 | continue;
229 | }
230 |
231 | try
232 | {
233 | if (timer._func(timer._params) == false)
234 | timer._repeat = false;
235 | }
236 | catch (id)
237 | {
238 | printf("VSLib Timer caught exception; closing timer %d. Error was: %s", idx, id.tostring());
239 | local deadFunc = timer._func;
240 | local params = timer._params;
241 | delete ::VSLib.Timers.TimersList[idx];
242 | deadFunc(params); // this will most likely throw
243 | continue;
244 | }
245 |
246 | if (timer._repeat)
247 | timer._startTime = curtime;
248 | else
249 | if (idx in ::VSLib.Timers.TimersList) // recheck-- timer may have been removed by timer callback
250 | delete ::VSLib.Timers.TimersList[idx];
251 | }
252 | }
253 | foreach (idx, timer in ::VSLib.Timers.ClockList)
254 | {
255 | if ( Time() > timer._lastUpdateTime )
256 | {
257 | local newTime = Time() - timer._lastUpdateTime;
258 |
259 | if ( timer._command == 1 )
260 | timer._value += newTime;
261 | else if ( timer._command == 2 )
262 | {
263 | if ( timer._allowNegTimer )
264 | timer._value -= newTime;
265 | else
266 | {
267 | if ( timer._value > 0 )
268 | timer._value -= newTime;
269 | }
270 | }
271 |
272 | timer._lastUpdateTime <- Time();
273 | }
274 | }
275 | }
276 |
277 | /*
278 | * Create a think timer
279 | */
280 | if (!("_thinkTimer" in ::VSLib.Timers))
281 | {
282 | ::VSLib.Timers._thinkTimer <- SpawnEntityFromTable("info_target", { targetname = "vslib_timer" });
283 | if (::VSLib.Timers._thinkTimer != null)
284 | {
285 | ::VSLib.Timers._thinkTimer.ValidateScriptScope();
286 | local scrScope = ::VSLib.Timers._thinkTimer.GetScriptScope();
287 | scrScope["ThinkTimer"] <- ::VSLib.Timers._thinkFunc;
288 | AddThinkToEnt(::VSLib.Timers._thinkTimer, "ThinkTimer");
289 | }
290 | else
291 | throw "VSLib Error: Timer system could not be created; Could not create dummy entity";
292 | }
293 |
294 |
295 | // Add a weakref
296 | ::Timers <- ::VSLib.Timers.weakref();
--------------------------------------------------------------------------------
/vscripts/LinGe/zs.nut:
--------------------------------------------------------------------------------
1 | // 自杀功能脚本
2 | ::LinGe.zs <- {};
3 |
4 | ::LinGe.zs.Config <- {
5 | enabled = true,
6 | hint = true,
7 | incap = "我不想变成魔女,这个世界还有许多我想守护的东西",
8 | noIncap = "灵魂宝石会孕育出魔女的话,大家不就只有去死了吗!"
9 | };
10 | ::LinGe.Config.Add("zs", ::LinGe.zs.Config);
11 | //::LinGe.Cache.zs_Config <- ::LinGe.zs.Config;
12 |
13 | if (!::LinGe.isVersus && ::LinGe.zs.Config.enabled) {
14 | printl("[LinGe] 自杀指令 正在载入");
15 | // !zs 自杀指令
16 | ::LinGe.zs.Cmd_zs <- function (player, args)
17 | {
18 | if (args.len() == 1)
19 | {
20 | if (::LinGe.GetPlayerTeam(player) != 2)
21 | return;
22 |
23 | local vplayer = ::VSLib.Player(player);
24 | if (!vplayer.IsPlayerEntityValid())
25 | return;
26 | if (!vplayer.IsAlive() || vplayer.IsDead())
27 | return;
28 |
29 | local isIncapacitated = vplayer.IsIncapacitated();
30 | vplayer.Kill();
31 | if (Config.hint) // 如果开启了自杀后提示
32 | {
33 | if (!vplayer.IsAlive() || vplayer.IsDead()) // 可能不准
34 | {
35 | if (isIncapacitated)
36 | {
37 | Say(player, "\x03" + Config.incap, false);
38 | }
39 | else
40 | {
41 | Say(player, "\x03" + Config.noIncap, false);
42 | }
43 | }
44 | }
45 | }
46 | }
47 | ::LinCmdAdd("zs", ::LinGe.zs.Cmd_zs, ::LinGe.zs, "自杀指令", false);
48 |
49 | }
--------------------------------------------------------------------------------
/vscripts/director_base_addon.nut:
--------------------------------------------------------------------------------
1 | IncludeScript("LinGe/VSLib"); // 必须 VSLib库
2 | IncludeScript("LinGe/Base"); // 必须 基础库 注册事件函数,实现了玩家人数统计、命令与权限管理
3 | // 请不要更改必须库的载入顺序,否则将无法正确载入脚本
4 | IncludeScript("LinGe/HUD"); // 可选 HUD 击杀与伤害统计 友伤提示等
5 | IncludeScript("LinGe/MoreSI"); // 可选 简易的多特控制
6 | IncludeScript("LinGe/zs"); // 可选 自杀指令
7 | IncludeScript("LinGe/Hint"); // 可选 玩家状态提示与物品标记功能
8 | IncludeScript("LinGe/RewardHP"); // 可选 击杀回复血量
--------------------------------------------------------------------------------
/vscripts/scriptedmode_addon.nut:
--------------------------------------------------------------------------------
1 | // 这个只是拿AdminSystem里的同名文件改了一下函数名字
2 | // 这个文件是必须的,且文件名不能随意更改,否则脚本无法正常工作
3 | // 我不太清楚这个的具体作用,因为对求生之路的游戏机制还不是特别了解
4 |
5 | ///////////////////////////////////////////////////////////////////////////////
6 | // Scriptedmode.nut
7 | // this holds the "control logic" for all scriptmodes, and loads up the Mode
8 | // and Map specific subscripts thus it has various initialization,
9 | // default/override table merging, and a "root" manager class
10 | ///////////////////////////////////////////////////////////////////////////////
11 |
12 | LinGe_ScriptMode_Init <- ScriptMode_Init;
13 | //=========================================================
14 | // called from C++ when you try and kick off a mode to
15 | // decide whether scriptmode wants to handle it
16 | //=========================================================
17 | function ScriptMode_Init( modename, mapname )
18 | {
19 | local bScriptedModeValid = LinGe_ScriptMode_Init( modename, mapname );
20 |
21 | //Include server.nut for LinGe Scripts
22 | IncludeScript("server");
23 |
24 | if ( !bScriptedModeValid )
25 | {
26 | printl( "Enabled ScriptMode for " + modename + " and now Initializing" );
27 |
28 | IncludeScript( mapname + "_" + modename, g_MapScript );
29 |
30 | // Add to the spawn array
31 | MergeSessionSpawnTables();
32 | MergeSessionStateTables();
33 |
34 | SessionState.MapName <- mapname;
35 | SessionState.ModeName <- modename;
36 |
37 | // If not specified, start active by default
38 | if ( !( "StartActive" in SessionState ) )
39 | {
40 | SessionState.StartActive <- true;
41 | }
42 |
43 | if ( SessionState.StartActive )
44 | {
45 | MergeSessionOptionTables();
46 | }
47 |
48 | // Sanitize the map
49 | if ( "SanitizeTable" in this )
50 | {
51 | SanitizeMap( SanitizeTable );
52 | }
53 |
54 | if ( "SessionSpawns" in getroottable() )
55 | {
56 | EntSpawn_DoIncludes( ::SessionSpawns );
57 | }
58 |
59 | // include all helper stuff before building the help
60 | IncludeScript( "sm_stages", g_MapScript );
61 |
62 | // check for any scripthelp_ strings and create help entries for them
63 | AddToScriptHelp( getroottable() );
64 | AddToScriptHelp( g_MapScript );
65 | AddToScriptHelp( g_ModeScript );
66 |
67 | // go ahead and call all the precache elements - the MapSpawn table ones then any explicit OnPrecache's
68 | ScriptedPrecache();
69 | ScriptMode_SystemCall("Precache");
70 | }
71 |
72 | return true;
73 | }
--------------------------------------------------------------------------------