Jump to content

Home

Lua Scripting For The Client Side


ensiform

Recommended Posts

The following commands are available to you with lua scripts:

 

cg.Print(string) -- print string to you
cg.ChatMsg(string) -- add message to your chatbox and print to console (not in top notify box)
cg.Broadcast(string) -- CP string to you
cg.OpenUIMenu(num) -- open specified number menu
cg.PlayerData(num) -- returns specified player data of you or person you are following if you are following someone
cg.LoadHud(string) -- load specified hud
cg.LuaExec(string) -- run specified lua script
cg.CleanStr(string) -- returns string with extended characters and 0-7 color codes removed
cg.CleanColor(string) -- returns string with color codes removed, not able to have blank or use alt+255 blank
cg.Time() -- return cg.time
cg.SVTime() -- return cg.snap->serverTime
cg.Milliseconds -- return trap_Milliseconds()
cg.Argc() -- return trap_Argc()
cg.Argv(num) -- return string from trap_Argv(num)
cg.ConcatArgs(start) -- return all arguments beginning from start as string
cg.IsEnsiMod() -- return boolean whether or not server is ensimod
cg.IsPublicBeta() -- return boolean whether server is EnsiMod Public Beta
cg.IsJAPlus() -- return boolean whether or not server is JA+
cg.EnsiModVer() -- return integer of ensimod server version (0.1.0 => 256)
cg.SiegeValid() -- return boolean if siegeRoundState is not 1 or 2
cg.AddCommand(string) -- add command to auto completion
cg.RemoveCommand(string) -- remove auto completion (and command from being used)
cg.LastAttacker() -- returns integer from CG_LastAttacker()
cg.CrosshairPlayer() -- returns integer from CG_CrosshairPlayer()
cg.Cvar_GetStr(name) -- return contents of cvar in string format
cg.Cvar_GetInt(name) -- return contents of cvar in integer format
cg.Cvar_GetFloat(name) -- returns contents of cvar in float format
cg.Cvar_Set(name,value) -- set cvar 'name' to 'value' value must be set, to clear use cg.Cvar_Clear(name) Note: cannot overwrite cheat state or read-only state
cg.Cvar_Clear(name) -- clears value of cvar 'name' Note: cannot overwrite cheat state or read-only state
cg.Command(string) -- send command like it came from client console / bind (basically anything you type in console)
cg.CommandToServer(string) -- send command to server that would be checked in g_cmds.c
cg.IsJedi() -- returns boolean whether or not you are a jedi in JvM mode
cg.IsMerc() -- returns boolean whether or not you are a merc in JvM mode
cg.IsJedivsMerc() -- returns boolean whether or not JvM mode is active
cg.IsJediMaster() -- returns boolean whether or not you are jedi master in Jedi Master mode
cg.DrawPic(x,y,w,h,shader) -- draw a pic on screen
cg.DrawText(x,y,scale,colorint,text,style,font) -- draw text on screen
cg.RegisterShader(string) -- register a shader/texture with engine for use (with cg.DrawPic)
cg.Gametype() -- return gametype number
cg.GetKeyCatcher() -- returns integer bitmask of what keycatchers are active (if any)
cg.SetKeyCatcher(int, 0/1) -- if there is a second arg and it is 1 then it will attempt to remove int keycatcher else it will attempt to enable it.
cg.ScoreboardActive() -- return boolean if scoreboard is active or not
cg.Info_ValueForKey(infostring,key) -- return contents of key in infostring
cg.FindClientNum(name) -- return client number from string passed
cg.RemoveEscapeChar(string) -- return '\x19' char from chat text for use with cg_ServerCommand(cmd)
cg.GetTranslatedString(refSection,refName) -- returns translated string in current language if the reference is in base strings file or EM language file.
cg.GetConfigString(num) -- return contents of configstring num
cg.FileOpen(string,mode) -- return fileHandle and length of file (game FS)
cg.FileClose(handle) -- close specified file handle (game FS)
cg.FileRead(handle,count) -- read count length from handle file, return contents of length told to read (game FS)
cg.FileWrite(data,writelen,handle) -- write data to file handle with specified length (game FS)
cg.GetFileList(path,extension) -- returns number of files and buffer list of files (game FS, buffer max forced at 4096)
cg.RegisterShader(string) -- returns handle of shader in int form
cg.DrawPic(x,y,w,h,shader) -- draw pic on screen
cg.DrawText(x,y,scale,intColor,string,style,font) -- draw text on screen
cg.StrIStr(string,find) -- returns boolean of whether find is found inside string

 

Basic, Package, Table, IO, OS, String, and Math Standard Lua Libraries enabled.

 

cgconst.lua:

-- Constants For Use with CGame of EnsiMod

-- some max defines that can be used
cg.MAX_CLIENTS = 32
cg.MAX_TERRAINS = 1
cg.MAX_LOCATIONS = 64
cg.MAX_MODELS = 512
cg.MAX_SOUNDS = 256
cg.MAX_ICONS = 64
cg.MAX_FX = 64
cg.MAX_G2BONES = 64
cg.MAX_SUB_BSP = 32
cg.MAX_AMBIENT_SETS = 256
cg.MAX_LIGHT_STYLES = 64
cg.MAX_CONFIG_STRINGS = 1700

-- for use with return of cg.GetKeyCatcher() and cg.SetKeyCatcher(X)
cg.KEYCATCH_CONSOLE = 1
cg.KEYCATCH_UI = 2
cg.KEYCATCH_MESSAGE = 4
cg.KEYCATCH_CGAME = 8

-- for cg.DrawPic
cg.SCREEN_WIDTH = 640
cg.SCREEN_HEIGHT = 480

-- cg.PlayerData(X) Defines
cg.HEALTH = 0
cg.MAX_HEALTH = 1
cg.ARMOR = 2
cg.FORCE = 3
cg.WEAPON = 4
cg.AMMO = 5
cg.SABERLEVEL = 6 -- saber level string (staff, akimbo, strong, medium, fast)
cg.NAME = 7
cg.LOCATIONTEXT = 8 -- location string
cg.SIEGECLASSTEXT = 9 -- base class name string
cg.TEAM = 10
cg.SPECSTATE = 11
cg.SIEGECLASS = 12 -- base class
cg.ORIGIN = 13
cg.ANGLES = 14
cg.SNAPNUMBER = 15 -- cg.snap->ps.clientNum
cg.LOCALNUMBER = 16 -- cg.clientNum (always local client and not following client number)

-- cg.DrawText style flags
cg.ITEM_TEXTSTYLE_NORMAL = 0
cg.ITEM_TEXTSTYLE_BLINK = 1
cg.ITEM_TEXTSTYLE_PULSE = 2
cg.ITEM_TEXTSTYLE_SHADOWED = 3
cg.ITEM_TEXTSTYLE_OUTLINED = 4
cg.ITEM_TEXTSTYLE_OUTLINESHADOWED = 5
cg.ITEM_TEXTSTYLE_SHADOWEDMORE = 6

-- cg.DrawText font flags
cg.FONT_SMALL = 1
cg.FONT_MEDIUM = 2
cg.FONT_LARGE = 3
cg.FONT_SMALL2 = 4

-- Config String Defines
cg.CS_SERVERINFO = 0
cg.CS_SYSTEMINFO = 1
cg.CS_MUSIC = 2
cg.CS_MESSAGE = 3
cg.CS_MOTD = 4
cg.CS_WARMUP = 5
cg.CS_SCORES1 = 6
cg.CS_SCORES2 = 7
cg.CS_VOTE_TIME = 8
cg.CS_VOTE_STRING = 9
cg.CS_VOTE_YES = 10
cg.CS_VOTE_NO = 11
cg.CS_TEAMVOTE_TIME = 12 -- unused with EM
cg.CS_TEAMVOTE_STRING = 14 -- unused with EM
cg.CS_TEAMVOTE_YES = 16 -- unused with EM
cg.CS_TEAMVOTE_NO = 18 -- unused with EM
cg.CS_GAME_VERSION = 20
cg.CS_LEVEL_START_TIME = 21
cg.CS_INTERMISSION = 22
cg.CS_FLAGSTATUS = 23
cg.CS_SHADERSTATE = 24
cg.CS_BOTINFO = 25 -- unused
cg.CS_ITEMS = 27
cg.CS_CLIENT_JEDIMASTER = 28
cg.CS_CLIENT_DUELWINNER = 29
cg.CS_CLIENT_DUELISTS = 30
cg.CS_CLIENT_DUELHEALTHS = 31
cg.CS_GLOBAL_AMBIENT_SET = 32
cg.CS_ENSIMODINFO = 34
cg.CS_AMBIENT_SET = 37
-- 37 through 292 are reserved for specific ambient sets
cg.CS_SIEGE_STATE = (cg.CS_AMBIENT_SET + cg.MAX_AMBIENT_SETS) --293
cg.CS_SIEGE_OBJECTIVES = (cg.CS_SIEGE_STATE + 1) --294
cg.CS_SIEGE_TIMEOVERRIDE = (cg.CS_SIEGE_OBJECTIVES + 1) --295
cg.CS_SIEGE_WINTEAM = (cg.CS_SIEGE_TIMEOVERRIDE + 1) --296
cg.CS_SIEGE_ICONS = (cg.CS_SIEGE_WINTEAM + 1) --297
cg.CS_MODELS = (cg.CS_SIEGE_ICONS + 1) --298
-- 298 through 809 are reserved for specific model data entries
cg.CS_SKYBOXORG = (cg.CS_MODELS + cg.MAX_MODELS) --810
cg.CS_SOUNDS = (cg.CS_SKYBOXORG + 1) --811
-- 811 through 1066 are reserved for specific sound data entries
cg.CS_ICONS = (cg.CS_SOUNDS + cg.MAX_SOUNDS) --1067
-- 1067 through 1130 are reserved for specific icon data entries
cg.CS_PLAYERS = (cg.CS_ICONS + cg.MAX_ICONS) --1131
-- 1131 through 1162 are reserved for player information
cg.CS_G2BONES = (cg.CS_PLAYERS + cg.MAX_CLIENTS) --1163
-- 1163 through 1226 are reserved for g2 bone information
cg.CS_LOCATIONS = (cg.CS_G2BONES + cg.MAX_G2BONES) --1227
-- 1227 through 1290 are reserved for location tags
cg.CS_PARTICLES = (cg.CS_LOCATIONS + cg.MAX_LOCATIONS) --1291
-- 1291 through 1334 are reserved for particles
cg.CS_EFFECTS = (cg.CS_PARTICLES + cg.MAX_LOCATIONS) --1335
-- 1335 through 1418 are reserved for effects data
cg.CS_LIGHT_STYLES = (cg.CS_EFFECTS + cg.MAX_FX) --1419
-- 1419 through 1610 are reserved for light-style data
cg.CS_TERRAINS = (cg.CS_LIGHT_STYLES + (cg.MAX_LIGHT_STYLES*3)) --1611
cg.CS_BSP_MODELS = (cg.CS_TERRAINS + cg.MAX_TERRAINS) --1612
-- 1612 through 1643 are reserved for bsp models
cg.CS_MAX = (cg.CS_BSP_MODELS + cg.MAX_SUB_BSP) --1644

-- TEAM_ Defines
cg.TEAM_FREE = 0
cg.TEAM_RED = 1
cg.TEAM_BLUE = 2
cg.TEAM_SPECTATOR = 3

-- Gametype Defines
cg.GT_FFA = 0
cg.GT_HOLOCRON = 1
cg.GT_JEDIMASTER = 2
cg.GT_DUEL = 3
cg.GT_POWERDUEL = 4
cg.GT_SINGLE_PLAYER = 5
cg.GT_TEAM = 6
cg.GT_SIEGE = 7
cg.GT_CTF = 8
cg.GT_CTY = 9

-- cg_ChatIntercept modes ("chat" -> 0, "tchat" -> 1)
cg.CHAT_DEFAULT = 0
cg.CHAT_TEAM = 1

-- JKA Engine File System Read Type Defines
cg.FS_READ = 0
cg.FS_WRITE = 1
cg.FS_APPEND = 2
cg.FS_APPEND_SYNC = 3

return 1

 

A special autoexec file will be called at the end of CG_Init and on CG_MapRestart to allow you to exec your configs when cgame has started instead of at UI load which wouldn't rly work so well. :roll: autoexec.lua is told to exec if it exists. So you would put something like:

 

local gametype = cg.Gametype()
if gametype == cg.GT_SIEGE then
cg.LuaExec("siege.lua")
else
cg.LuaExec("other.lua")
end

 

Added em_execSpawnScript CVar to determine whether or not to call spawn.lua on (re)spawn if it exists.

 

If anyone is interested in adding lua to their mod, whether it be client or server side feel free to ask here or send me a PM.

Link to comment
Share on other sites

Some more examples:

 

autoexec.lua:

if cg.Gametype() == cg.GT_CTF or cg.Gametype() == cg.GT_CTY then
 cg.LuaExec("ctf.lua")
elseif cg.Gametype() == cg.GT_SIEGE then
 cg.LuaExec("siege.lua")
else
 cg.LueExec("defaults.lua")
end

if cg.IsJAPlus() then -- If Server is JA+
 serverinfo = cg.GetConfigString(cg.CS_SERVERINFO) -- Put CS_SERVERINFO data in 'serverinfo'
 version = cg.Info_ValueForKey(serverinfo, "V") - Find "V" key and put it's data in version
 cg.Command(string.format("say \"Detected JA+ Server! Mod Version: %s\"\n", ver))
end

 

ctf.lua:

cg.Cvar_Set("cg_drawRadar", "0")
cg.LoadHud("ctfhud")

 

siege.lua:

cg.Cvar_Set("cg_drawRadar", "1")
cg.LoadHud("siegehud")

 

defaults.lua:

cg.Cvar_Set("cg_drawRadar", "0")
cg.LoadHud("ensiform")

 

bind c "lua_exec location.lua"

 

location.lua:

function SendLocation()
 cg.Command(string.format("say_team \"My Location is: %s^5!\"\n", cg.PlayerData(cg.LOCATION)
end

SendLocation()

 

spawn.lua:

function SayClass()
 if cg.Gametype() == cg.GT_SIEGE and cg.SiegeValid() == true then
   if cg.PlayerData(cg.TEAM) ~= cg.TEAM_SPECTATOR and cg.PlayerData(cg.SPECSTATE) == false then
     cg.Command(string.format("say_team \"Spawning as: %s...\"\n", cg.PlayerData(cg.SIEGECLASS)))
   end
 end
end

SayClass()

Link to comment
Share on other sites

Working on some cgame function wrappers that can be added to scripts to interpret your own commands, or close file descriptors, or add commands to auto completion for instance.

 

Ex:

 

-- return 0 to pass through to cgame
-- return 1 to interpret cmd here
-- cmd is command accepted from CG_ConsoleCommand via CG_Argv(0)
function cg_ConsoleCommand(cmd)
 if cmd == "mycmd" then
   --run functions, do work, etc
   return 1
 end
 return 0
end

 

function cg_DrawActiveFrame(serverTime, stereoView, demoPlayback)
cg.Print(string.format("cg_DrawActiveFrame: [%d] [%d] [%d]\n", serverTime, stereoView, demoPlayback))
end

 

-- clientNum is the clientNum passed from the vmCall to CG_Init
function cg_Init(clientNum)
 cg.Print(string.format("cg_Init: [%d]\n", clientNum))
end

 

function cg_ShutDown()
 -- close any file descriptors, do clean-up, etc.
end

Link to comment
Share on other sites

This should allow you to mimic the functionality of the JA+ client-side command to show real player IDs of clients:

 

cg.CS_SERVERINFO = 0
cg.CS_PLAYERS = 1131
cg.AddCommand("showPlayerID")

function showPlayerID()
svinfo = cg.GetConfigString(cg.CS_SERVERINFO)
sv_maxclients = tonumber(cg.Info_ValueForKey(svinfo, "sv_maxclients"))
cg.Print(" ID Name\n")
local count = 0
local n = 0
for n = 0, sv_maxclients-1 do
	info = cg.GetConfigString(cg.CS_PLAYERS + n)
	if info ~= "" then
		name = cg.Info_ValueForKey(info, "n")
		cg.Print(string.format(" %2i %s^7\n", n, name))
		count = count + 1;
	end
end
cg.Print(string.format("%2i totalplayers\n", count))
end

-- return 1 to intercept
-- return 0 to pass through to client module
function cg_ConsoleCommand(cmd)
if cmd == "showPlayerID" then
	showPlayerID()
	return 1
end
return 0
end

function cg_Shutdown()
cg.RemoveCommand("showPlayerID")
end

Link to comment
Share on other sites

  • 3 months later...

Because it is part of a mod that is only released to select few at the present time. :lol:

 

And the source code is unstable for the lua built in, that is why you dont get to see it.

 

Plus, building lua scripts itself doesn't require the mod. They don't need to be compiled lol.

 

If you really wanna see it, can talk to me in private.

Give details as to why you wish to use/see though.

I based mine off of the basic implementation of Xreal's server-side LUA code.

Link to comment
Share on other sites

  • 5 weeks later...

http://www.somedude.net/gamemonkey/

 

I mainly decided to use this because of these reasons:

- API code is somewhat generally smaller than LUA even though I put the entire base of cgconst.lua into the CGAME table directly into code.

- Multithreading support (natively)

- More like C/C++

- RTI Garbage Collecting

- Easy to bind C/C++ functions to call from script and call script from C/C++

- Runtime debugging and reflexion support.

- Good performance when comparing CPU Usage and Memory Usage. Speed is a trade-off though.

- Written in C++

- Has true class support unlike LUA which cheats and uses tables.

 

Example code from home page:

 

OnDoorTriggerEnter = function(door, objEntering)
{
 if(objEntering == player && !door.IsOpen())
 {
   door.Open();
   return true;
 }
 return false;
};

Link to comment
Share on other sites

"Hump the Noob" Function In LUA:

function HumpTheNoob()
cg.Command("taunt; wait 15\n")
local n = 0
for n = 0, 7 do
	cg.Command("+movedown;wait 15\n")
	cg.Command("-movedown;wait 15\n")
end
cg.Command("say \"^3You just got ^0<^1hump^0>^3'd!\"\n")
end

 

"Hump the Noob" Function in GM:

 

HumpTheNoob = function()
{
CGAME.Command("taunt");
sleep(0.015); // 15ms/1000
n = 0;
for (n = 0; n < 7; n++) {
	CGAME.Command("+movedown\n");
	sleep(0.015); // 15ms/1000
	CGAME.Command("-movedown\n");
	sleep(0.015); // 15ms/1000
}
CGAME.Command("say \"^3You just got ^0<^1hump^0>^3'd!\"\n");
};

HumpTheNoob Copyright © 2007 omg2ez.com

Link to comment
Share on other sites

  • 3 weeks later...

sounds cool

I implemented lua to the "server" part of quake3. So a little different than xreal it directly implements to "game". Since I want a qvm I cant implement to "game" (not easily).

I see you moved to game monkey. did you build dll to have lua in "cgame"?

Link to comment
Share on other sites

  • 4 weeks later...

Game Monkey Script Status Update:

 

- Now Uses PhysFS

- CG_ConsoleCommand is no longer intercepted

- Now has global Commands table that you set Commands to a function.

- Color Constants added to "COLOR" table.

- Garbage Collection is turned off during Init and when dispatch command is called if there is more than the cmd arg.

- Tweaked the other intercept functions a bit.

- Removed: CGAME.Argv, CGAME.Argc, and CGAME.ConcatArgs (No longer really needed).

 

The following functions are available in the "CGAME" table:

 

  • ChatmMsg
  • Time
  • SVTime
  • Milliseconds
  • Broadcast
  • SiegeValid
  • PlayerData
  • ForceData
  • ItemData
  • PowerupData
  • ClassData
  • TeamPlayers
  • CleanColor
  • LoadHud
  • AddCommand
  • RemoveCommand
  • LastAttacker
  • CrosshairPlayer
  • StrIStr
  • StrReplace
  • GetKeyCatcher
  • SetKeyCatcher
  • Cvar_Get
  • Cvar_Set
  • Cvar_Clear
  • Command
  • ReliableCommand
  • GetTranslatedString
  • GetConfigString
  • Gametype
  • ScoreboardActive
  • DemoPlayback
  • IsJedi
  • IsMerc
  • IsJedivsMerc
  • IsJediMaster
  • InstagibMode
  • MutantMode
  • IsMutant
  • IsBottomFeeder
  • Info_ValueForKey
  • IsEnsiMod
  • IsPublicBeta
  • IsJAPlus
  • EnsiModVer
  • DrawPic
  • RegisterShader
  • RemapShader
  • TextWidth
  • TextHeight
  • DrawText
  • GetPointContents
  • TraceLine

 

The following items are allowed to be set to functions in the "Events" table:

 

  • Init
  • Shutdown
  • Draw2D
  • RunFrame
  • CenterPrint
  • Chat
  • Respawn

 

Global Commands table works like so:

NOTE: The commands must actually come before you set them here (so put these at bottom of file).

 

Commands["csdump"] = CSDUMP;

 

CSDUMP looks like so:

global CSDUMP = function(csnum_str) {
if (csnum_str == null) {
	print("usage: csdump [csnum]");
	return;
}
csnum = ToInt(csnum_str.Int);
if (csnum < 0 || csnum >= MAX.CONFIGSTRINGS) {
	print("csdump: illegal csnum");
	return;
}
cs = CGAME.GetConfigString(csnum).String();
print(cs);
};

 

The parameter will be null if local player did not specify that arg.

 

Moved constants to separate tables based on what the constant is part of.

 

CGAME.MAX_* becomes MAX.*

CGAME.KEYCATCH_* becomes KEYCATCH.*

CGAME.SCREEN_* becomes SCREEN.*

CGAME.(PLAYERDATA ITEMS) becomes PD.*

CGAME.ITEM_TEXTSTYLE_* becomes TEXT.*

CGAME.FONT_* becomes FONT.*

CGAME.CS_* becomes CS.*

CGAME.TEAM_* becomes TEAM.*

CGAME.GT_* becomes GAME.*

CGAME.CHAT_* becomes CHAT.*

Added WEAPON.*, AMMO.*, FORCE.*

Added COLOR.* (for colorTable in CGAME ie drawing text, etc).

Link to comment
Share on other sites

  • 4 months later...

I don't know if it's needed with the GameMonkey script, but how would Python compare to Lua for embedding in JKA? I only ask cause I know it a bit, unlike Lua.

 

On the other hand has anyone tried taking the Icarus guts out of the Star Trek game SP SDK and completing JKA MP with it?

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...