Scripting API文档:
https://developer.valvesoftware.com/wiki/Counter-Strike_2_Workshop_Tools/Scripting_API
Scripting API文档(Scripting API - Valve Developer Community,主要针对 Counter-Strike 2 Workshop Tools 的 cs_script API)为开发者提供了强大的工具,用于创建自定义游戏模式、地图逻辑和事件处理。
该 API 的功能可以总结为以下几个核心领域:
1、顶层 Instance:脚本的"入口工具箱"
Instance 是挂在 point_script 实体上的顶层 API,绝大多数实用功能都从这里进来。
1.1 控制客户端 & 服务器命令
-
ClientCommand(playerSlot, command) 对指定玩家执行控制台指令(相当于在该客户端敲命令)。
-
ServerCommand(command) 在服务器上执行控制台指令(改 cvar、切图之类)。
-
Msg(text) 在服务器控制台输出日志,方便调试。
用途:自定义管理命令、一键配置训练服、自动执行 warmup / match 相关指令等。
1.2 调试绘制:画线、画盒子、屏幕文字
只在开发环境中可见,用于调试脚本逻辑:
-
DebugBox({ mins, maxs, duration?, color? }):在世界里画一个 AABB 盒子。
-
DebugLine({ start, end, duration?, color? }):画一条 3D 线段。
-
DebugSphere({ center, radius, duration?, color? }):画线框球。
-
DebugScreenText({ text, x, y, duration?, color? }):在游戏画面上写字。
用途:可视化碰撞盒、子弹轨迹、触发区、调试逻辑状态等。
1.3 实体查找与 I/O 驱动
-
查找实体:
-
FindEntitiesByClass(className) / FindEntityByClass(className)
-
FindEntitiesByName(name) / FindEntityByName(name)
-
-
触发 Hammer I/O:
-
EntFireAtName({ name, input, value?, caller?, activator?, delay? })
-
EntFireAtTarget({ target, input, value?, caller?, activator?, delay? })
-
-
输出连接:
- ConnectOutput(target, output, callback) / DisconnectOutput(id) 把实体的输出(如 OnStartTouch)连到脚本回调。
用途:脚本侧驱动传统 Hammer 逻辑、替换复杂 I/O 图、做"脚本触发器"。
1.4 游戏状态与时间
-
GetGameMode() / GetGameType():当前游戏模式 & 类型(参考 CS:GO 的 game modes 列表)。
-
GetMapName():当前地图名。
-
GetRoundsPlayed():当前局已经打了多少回合。
-
IsFreezePeriod() / IsWarmupPeriod():是否冻结时间 / 热身阶段。
-
GetGameTime():当前游戏时间(秒)。
用途:做基于回合/时间的脚本(比如 warmup 特殊逻辑、OT 规则、自定义回合流程)。
1.5 Think 回调:定时执行逻辑
-
SetThink(callback):设置 "每次 think 时调用的函数"。
-
SetNextThink(time):控制下次 think 触发的时间(秒)。
用途:定时检查状态、做简单的"每帧/定时 tick"逻辑,不需要额外实体。
1.6 碰撞 / 子弹 / 视线检测
一组 Trace 工具,用于计算射线、盒子、球体碰撞和子弹仿真:
-
TraceLine(trace: BaseTraceConfig): TraceResult
-
TraceBox({ mins, maxs } & BaseTraceConfig): TraceResult
-
TraceSphere({ radius } & BaseTraceConfig): TraceResult
-
TraceBullet(trace: BulletTrace): BulletTraceResult[]
其中:
-
BaseTraceConfig:start, end, ignoreEntity, ignorePlayers, traceHitboxes 等。
-
BulletTrace:start, end, damage, penetration, rangeModifier, shooter(会被忽略碰撞)。
-
TraceResult / BulletTraceResult:返回是否命中、命中实体、命中部位(HitGroup)、位置、法线、伤害值等。
用途:
-
自己做"是否能看到此点"、自定义打点检测;
-
模拟子弹穿透 & 伤害,用于教学/训练地图(墙穿可视化等);
-
做自定义技能 / 击中检测。
1.7 事件 Hooks:绑定游戏事件回调
通过 Instance 上的一系列 OnXXX 注册事件回调:
玩家/连接相关
-
OnPlayerConnect, OnPlayerActivate, OnPlayerDisconnect
-
OnPlayerChat(可拿到 text、team)、OnPlayerPing(ping 的位置)
-
OnPlayerJump, OnPlayerLand, OnPlayerReset(重生/换队/回 spawn)
战斗和炸弹相关
-
OnBeforePlayerDamage:玩家即将受到伤害,可修改 damage 或中止。
-
OnPlayerDamage:玩家已经扣血之后的事件。
-
OnPlayerKill:玩家被击杀(提供 attacker、weapon、inflictor)。
-
OnGunFire, OnGunReload, OnKnifeAttack
-
OnGrenadeThrow, OnGrenadeBounce
-
OnBulletImpact:子弹每次击中面都触发(包括穿透多次)。
-
OnBombPlant, OnBombDefuse
回合与脚本自身
-
OnRoundStart, OnRoundEnd(给出胜方 & 结束原因 CSRoundEndReason)。
-
OnActivate:point_script 实体被激活时。
-
OnScriptInput(name, callback):point_script 的自定义输入触发。
-
OnScriptReload({ before, after }):Tools 模式重载脚本时进行状态保存/恢复。
用途:
-
自定义计分、练习图统计、回放收集;
-
自建 mini 游戏、特殊伤害模式、限制武器模式;
-
在炸弹事件/回合事件上挂逻辑(如比分板、额外奖励等)。
2、实体层:Entity & BaseModelEntity
2.1 Entity:所有实体共同的基础操作
Entity 是所有实体的基类。
获取状态
-
位置/朝向/速度: GetAbsOrigin, GetAbsAngles, GetAbsVelocity GetLocalOrigin, GetLocalAngles, GetLocalVelocity
-
名称与 class:GetEntityName, GetClassName
-
团队:GetTeamNumber
-
生命:GetHealth, GetMaxHealth
-
其他:GetParent, GetOwner, GetGroundEntity(脚下地面实体),IsAlive, IsValid, IsWorld 等。
修改状态
-
生命与拥有者:SetHealth, SetMaxHealth, SetOwner
-
父子关系:SetParent
-
名称:SetEntityName
-
传送/改变动量:Teleport({ position?, angles?, velocity? })
-
伤害/删除:TakeDamage(entityDamage), Kill(), Remove()
用途:几乎所有"操作实体"的需求都可以通过这些 API 实现,比如传送玩家/道具、设置血量、做自杀/清理实体等。
2.2 BaseModelEntity:有模型的实体
继承自 Entity,专门针对有模型的实体(玩家、武器等)。
-
SetModel(modelName):切模型。
-
SetModelScale(scale):缩放。
-
SetColor(color):改渲染颜色。
-
Glow(color?) / Unglow():设置/取消 glow 效果。
用途:做高亮提示、模型切换、可视化标记等。
3、玩家相关类
3.1 CSPlayerController
控制"玩家控制器"(账号/slot 层),继承自 Entity。
-
玩家信息:GetPlayerName, GetPlayerSlot, IsBot, IsConnected, IsObserving
-
pawn / observer:
-
GetPlayerPawn():返回当前控制的 CSPlayerPawn
-
GetObserverPawn():观察者 pawn
-
-
队伍 & 分数:
-
JoinTeam(team)
-
GetScore(), AddScore(points)(可加负分但不会 < 0)
-
-
武器配置:
- GetWeaponDataForLoadoutSlot(slot, team?):查看指定 Loadout 槽位的武器数据。
用途:做排行榜、自定义计分、管理玩家队伍、根据 Loadout 做限制等。
3.2 CSObserverPawn
观战用 pawn,继承自 BaseModelEntity。
-
观战模式:GetObserverMode(), SetObserverMode(mode)
-
控制器关系:
-
GetOriginalPlayerController()
-
GetPlayerController()
-
用途:自定义观战视角逻辑、限制/引导观战行为。
3.3 CSPlayerPawn
真正的"玩家身体",继承自 BaseModelEntity。
武器操作
-
GiveNamedItem(name, autoDeploy?):给玩家一把指定名称的武器。
-
FindWeapon(name) / FindWeaponBySlot(slot)
-
GetActiveWeapon()
-
SwitchToWeapon(weapon)
-
DropWeapon(weapon)
-
DestroyWeapon(weapon) / DestroyWeapons()
状态相关
-
GetArmor(), SetArmor(value)
-
姿态:IsCrouched(), IsCrouching()
-
是否 noclip:IsNoclipping()
-
控制器:GetPlayerController(), GetOriginalPlayerController()
用途:
-
自定义出生物资 / 限制武器;
-
练习地图给特定武器组合;
-
根据状态做触发,例如"蹲下才触发区域"等。
4、武器相关类
4.1 CSWeaponBase
继承 BaseModelEntity,代表一把实际的武器实体。
-
GetOwner():持有这把武器的 CSPlayerPawn。
-
GetData():返回 CSWeaponData(静态配置)。
4.2 CSWeaponData
主要是这把武器的"配置参数":
-
基础伤害:GetDamage()
-
穿透力:GetPenetration()
-
射程:GetRange()
-
距离衰减:GetRangeModifier()(公式:nextDamage = currentDamage * rangeModifier^(distance/500))
-
价格:GetPrice()
-
类型/槽位:GetType(): CSWeaponType, GetGearSlot(): CSGearSlot
用途:
-
画出武器面板、对比枪械;
-
自定义经济 / 价格逻辑;
-
配合 TraceBullet 做更真实/自定义的伤害模拟。
5、其它:PointTemplate
PointTemplate 继承 Entity,主要提供:
- ForceSpawn(origin?, angle?): 根据模板实例化一批实体,返回生成的实体数组。
用途:脚本动态刷一批预设好的场景/道具,比如训练靶子、地图机关组合等。
6、接口(Interfaces):伤害 & 追踪数据结构
这些是 TypeScript 类型接口,用于描述事件参数和 Trace 结果。
-
伤害相关:
-
BeforePlayerDamageEvent / BeforePlayerDamageModify
-
EntityDamage
-
PlayerDamageEvent 统一描述:攻击者、被攻击玩家、伤害数值、伤害类型(CSDamageTypes)、Flags(CSDamageFlags)、武器、inflictor 等。
-
-
追踪相关:
-
BulletTrace, BaseTraceConfig:Trace 的输入配置。
-
BulletTraceResult, TraceResult:Trace 的结果(是否命中、命中实体/部位、位置、伤害等)。
-
用途:做复杂的伤害改写逻辑(例如腿部伤害统一减半、爆头额外处理、防止队友伤害等)。
7、枚举(Enums):统一游戏常量
API 还定义了一系列枚举,避免魔法数字:
-
CSDamageFlags:控制伤害行为(如 SUPPRESS_HEALTH_CHANGES, PREVENT_DEATH, FORCE_DEATH 等)。
-
CSDamageTypes:伤害类型(子弹、爆炸、跌落、近战、毒、溺水、爆头等)。
-
CSGearSlot:装备槽(RIFLE, PISTOL, KNIFE, GRENADES, C4, BOOSTS)。
-
CSHitGroup:命中部位(HEAD, CHEST, STOMACH, LEFTARM, RIGHTLEG 等)。
-
CSLoadoutSlot:玩家 Loadout 槽位(SECONDARY0/1/...,RIFLE0/1/... 等)。
-
CSRoundEndReason:回合结束原因(DRAW, BOMB_DEFUSED, TARGET_BOMBED, CTS_WIN, TERRORISTS_WIN, SURRENDER 等)。
-
CSWeaponAttackType:攻击类型(PRIMARY / SECONDARY)。
-
CSWeaponType:武器大类(PISTOL, RIFLE, KNIFE, GRENADE, EQUIPMENT 等)。
8、类型别名(Type Aliases)
一些常用的结构类型快捷别名:
-
BeforeDamageResult = { damage?: number, abort?: boolean } | void ------ OnBeforePlayerDamage 回调的返回类型,用于改伤害或取消。
-
Color = { r: number, g: number, b: number, a?: number }(0--255)
-
InputValue = boolean | number | string | Vector | Color | undefined
-
QAngle = { pitch: number, yaw: number, roll: number }
-
Vector = { x: number, y: number, z: number }
使用 GSI 获取 CS2 的游戏数据
要在外部 Python 程序中获取 Counter-Strike 2(CS2)的游戏数据,标准的和推荐的方法是使用 游戏状态集成(Game State Integration, GSI)。
步骤一:配置 GSI
需要在 CS2 的配置文件夹中创建一个 GSI 配置文件,让游戏将数据推送到 Python 程序。
-
找到 CS2 配置目录(通常是 \steamapps\common\Counter-Strike Global Offensive\game\csgo\cfg)。
-
创建一个名为 gamestate_integration_python.cfg 的文件。
-
将以下内容粘贴到文件中(请确保 uri 部分的端口号与 Python 代码中设置的端口号一致,例如 3000):
python
"Python GSI"
{
"uri" "http://127.0.0.1:3000/cs2_gsi"
"timeout" "5.0"
"buffer" "0.1"
"throttle" "0.1"
"heartbeat" "30.0"
"auth"
{
"token" "example_token_12345"
}
"output"
{
"precision_time" "3"
"precision_position" "3"
"precision_vector" "3"
}
"data"
{
// 最关键的几个开关
"provider" "1"
"map" "1"
"round" "1"
"player_id" "1"
"player_state" "1"
"player_weapons" "1"
"player_match_stats" "1"
"player_position" "1"
}
}
注意:
-
文件编码 UTF-8 (无 BOM )。
-
文件名格式:必须 gamestate_integration_xxx.cfg,不能少 gamestate_integration_ 这段前缀。
-
CS2 每次改 cfg 后要完全 重启 游戏。
步骤二:Python GSI 服务器代码
以下 Python 代码创建了一个简单的 HTTP 服务器,监听 CS2 发送的游戏状态数据,并从中提取所需的游戏信息。
python
from flask import Flask, request, jsonify
import json
app = Flask(__name__)
latest_state = {} # 用来缓存最近一次收到的游戏状态
@app.route("/cs2_gsi", methods=["POST"])
def cs2_gsi():
global latest_state
data = request.get_json(force=True, silent=True) or {}
# 缓存最近一次状态
latest_state = data
print("RAW JSON:")
print(json.dumps(data, indent=2, ensure_ascii=False))
# 从 JSON 里获取信息
# 下面这些字段命名是按 CS:GO/CS2 GSI 的常见格式写的,不同版本可能略有差别
# 1. 当前地图名
map_name = data.get("map", {}).get("name")
# 2. 当前玩家信息
player = data.get("player", {})
player_name = player.get("name")
team = player.get("team") # "T", "CT" 等
state = player.get("state", {})
health = state.get("health")
armor = state.get("armor")
helmet = state.get("helmet")
money = state.get("money")
equip_value = state.get("equip_value")
# 3. 武器信息(通常是一个字典,每个 key 是 weapon_X)
weapons_raw = player.get("weapons", {})
weapons = []
for wid, winfo in weapons_raw.items():
weapons.append({
"id": wid,
"name": winfo.get("name"),
"type": winfo.get("type"),
"state": winfo.get("state"), # active / holstered / etc.
"ammo_clip": winfo.get("ammo_clip"),
"ammo_reserve": winfo.get("ammo_reserve"),
"clip": winfo.get("ammo_clip"),
"clip_max": winfo.get("ammo_clip_max"),
"reserve": winfo.get("ammo_reserve"),
})
print("Money:", money)
print("Armor:", armor, "Helmet:", helmet)
print("equip_value:", equip_value)
print("Weapons:", weapons)
# 4. 当前位置
# 有的 GSI 提供 "position": "x,y,z" 这样的字符串
pos_str = player.get("position") # 例如 "123.4, -567.8, 90.0"
position = None
if isinstance(pos_str, str):
try:
x, y, z = map(float, pos_str.split(","))
position = {"x": x, "y": y, "z": z}
except ValueError:
pass
# 打印到控制台,方便调试
print("=== CS2 GSI Update ===")
print(f"Map: {map_name}")
print(f"Player: {player_name} | Team: {team} | HP: {health}")
print(f"Position: {position}")
print("Weapons:")
for w in weapons:
print(f" - {w['name']} ({w['type']}), state={w['state']}, "
f"clip={w['ammo_clip']}, reserve={w['ammo_reserve']}")
# 返回个简单 OK
return jsonify({"status": "ok"})
@app.route("/current_state", methods=["GET"])
def current_state():
"""
方便其它脚本查询当前缓存的状态:
GET /current_state 就能取最近一帧。
"""
return jsonify(latest_state or {})
if __name__ == "__main__":
# 监听本地 3000 端口,可以改其它端口
app.run(host="0.0.0.0", port=3000, debug=True)