LucasForums

LucasForums (http://www.lucasforums.com/index.php)
-   JA Coding (http://www.lucasforums.com/forumdisplay.php?f=539)
-   -   Lua Scripting For The Client Side (http://www.lucasforums.com/showthread.php?t=175443)

ensiform 02-08-2007 11:05 AM

Lua Scripting For The Client Side
 
The following commands are available to you with lua scripts:

Code:

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:
Code:

-- 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:

Code:

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.

ensiform 02-08-2007 11:48 AM

Some more examples:

autoexec.lua:
Code:

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:
Code:

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

siege.lua:
Code:

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

defaults.lua:
Code:

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

Code:

bind c "lua_exec location.lua"
location.lua:
Code:

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

SendLocation()

spawn.lua:
Code:

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()


Tinny 02-08-2007 02:40 PM

Woah, nice job there man.

stubert 02-09-2007 01:07 AM

GHF

this will be merged into ojp asap i assume

ensiform 02-09-2007 11:17 AM

Not likely :s

ensiform 02-09-2007 12:34 PM

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:

Code:

-- 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

Code:

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

Code:

-- 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

Code:

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


ensiform 02-11-2007 02:37 AM

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

Code:

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


razorace 02-13-2007 02:03 PM

Quote:

Originally Posted by stubert
GHF

this will be merged into ojp asap i assume

I suppose we could go for it if that's what the majority of the OJP developers want.

Tinny 02-13-2007 07:44 PM

Hey Razor, long time no see man. I always thought Lua to be superior to Icarus and that atleast the server side of lua editing would greatly benefit developers.

ensiform 02-14-2007 07:38 PM

Well, it wont get that far yet.

You have to figure out how to have tasks, figure out wait(time), waitforsignal(...) etc.

f0rqu3 05-23-2007 08:30 AM

is the source code available

ensiform 05-23-2007 04:15 PM

<ensiform: 2. Negative>

f0rqu3 05-23-2007 04:51 PM

eh what is the point then
"The following commands are available to you with lua scripts:"
definitely they are not available to me :P

ensiform 05-23-2007 04:54 PM

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.

f0rqu3 05-23-2007 05:16 PM

:D thanks I am searhing thru xreal now
btw what is the name of the mod

ensiform 06-22-2007 05:34 PM

My Mod? Is EnsiMod, formerly Red Slushie.

And FYI for all here, I'm converting to Game Monkey instead.

Griswald 06-22-2007 08:28 PM

What's Game Monkey? O.o

ensiform 06-23-2007 12:05 AM

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:

Code:

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


ensiform 06-23-2007 12:14 AM

"Hump the Noob" Function In LUA:
Code:

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:

Code:

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 (c) 2007 omg2ez.com

f0rqu3 07-14-2007 08:51 PM

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"?

ensiform 07-15-2007 12:17 AM

Well I added all the needed files to my cgame vcproj. For LUA and GM.

ensiform 08-06-2007 09:07 PM

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).

Code:

Commands["csdump"] = CSDUMP;
CSDUMP looks like so:
Code:

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).

dnifan 12-17-2007 02:42 PM

You know what's funny? :P

Our mod, JKALUA, is implementing Lua in 'game', so server-side. :P

ensiform 12-18-2007 11:12 AM

I've done that already too, to replace ICARUS in the past. LUA is just not as functional as I want it to be.

Xandy 12-18-2007 03:31 PM

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?

ensiform 12-19-2007 11:28 PM

Python would be a lot more work. Though, for true, full, and very robust GM support it can also be a pain, especially those with low experience and no C++ knowledge.

To even initialize the GM stuff I call this entire block:

Code:

        void CG_InitGM(void) {
                CG_Printf("------- Initializing Game Monkey Script Engine -------\n");
                // Set machine callbacks
                m_scriptEngine = new gmMachine;
                m_scriptEngine->SetDebugMode(true);
                gmMachine::s_printCallback = gmPrintf;
                gmMachine::s_machineCallback = ScriptMachineCallback;

                gmGCRootManager::Init();

                m_scriptEngine->EnableGC(false);

                const int MEM_USAGE_MB = 2 * 1048576;
                const int MEM_USAGE_KB = 0 * 1024;
                const int HARD_MEM_USAGE = MEM_USAGE_MB + MEM_USAGE_KB;
                const int SOFT_MEM_USAGE = HARD_MEM_USAGE * 9 / 10;
                m_scriptEngine->SetDesiredByteMemoryUsageHard(HARD_MEM_USAGE);
                m_scriptEngine->SetDesiredByteMemoryUsageSoft(SOFT_MEM_USAGE);

                //////////////////////////////////////////////////////////////////////////
                CG_Printf("Hard Memory Limit: %s\n", Utils::FormatByteString(HARD_MEM_USAGE).c_str());
                CG_Printf("Soft Memory Limit: %s\n", Utils::FormatByteString(SOFT_MEM_USAGE).c_str());

                lastUpdateTime = cg.time;

                // Allocate some permanent strings for properties that will be used alot.
                g_CommandTableString = m_scriptEngine->AllocPermanantStringObject("Commands");
                g_ICCTableString = m_scriptEngine->AllocPermanantStringObject("ICC");
                g_ColorTableString = m_scriptEngine->AllocPermanantStringObject("COLOR");
                g_EventsTableString = m_scriptEngine->AllocPermanantStringObject("Events");

                // Bind libraries.
                gmBindMathLibrary(m_scriptEngine);
                gmBindVectorLib(m_scriptEngine);
                gmBindStringLib(m_scriptEngine);

                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, gmVariable(g_CommandTableString), gmVariable(m_scriptEngine->AllocTableObject()));
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, gmVariable(g_ICCTableString), gmVariable(m_scriptEngine->AllocTableObject()));
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, gmVariable(g_ColorTableString), gmVariable(m_scriptEngine->AllocTableObject()));
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, gmVariable(g_EventsTableString), gmVariable(m_scriptEngine->AllocTableObject()));

                // Add the color constants to the global table.
                gmTableObject *colorTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, gmVariable(g_ColorTableString), gmVariable(colorTable));
                colorTable->Set(m_scriptEngine, "NONE", gmVariable(CT_NONE));
                colorTable->Set(m_scriptEngine, "BLACK", gmVariable(CT_BLACK));
                colorTable->Set(m_scriptEngine, "RED", gmVariable(CT_RED));
                colorTable->Set(m_scriptEngine, "GREEN", gmVariable(CT_GREEN));
                colorTable->Set(m_scriptEngine, "BLUE", gmVariable(CT_BLUE));
                colorTable->Set(m_scriptEngine, "YELLOW", gmVariable(CT_YELLOW));
                colorTable->Set(m_scriptEngine, "MAGENTA", gmVariable(CT_MAGENTA));
                colorTable->Set(m_scriptEngine, "CYAN", gmVariable(CT_CYAN));
                colorTable->Set(m_scriptEngine, "WHITE", gmVariable(CT_WHITE));
                colorTable->Set(m_scriptEngine, "LTGREY", gmVariable(CT_LTGREY));
                colorTable->Set(m_scriptEngine, "MDGREY", gmVariable(CT_MDGREY));
                colorTable->Set(m_scriptEngine, "DKGREY", gmVariable(CT_DKGREY));
                colorTable->Set(m_scriptEngine, "DKGREY2", gmVariable(CT_DKGREY2));
                colorTable->Set(m_scriptEngine, "VLTORANGE", gmVariable(CT_VLTORANGE));
                colorTable->Set(m_scriptEngine, "LTORANGE", gmVariable(CT_LTORANGE));
                colorTable->Set(m_scriptEngine, "DKORANGE", gmVariable(CT_DKORANGE));
                colorTable->Set(m_scriptEngine, "VDKORANGE", gmVariable(CT_VDKORANGE));
                colorTable->Set(m_scriptEngine, "VLTBLUE1", gmVariable(CT_VLTBLUE1));
                colorTable->Set(m_scriptEngine, "LTBLUE1", gmVariable(18));
                colorTable->Set(m_scriptEngine, "DKBLUE1", gmVariable(19));
                colorTable->Set(m_scriptEngine, "VDKBLUE1", gmVariable(CT_VDKBLUE1));
                colorTable->Set(m_scriptEngine, "VLTBLUE2", gmVariable(CT_VLTBLUE2));
                colorTable->Set(m_scriptEngine, "LTBLUE2", gmVariable(CT_LTBLUE2));
                colorTable->Set(m_scriptEngine, "DKBLUE2", gmVariable(CT_DKBLUE2));
                colorTable->Set(m_scriptEngine, "VDKBLUE2", gmVariable(CT_VDKBLUE2));
                colorTable->Set(m_scriptEngine, "VLTBROWN", gmVariable(CT_VLTBROWN1));
                colorTable->Set(m_scriptEngine, "LTBROWN", gmVariable(CT_LTBROWN1));
                colorTable->Set(m_scriptEngine, "DKBROWN", gmVariable(CT_DKBROWN1));
                colorTable->Set(m_scriptEngine, "VDKBROWN", gmVariable(CT_VDKBROWN1));
                colorTable->Set(m_scriptEngine, "VLTGOLD", gmVariable(CT_VLTGOLD1));
                colorTable->Set(m_scriptEngine, "LTGOLD", gmVariable(CT_LTGOLD1));
                colorTable->Set(m_scriptEngine, "DKGOLD", gmVariable(CT_DKGOLD1));
                colorTable->Set(m_scriptEngine, "VDKGOLD", gmVariable(CT_VDKGOLD1));
                colorTable->Set(m_scriptEngine, "VLTPURPLE1", gmVariable(CT_VLTPURPLE1));
                colorTable->Set(m_scriptEngine, "LTPURPLE1", gmVariable(CT_LTPURPLE1));
                colorTable->Set(m_scriptEngine, "DKPURPLE1", gmVariable(CT_DKPURPLE1));
                colorTable->Set(m_scriptEngine, "VDKPURPLE1", gmVariable(CT_VDKPURPLE1));
                colorTable->Set(m_scriptEngine, "VLTPURPLE2", gmVariable(CT_VLTPURPLE2));
                colorTable->Set(m_scriptEngine, "LTPURPLE2", gmVariable(CT_LTPURPLE2));
                colorTable->Set(m_scriptEngine, "DKPURPLE2", gmVariable(CT_DKPURPLE2));
                colorTable->Set(m_scriptEngine, "VDKPURPLE2", gmVariable(CT_VDKPURPLE2));
                colorTable->Set(m_scriptEngine, "VLTPURPLE3", gmVariable(CT_VLTPURPLE3));
                colorTable->Set(m_scriptEngine, "LTPURPLE3", gmVariable(CT_LTPURPLE3));
                colorTable->Set(m_scriptEngine, "DKPURPLE3", gmVariable(CT_DKPURPLE3));
                colorTable->Set(m_scriptEngine, "VDKPURPLE3", gmVariable(CT_VDKPURPLE3));
                colorTable->Set(m_scriptEngine, "VLTRED1", gmVariable(CT_VLTRED1));
                colorTable->Set(m_scriptEngine, "LTRED1", gmVariable(CT_LTRED1));
                colorTable->Set(m_scriptEngine, "DKRED1", gmVariable(CT_DKRED1));
                colorTable->Set(m_scriptEngine, "VDKRED1", gmVariable(CT_VDKRED1));
                colorTable->Set(m_scriptEngine, "VDKRED", gmVariable(CT_VDKRED));
                colorTable->Set(m_scriptEngine, "DKRED", gmVariable(CT_DKRED));
                colorTable->Set(m_scriptEngine, "VLTAQUA", gmVariable(CT_VLTAQUA));
                colorTable->Set(m_scriptEngine, "LTAQUA", gmVariable(CT_LTAQUA));
                colorTable->Set(m_scriptEngine, "DKAQUA", gmVariable(CT_DKAQUA));
                colorTable->Set(m_scriptEngine, "VDKAQUA", gmVariable(CT_VDKAQUA));
                colorTable->Set(m_scriptEngine, "LTPINK", gmVariable(CT_LTPINK));
                colorTable->Set(m_scriptEngine, "DKPINK", gmVariable(CT_DKPINK));
                colorTable->Set(m_scriptEngine, "LTCYAN", gmVariable(57));
                colorTable->Set(m_scriptEngine, "DKCYAN", gmVariable(58));
                colorTable->Set(m_scriptEngine, "LTBLUE3", gmVariable(CT_LTBLUE3));
                colorTable->Set(m_scriptEngine, "BLUE3", gmVariable(CT_BLUE3));
                colorTable->Set(m_scriptEngine, "DKBLUE3", gmVariable(CT_DKBLUE3));
                colorTable->Set(m_scriptEngine, "HUD_GREEN", gmVariable(CT_HUD_GREEN));
                colorTable->Set(m_scriptEngine, "HUD_RED", gmVariable(CT_HUD_RED));
                colorTable->Set(m_scriptEngine, "ICON_BLUE", gmVariable(CT_ICON_BLUE));
                colorTable->Set(m_scriptEngine, "NO_AMMO_RED", gmVariable(CT_NO_AMMO_RED));
                colorTable->Set(m_scriptEngine, "HUD_ORANGE", gmVariable(CT_HUD_ORANGE));

                gmTableObject *pMaxTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "MAX", gmVariable(pMaxTable));
                pMaxTable->Set(m_scriptEngine, "CLIENTS", gmVariable(MAX_CLIENTS));
                pMaxTable->Set(m_scriptEngine, "TERRAINS", gmVariable(MAX_TERRAINS));
                pMaxTable->Set(m_scriptEngine, "LOCATIONS", gmVariable(MAX_LOCATIONS));
                pMaxTable->Set(m_scriptEngine, "MODELS", gmVariable(MAX_MODELS));
                pMaxTable->Set(m_scriptEngine, "SOUNDS", gmVariable(MAX_SOUNDS));
                pMaxTable->Set(m_scriptEngine, "ICONS", gmVariable(MAX_ICONS));
                pMaxTable->Set(m_scriptEngine, "FX", gmVariable(MAX_FX));
                pMaxTable->Set(m_scriptEngine, "G2BONES", gmVariable(MAX_G2BONES));
                pMaxTable->Set(m_scriptEngine, "SUB_BSP", gmVariable(MAX_SUB_BSP));
                pMaxTable->Set(m_scriptEngine, "AMBIENT_SETS", gmVariable(MAX_AMBIENT_SETS));
                pMaxTable->Set(m_scriptEngine, "LIGHT_STYLES", gmVariable(MAX_LIGHT_STYLES));
                pMaxTable->Set(m_scriptEngine, "CONFIGSTRINGS", gmVariable(MAX_CONFIGSTRINGS));

                gmTableObject *pKeyTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "KEYCATCH", gmVariable(pKeyTable));
                pKeyTable->Set(m_scriptEngine, "CONSOLE", gmVariable(KEYCATCH_CONSOLE));
                pKeyTable->Set(m_scriptEngine, "UI", gmVariable(KEYCATCH_UI));
                pKeyTable->Set(m_scriptEngine, "MESSAGE", gmVariable(KEYCATCH_MESSAGE));
                pKeyTable->Set(m_scriptEngine, "CGAME", gmVariable(KEYCATCH_CGAME));

                gmTableObject *pScreenTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "SCREEN", gmVariable(pScreenTable));
                pScreenTable->Set(m_scriptEngine, "WIDTH", gmVariable(SCREEN_WIDTH));
                pScreenTable->Set(m_scriptEngine, "HEIGHT", gmVariable(SCREEN_HEIGHT));

                gmTableObject *pDataTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "PD", gmVariable(pDataTable));
                pDataTable->Set(m_scriptEngine, "HEALTH", gmVariable(PD_HEALTH));
                pDataTable->Set(m_scriptEngine, "MAX_HEALTH", gmVariable(PD_MAX_HEALTH));
                pDataTable->Set(m_scriptEngine, "ARMOR", gmVariable(PD_ARMOR));
                pDataTable->Set(m_scriptEngine, "FORCE", gmVariable(PD_FORCE));
                pDataTable->Set(m_scriptEngine, "WEAPON", gmVariable(PD_WEAPON));
                pDataTable->Set(m_scriptEngine, "AMMO", gmVariable(PD_AMMO));
                pDataTable->Set(m_scriptEngine, "SABERTEXT", gmVariable(PD_SABERTEXT));
                pDataTable->Set(m_scriptEngine, "NAME", gmVariable(PD_NAME));
                pDataTable->Set(m_scriptEngine, "LOCATIONTEXT", gmVariable(PD_LOCATIONTEXT));
                pDataTable->Set(m_scriptEngine, "SIEGECLASSTEXT", gmVariable(PD_SIEGECLASSTEXT));
                pDataTable->Set(m_scriptEngine, "TEAM", gmVariable(PD_TEAM));
                pDataTable->Set(m_scriptEngine, "SPECSTATE", gmVariable(PD_SPECSTATE));
                pDataTable->Set(m_scriptEngine, "SIEGECLASS", gmVariable(PD_SIEGECLASS));
                pDataTable->Set(m_scriptEngine, "ORIGIN", gmVariable(PD_ORIGIN));
                pDataTable->Set(m_scriptEngine, "ANGLES", gmVariable(PD_ANGLES));
                pDataTable->Set(m_scriptEngine, "SNAPNUMBER", gmVariable(PD_SNAPNUMBER));
                pDataTable->Set(m_scriptEngine, "LOCALNUMBER", gmVariable(PD_LOCALNUMBER));

                gmTableObject *pTextTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "TEXT", gmVariable(pTextTable));
                pTextTable->Set(m_scriptEngine, "NORMAL", gmVariable(ITEM_TEXTSTYLE_NORMAL));
                pTextTable->Set(m_scriptEngine, "BLINK", gmVariable(ITEM_TEXTSTYLE_BLINK));
                pTextTable->Set(m_scriptEngine, "PULSE", gmVariable(ITEM_TEXTSTYLE_PULSE));
                pTextTable->Set(m_scriptEngine, "SHADOWED", gmVariable(ITEM_TEXTSTYLE_SHADOWED));
                pTextTable->Set(m_scriptEngine, "OUTLINED", gmVariable(ITEM_TEXTSTYLE_OUTLINED));
                pTextTable->Set(m_scriptEngine, "OUTLINESHADOWED", gmVariable(ITEM_TEXTSTYLE_OUTLINESHADOWED));
                pTextTable->Set(m_scriptEngine, "SHADOWEDMORE", gmVariable(ITEM_TEXTSTYLE_SHADOWEDMORE));

                gmTableObject *pFontTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "FONT", gmVariable(pFontTable));
                pFontTable->Set(m_scriptEngine, "SMALL", gmVariable(FONT_SMALL));
                pFontTable->Set(m_scriptEngine, "MEDIUM", gmVariable(FONT_MEDIUM));
                pFontTable->Set(m_scriptEngine, "LARGE", gmVariable(FONT_LARGE));
                pFontTable->Set(m_scriptEngine, "SMALL2", gmVariable(FONT_SMALL2));

                gmTableObject *pCSTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "CS", gmVariable(pCSTable));
                pCSTable->Set(m_scriptEngine, "SERVERINFO", gmVariable(CS_SERVERINFO));
                pCSTable->Set(m_scriptEngine, "SYSTEMINFO", gmVariable(CS_SYSTEMINFO));
                pCSTable->Set(m_scriptEngine, "MUSIC", gmVariable(CS_MUSIC));
                pCSTable->Set(m_scriptEngine, "MESSAGE", gmVariable(CS_MESSAGE));
                pCSTable->Set(m_scriptEngine, "MOTD", gmVariable(CS_MOTD));
                pCSTable->Set(m_scriptEngine, "WARMUP", gmVariable(CS_WARMUP));
                pCSTable->Set(m_scriptEngine, "SCORES1", gmVariable(CS_SCORES1));
                pCSTable->Set(m_scriptEngine, "SCORES2", gmVariable(CS_SCORES2));
                pCSTable->Set(m_scriptEngine, "VOTE_TIME", gmVariable(CS_VOTE_TIME));
                pCSTable->Set(m_scriptEngine, "VOTE_STRING", gmVariable(CS_VOTE_STRING));
                pCSTable->Set(m_scriptEngine, "VOTE_YES", gmVariable(CS_VOTE_YES));
                pCSTable->Set(m_scriptEngine, "VOTE_NO", gmVariable(CS_VOTE_NO));
                pCSTable->Set(m_scriptEngine, "TEAMVOTE_TIME", gmVariable(CS_TEAMVOTE_TIME));
                pCSTable->Set(m_scriptEngine, "TEAMVOTE_STRING", gmVariable(CS_TEAMVOTE_STRING));
                pCSTable->Set(m_scriptEngine, "TEAMVOTE_YES", gmVariable(CS_TEAMVOTE_YES));
                pCSTable->Set(m_scriptEngine, "TEAMVOTE_NO", gmVariable(CS_TEAMVOTE_NO));
                pCSTable->Set(m_scriptEngine, "GAME_VERSION", gmVariable(CS_GAME_VERSION));
                pCSTable->Set(m_scriptEngine, "LEVEL_START_TIME", gmVariable(CS_LEVEL_START_TIME));
                pCSTable->Set(m_scriptEngine, "INTERMISSION", gmVariable(CS_INTERMISSION));
                pCSTable->Set(m_scriptEngine, "FLAGSTATUS", gmVariable(CS_FLAGSTATUS));
                pCSTable->Set(m_scriptEngine, "SHADERSTATE", gmVariable(CS_SHADERSTATE));
                pCSTable->Set(m_scriptEngine, "BOTINFO", gmVariable(CS_BOTINFO));
                pCSTable->Set(m_scriptEngine, "CLIENT_JEDIMASTER", gmVariable(CS_CLIENT_JEDIMASTER));
                pCSTable->Set(m_scriptEngine, "CLIENT_DUELWINNER", gmVariable(CS_CLIENT_DUELWINNER));
                pCSTable->Set(m_scriptEngine, "CLIENT_DUELISTS", gmVariable(CS_CLIENT_DUELISTS));
                pCSTable->Set(m_scriptEngine, "CLIENT_DUELHEALTHS", gmVariable(CS_CLIENT_DUELHEALTHS));
                pCSTable->Set(m_scriptEngine, "GLOBAL_AMBIENT_SET", gmVariable(CS_GLOBAL_AMBIENT_SET));
                pCSTable->Set(m_scriptEngine, "ENSIMODINFO", gmVariable(CS_ENSIMODINFO));
                pCSTable->Set(m_scriptEngine, "MUTANT", gmVariable(CS_MUTANT));
                pCSTable->Set(m_scriptEngine, "SVCV", gmVariable(CS_SVCV));
                pCSTable->Set(m_scriptEngine, "AMBIENT_SET", gmVariable(CS_AMBIENT_SET));
                pCSTable->Set(m_scriptEngine, "SIEGE_STATE", gmVariable(CS_SIEGE_STATE));
                pCSTable->Set(m_scriptEngine, "SIEGE_OBJECTIVES", gmVariable(CS_SIEGE_OBJECTIVES));
                pCSTable->Set(m_scriptEngine, "SIEGE_TIMEOVERRIDE", gmVariable(CS_SIEGE_TIMEOVERRIDE));
                pCSTable->Set(m_scriptEngine, "SIEGE_WINTEAM", gmVariable(CS_SIEGE_WINTEAM));
                pCSTable->Set(m_scriptEngine, "SIEGE_ICONS", gmVariable(CS_SIEGE_ICONS));
                pCSTable->Set(m_scriptEngine, "MODELS", gmVariable(CS_MODELS));
                pCSTable->Set(m_scriptEngine, "SKYBOXORG", gmVariable(CS_SKYBOXORG));
                pCSTable->Set(m_scriptEngine, "ICONS", gmVariable(CS_ICONS));
                pCSTable->Set(m_scriptEngine, "PLAYERS", gmVariable(CS_PLAYERS));
                pCSTable->Set(m_scriptEngine, "G2BONES", gmVariable(CS_G2BONES));
                pCSTable->Set(m_scriptEngine, "LOCATIONS", gmVariable(CS_LOCATIONS));
                pCSTable->Set(m_scriptEngine, "PARTICLES", gmVariable(CS_PARTICLES));
                pCSTable->Set(m_scriptEngine, "EFFECTS", gmVariable(CS_EFFECTS));
                pCSTable->Set(m_scriptEngine, "LIGHT_STYLES", gmVariable(CS_LIGHT_STYLES));
                pCSTable->Set(m_scriptEngine, "TERRAINS", gmVariable(CS_TERRAINS));
                pCSTable->Set(m_scriptEngine, "BSP_MODELS", gmVariable(CS_BSP_MODELS));
                pCSTable->Set(m_scriptEngine, "MAX", gmVariable(CS_MAX));

                gmTableObject *pTeamTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "TEAM", gmVariable(pTeamTable));
                pTeamTable->Set(m_scriptEngine, "FREE", gmVariable(TEAM_FREE));
                pTeamTable->Set(m_scriptEngine, "RED", gmVariable(TEAM_RED));
                pTeamTable->Set(m_scriptEngine, "BLUE", gmVariable(TEAM_BLUE));
                pTeamTable->Set(m_scriptEngine, "SPECTATOR", gmVariable(TEAM_SPECTATOR));

                gmTableObject *pGameTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "GAME", gmVariable(pGameTable));
                pGameTable->Set(m_scriptEngine, "FFA", gmVariable(GT_FFA));
                pGameTable->Set(m_scriptEngine, "HOLOCRON", gmVariable(GT_HOLOCRON));
                pGameTable->Set(m_scriptEngine, "JEDIMASTER", gmVariable(GT_JEDIMASTER));
                pGameTable->Set(m_scriptEngine, "DUEL", gmVariable(GT_DUEL));
                pGameTable->Set(m_scriptEngine, "POWERDUEL", gmVariable(GT_POWERDUEL));
                pGameTable->Set(m_scriptEngine, "SINGLE_PLAYER", gmVariable(GT_SINGLE_PLAYER));
                pGameTable->Set(m_scriptEngine, "TEAM", gmVariable(GT_TEAM));
                pGameTable->Set(m_scriptEngine, "SIEGE", gmVariable(GT_SIEGE));
                pGameTable->Set(m_scriptEngine, "CTF", gmVariable(GT_CTF));
                pGameTable->Set(m_scriptEngine, "CTY", gmVariable(GT_CTY));

                gmTableObject *pChatTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "CHAT", gmVariable(pChatTable));
                pChatTable->Set(m_scriptEngine, "DEFAULT", gmVariable(SAY_ALL));
                pChatTable->Set(m_scriptEngine, "TEAM", gmVariable(SAY_TEAM));

                gmTableObject *pWeaponTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "WEAPON", gmVariable(pWeaponTable));
                pWeaponTable->Set(m_scriptEngine, "NONE", gmVariable(WP_NONE));
                pWeaponTable->Set(m_scriptEngine, "STUN", gmVariable(WP_STUN_BATON));
                pWeaponTable->Set(m_scriptEngine, "MELEE", gmVariable(WP_MELEE));
                pWeaponTable->Set(m_scriptEngine, "SABER", gmVariable(WP_SABER));
                pWeaponTable->Set(m_scriptEngine, "PISTOL", gmVariable(WP_BRYAR_PISTOL));
                pWeaponTable->Set(m_scriptEngine, "BLASTER", gmVariable(WP_BLASTER));
                pWeaponTable->Set(m_scriptEngine, "DISRUPTOR", gmVariable(WP_DISRUPTOR));
                pWeaponTable->Set(m_scriptEngine, "BOWCASTER", gmVariable(WP_BOWCASTER));
                pWeaponTable->Set(m_scriptEngine, "REPEATER", gmVariable(WP_REPEATER));
                pWeaponTable->Set(m_scriptEngine, "DEMP2", gmVariable(WP_DEMP2));
                pWeaponTable->Set(m_scriptEngine, "FLECHETTE", gmVariable(WP_FLECHETTE));
                pWeaponTable->Set(m_scriptEngine, "ROCKET_LAUNCHER", gmVariable(WP_ROCKET_LAUNCHER));
                pWeaponTable->Set(m_scriptEngine, "THERMAL", gmVariable(WP_THERMAL));
                pWeaponTable->Set(m_scriptEngine, "TRIP_MINE", gmVariable(WP_TRIP_MINE));
                pWeaponTable->Set(m_scriptEngine, "DET_PACK", gmVariable(WP_DET_PACK));
                pWeaponTable->Set(m_scriptEngine, "CONCUSSION", gmVariable(WP_CONCUSSION));
                pWeaponTable->Set(m_scriptEngine, "OLDPISTOL", gmVariable(WP_BRYAR_OLD));
                pWeaponTable->Set(m_scriptEngine, "EMPLACED", gmVariable(WP_EMPLACED_GUN));
                pWeaponTable->Set(m_scriptEngine, "TURRET", gmVariable(WP_TURRET));

                gmTableObject *pAmmoTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "AMMO", gmVariable(pAmmoTable));
                pAmmoTable->Set(m_scriptEngine, "NONE", gmVariable(AMMO_NONE));
                pAmmoTable->Set(m_scriptEngine, "BLASTER", gmVariable(AMMO_BLASTER));
                pAmmoTable->Set(m_scriptEngine, "POWERCELL", gmVariable(AMMO_POWERCELL));
                pAmmoTable->Set(m_scriptEngine, "METALBOLTS", gmVariable(AMMO_METAL_BOLTS));
                pAmmoTable->Set(m_scriptEngine, "ROCKETS", gmVariable(AMMO_ROCKETS));
                pAmmoTable->Set(m_scriptEngine, "THERMAL", gmVariable(AMMO_THERMAL));
                pAmmoTable->Set(m_scriptEngine, "TRIPMINE", gmVariable(AMMO_TRIPMINE));
                pAmmoTable->Set(m_scriptEngine, "DETPACK", gmVariable(AMMO_DETPACK));

                gmTableObject *pForceTable = m_scriptEngine->AllocTableObject();
                m_scriptEngine->GetGlobals()->Set(m_scriptEngine, "FORCE", gmVariable(pForceTable));
                pForceTable->Set(m_scriptEngine, "HEAL", gmVariable(FP_HEAL));
                pForceTable->Set(m_scriptEngine, "JUMP", gmVariable(FP_LEVITATION));
                pForceTable->Set(m_scriptEngine, "SPEED", gmVariable(FP_SPEED));
                pForceTable->Set(m_scriptEngine, "PUSH", gmVariable(FP_PUSH));
                pForceTable->Set(m_scriptEngine, "PULL", gmVariable(FP_PULL));
                pForceTable->Set(m_scriptEngine, "MINDTRICK", gmVariable(FP_TELEPATHY));
                pForceTable->Set(m_scriptEngine, "GRIP", gmVariable(FP_GRIP));
                pForceTable->Set(m_scriptEngine, "LIGHTNING", gmVariable(FP_LIGHTNING));
                pForceTable->Set(m_scriptEngine, "RAGE", gmVariable(FP_RAGE));
                pForceTable->Set(m_scriptEngine, "PROTECT", gmVariable(FP_PROTECT));
                pForceTable->Set(m_scriptEngine, "ABSORB", gmVariable(FP_ABSORB));
                pForceTable->Set(m_scriptEngine, "TEAM_HEAL", gmVariable(FP_TEAM_HEAL));
                pForceTable->Set(m_scriptEngine, "TEAM_ENERGIZE", gmVariable(FP_TEAM_FORCE));
                pForceTable->Set(m_scriptEngine, "DRAIN", gmVariable(FP_DRAIN));
                pForceTable->Set(m_scriptEngine, "SEE", gmVariable(FP_SEE));
                pForceTable->Set(m_scriptEngine, "SABER_OFFENSE", gmVariable(FP_SABER_OFFENSE));
                pForceTable->Set(m_scriptEngine, "SABER_DEFENSE", gmVariable(FP_SABER_DEFENSE));
                pForceTable->Set(m_scriptEngine, "SABER_THROW", gmVariable(FP_SABERTHROW));

                gmBindCGameLib(m_scriptEngine);
                m_scriptEngine->EnableGC(true);
                CG_Printf("------------------------------------------------------\n");
        }

And to load a script:

Code:

        void CG_LoadGMScript(const char *fileName) {
                GM_ASSERT(m_scriptEngine);
                if(!m_scriptEngine)
                        return;
                PHYSFS_File *file;
               
                CG_Printf("...loading '%s'\n", fileName);

                file = PFS_openRead(MODPATH_FS_GAME, fileName);
                if(!file) {
                        CG_Printf(S_COLOR_RED "file not found: %s\n", fileName);
                        return;
                }
               
                int len = PFS_fileLength(file);
                boost::shared_array<char> pScript(new char[len+1]);
                PFS_read(file, pScript.get(), len);
                pScript[len] = 0;
                PFS_close(file);

                int errors = m_scriptEngine->ExecuteString(pScript.get(), GM_INVALID_THREAD, false, fileName);
                if(errors) {
                        gmLogAnyErrorMsgs(m_scriptEngine);
                }
        }


Xandy 12-20-2007 12:18 AM

Thanks for that code.

razorace 12-20-2007 02:48 PM

Quote:

Originally Posted by Xandy
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?

We already have access to the SP code for most of the ICARUS scripting and have translated a lot of it as part of OJP.

Tinny 12-20-2007 04:23 PM

I just wish the map specific animations and other sp map entities would work :(.

ensiform 12-23-2007 02:24 AM

Quote:

Originally Posted by dnifan
You know what's funny? :P

Our mod, JKALUA, is implementing Lua in 'game', so server-side. :P

FYI, I've seen better server side implementations of LUA in my sleep. :(

And, making it need the extra dll is no something you'd want to do.

ensiform 01-10-2008 04:27 AM

I've actually been pondering just recently a better way to implement an alternate scripting for server-side all together (LUA, GM, Squirrel, or w/e you want).

But you'd want to consider the following:

Replace ICARUS ****.
Allow for server manipulation type stuff (that can be see in like ETPro, and other various games/mods)
As you can see, ICARUS is using a separate file for each script which is kind of messy and you would want to limit map scripts to just 1 script and do everything in that file.

For instance:

If you have some entity that has many scripts attached to it, instead of each file per "behavior set" you'd just have events set up as such:

GM could be like so:

Code:

some code above...

//note this. inside these functions would be accessing myEnt (I think) Might be events but not positive.

myEnt = FunctionToRetrieveEntity(params?);
myEnt.Events[EVENT.SPAWN] = function(SpawnTime) {
        //do some actions upon myEnt spawning
};

myEnt.Events[EVENT.USE] = function(UseEnt) {
        //do some actions when myEnt has been used
};

myEnt.Events[EVENT.AWAKE] = function(params?) {
        //do some actions when myEnt has awoken or been startled
};

myEnt.Events[EVENT.ANGER] = function(Enemy) {
        //do some actions when myEnt has found an enemy
};

myEnt.Events[EVENT.VICTORY] = function(Victim, MeansOfDeath) {
        //do some actions when myEnt has killed someone or something
};

myEnt.Events[EVENT.LOSTENEMY] = function(LastEnemy) {
        //do some actions when myEnt has lost its enemy
};

myEnt.Events[EVENT.PAIN] = function(Inflictor) {
        //do some actions when myEnt takes damage
};

myEnt.Events[EVENT.FLEE] = function(Health) {
        //do some actions when myEnt's health is below 50%
};

myEnt.Events[EVENT.DEATH] = function(Inflictor, MeansOfDeath) {
        //do some actions when myEnt has died
};

myEnt.Events[EVENT.DELAYED] = function(TimedDelay) {
        //do some actions when myEnt delayScriptTime has been reached (this could be done away with IMO and replaced with script delays...)
};

myEnt.Events[EVENT.BLOCKED] = function(BlockEnt) {
        //do some actions when myEnt is blocked by a friendly NPC or player
};

myEnt.Events[EVENT.BUMPED] = function(Bumpee, Radius) {
        //do some actions when myEnt is bumped by a friendly NPC or player
};

myEnt.Events[EVENT.STUCK] = function(BlockEnt) {
        //do some actions when myEnt is blocked by a wall
};

myEnt.Events[EVENT.FFIRE] = function(Victim, MethodOfDamage) {
        //do some actions when myEnt shoots at its teammates
};

myEnt.Events[EVENT.FFDEATH] = function(Victim, MeansOfDeath) {
        //do some actions when myEnt kills a teammate
};

myEnt.Events[EVENT.MINDTRICK] = function(Inflictor) {
        //do some actions when myEnt has been mind tricked by someone
};

some code below...


pipobona 02-13-2008 11:10 AM

Quote:

Originally Posted by ensiform
I've actually been pondering just recently a better way to implement an alternate scripting for server-side all together (LUA, GM, Squirrel, or w/e you want).

But you'd want to consider the following:

Replace ICARUS ****.
Allow for server manipulation type stuff (that can be see in like ETPro, and other various games/mods)
As you can see, ICARUS is using a separate file for each script which is kind of messy and you would want to limit map scripts to just 1 script and do everything in that file.

For instance:

If you have some entity that has many scripts attached to it, instead of each file per "behavior set" you'd just have events set up as such:

GM could be like so:

Code:

some code above...

//note this. inside these functions would be accessing myEnt (I think) Might be events but not positive.

myEnt = FunctionToRetrieveEntity(params?);
myEnt.Events[EVENT.SPAWN] = function(SpawnTime) {
        //do some actions upon myEnt spawning
};

myEnt.Events[EVENT.USE] = function(UseEnt) {
        //do some actions when myEnt has been used
};

myEnt.Events[EVENT.AWAKE] = function(params?) {
        //do some actions when myEnt has awoken or been startled
};

myEnt.Events[EVENT.ANGER] = function(Enemy) {
        //do some actions when myEnt has found an enemy
};

myEnt.Events[EVENT.VICTORY] = function(Victim, MeansOfDeath) {
        //do some actions when myEnt has killed someone or something
};

myEnt.Events[EVENT.LOSTENEMY] = function(LastEnemy) {
        //do some actions when myEnt has lost its enemy
};

myEnt.Events[EVENT.PAIN] = function(Inflictor) {
        //do some actions when myEnt takes damage
};

myEnt.Events[EVENT.FLEE] = function(Health) {
        //do some actions when myEnt's health is below 50%
};

myEnt.Events[EVENT.DEATH] = function(Inflictor, MeansOfDeath) {
        //do some actions when myEnt has died
};

myEnt.Events[EVENT.DELAYED] = function(TimedDelay) {
        //do some actions when myEnt delayScriptTime has been reached (this could be done away with IMO and replaced with script delays...)
};

myEnt.Events[EVENT.BLOCKED] = function(BlockEnt) {
        //do some actions when myEnt is blocked by a friendly NPC or player
};

myEnt.Events[EVENT.BUMPED] = function(Bumpee, Radius) {
        //do some actions when myEnt is bumped by a friendly NPC or player
};

myEnt.Events[EVENT.STUCK] = function(BlockEnt) {
        //do some actions when myEnt is blocked by a wall
};

myEnt.Events[EVENT.FFIRE] = function(Victim, MethodOfDamage) {
        //do some actions when myEnt shoots at its teammates
};

myEnt.Events[EVENT.FFDEATH] = function(Victim, MeansOfDeath) {
        //do some actions when myEnt kills a teammate
};

myEnt.Events[EVENT.MINDTRICK] = function(Inflictor) {
        //do some actions when myEnt has been mind tricked by someone
};

some code below...


We have implented serverside lua now and a release is available already at http://www.jkalua.net/ Please check it out and tell me what you think about it :P

ensiform 02-13-2008 11:36 AM

Looks nice and all, but its still missing the ICARUS replacement >.<

And do you absolutely need to at least define the hooks or does it know that it is okay to not call if its not there?

pipobona 02-13-2008 11:38 AM

it tells you an error if you havent defined the hooks in your scripts. But this error is just handled and the game will shutdown without crashing.

We haven't got the icarus replacement yet because animations and stuff isnt in there yet. We will put that in the next release probably. As for now we need to get people who would like to use it.

ensiform 02-13-2008 07:00 PM

Quote:

Originally Posted by pipobona
it tells you an error if you havent defined the hooks in your scripts. But this error is just handled and the game will shutdown without crashing.

I think the best thing would be to just not call it at all if it doesn't exist and assume that its not there. If it is and not correct maybe, but I wouldn't shutdown.

This is what I do with GameMonkey:

(It's cgame but still my example for doing hooks/callbacks (the command/icc one is a little more complex tho)

http://pastebin.com/m2e77372b

dnifan 02-16-2008 09:01 AM

No, it just returns when the hook is not defined.


All times are GMT -4. The time now is 04:17 PM.

Powered by vBulletin®
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
LFNetwork, LLC ©2002-2011 - All rights reserved.