Global Communications > killermonkey's Blog
KM Blog - LUA Specs
(1/1)
killermonkey:
Okay folks, as I promised I am going to go into some detail about BETA 3's features. This week will be about LUA gameplay. I will start by shooting off a couple tutorials for you to read:
http://lua-users.org/wiki/TutorialDirectory
http://lua-users.org/wiki/SampleCode
Now LUA for GES is definitely not going to explore the most advanced sides of the scripting language, but we absolutely employ many C++ to LUA and vice versa features. The neatest feature is that fact that any errors in your LUA script print out directly to the console window so you can correct them easily and you can reload the gameplay without reloading GES! We do this with the following commands:
ge_gameplaylist - List the current available gameplay identities
ge_gameplay [ident] - Load a gameplay by it's identity, this restarts the round
Here is a sample LUA gameplay definition and script for the YOLT gameplay (not final):
yolt.txt:
--- Code: ---
"Gameplay"
{
"PrintName" "You Only Live Twice"
"TeamPlay" "2"
"Events"
{
//C++ Events// //LUA functions//
"OnLoadGamePlay" "OnLoadGamePlay"
"PreRoundBegin" "PreRoundBegin"
"Think" "Think"
"PlayerConnect" "PlayerConnect"
"CanPlayerRespawn" "CanPlayerRespawn"
}
}
--- End code ---
This defines the different functions we are going to implement in our LUA script. This basically tells our gameplay function in C++ what functions to expect to be defined so that it will know to call them during the course of play. Note the "teamplay" variable:
0 - NO TEAMPLAY
1 - ALWAYS TEAMPLAY
2 - TOGGLE TEAMPLAY (uses ge_teamplay convar)
Now you can define internal functions to the LUA script that does anything you want, but the C++ only recognizes the following functions as "events" (for now) and thus calls them during the course of gameplay:
"Think"
"OnLoadGamePlay"
"OnUnloadGamePlay"
"PlayerConnect"
"PlayerDisconnect"
"PreRoundBegin"
"PostRoundBegin"
"PrePlayerSpawn"
"PostPlayerSpawn"
"PlayerKilled"
"CanPlayerRespawn"
Now I will show you excerpts from the YOLT script (yolt.lua):
--- Code: ---
g_bStartedRound = false;
function GetGameDescription()
return "YOLT";
end
function OnLoadGamePlay()
SetDamageMultiplier( FOR_ALL_PLAYERS, 1 );
end
function PlayerConnect(player)
--When a client connects let him join in, unless the round has started
if (g_bStartedRound) then
AddDeaths(player, 2);
end
end
function PreRoundBegin()
g_bStartedRound = false;
for i=0,31 do
ResetDeaths(i);
end
end
--- End code ---
GetGameDescription() is what tells the server what to print under "Game" in the server browser.
First we make sure the damage multiplier is reset to 1 in case we were playing another mode that changed it and didn't change it back. Then we tell the server what to do when a player connects, in this case we check to see if we have started playing the game, if we have we keep the player out of it by giving him two deaths to start with.
Then we define what to do when we restart the round. In this case we set the start flag to false and reset everyone's death counts.
--- Code: ---
function Think()
if ( GetNumActivePlayers() <= 1 or (IsTeamplay() and GetNumActivePlayers() < 2) ) then
g_bStartedRound = false;
return;
end
if (not g_bStartedRound) then
g_bStartedRound = true;
end
--Check to see if the round is over!
if( IsTeamplay() ) then
-- check to see if each team has a player...
local iMI6PlayersLeft = 0;
local iJanusPlayersLeft = 0;
for i=0,31 do
if(GetDeaths(i) < 2 and IsValidPlayer(i)) then
if(GetPlayerTeam(i) == TEAM_MI6) then
iMI6PlayersLeft = iMI6PlayersLeft + 1;
elseif(GetPlayerTeam(i) == TEAM_JANUS) then
iJanusPlayersLeft = iJanusPlayersLeft + 1;
end
end
end
if ( (iMI6PlayersLeft == 0) and (iJanusPlayersLeft == 0) ) then
ClientPrintAll(HUD_PRINTTALK,"#TIE")
EndRound()
elseif ( iMI6PlayersLeft == 0 and iJanusPlayersLeft > 0 ) then
AddToTeamScore( TEAM_JANUS, 1 );
ClientPrintAll(HUD_PRINTTALK,"#JANUS_WINS")
EndRound()
elseif ( iJanusPlayersLeft == 0 and iMI6PlayersLeft > 0 ) then
AddToTeamScore( TEAM_MI6, 1 );
ClientPrintAll(HUD_PRINTTALK,"#MI6_WINS")
EndRound()
end
else
--Check to see if more than one player is around
local iPlayersLeft = 0;
local iPlayerIndex = 0; -- Start at 1 for player index
for i=0,31 do
if(GetDeaths(i) < 2 and IsValidPlayer(i)) then
iPlayerIndex = i;
iPlayersLeft = iPlayersLeft + 1;
end
end
if(iPlayersLeft <= 1) then
ClientPrintAll(HUD_PRINTTALK,"#PLAYER_WINS",PlayerName(iPlayerIndex))
EndRound()
end
end
end
--- End code ---
This is a big one to stomach. First off, this is the think function, it is called every 1/10th of a second from the gamerules only if we are in active gameplay (ie not pre/post round or intermission). Basically we don't start the round until we have at least 2 people for non-teamplay and 3 people for teamplay (otherwise a win condition would happen automagically). Then we go through different criteria for each case (team or no team) and decide if a win happened (1 player left!). If it does, we let everyone know and end the round.
PHEW! I will leave you with a list and some description of the different functions we can use in LUA that invoke changes / gets information directly from the C++ server code:
"Msg" - Send a message out to the chat window
"ConMsg" - Send a console message out
"ClientPrintAll" - Send a message out to all clients, uses localization
"EndRound"
"IsTeamplay"
"IsValidPlayer"
"GetNumActivePlayers" - Number of players currently in the server and playing (NOT spectating)
"GetPlayerTeam"
"SetPlayerTeam" - Set's a player on a certain team (useful for president modes, not fully implemented though)
"AddToTeamScore" - Add's to the team score the value given
"PlayerHealth" - Get the health of a player
"PlayerSetHealth" - Set a player's health level
"PlayerMaxHealth" - Get the maximum health
"PlayerSetMaxHealth" - Set the maximum health
"PlayerArmor"
"PlayerSetArmor"
"PlayerMaxArmor"
"SetDamageMultiplier" - A flat scaling of the damage received (any damage!)
"GetKills" - Get a player's kills
"GetDeaths" - Get a player's deaths
"AddKills" - Give the player kills (score)
"AddDeaths" - Give the player deaths
"ResetDeaths" - Reset the deaths (0)
"PlayerName" - Get the player's name
Navigation
[0] Message Index
Go to full version