Synthetic Reality
TurnAbout API
 
Arcadia:
Home Page
Donate $
Contact Us

Community:
Bulletin Board
Synthetic Reality

Toys:
Collaboration
DomiNation
Empyrion
synChess
synJam
synJet
synPool
synSpades
synSpace
synVille
synVideo
TurnAbout

API Events:
TA_OnLoaded
TA_OnStartGame
TA_OnStopGame
TA_OnStateAnimationDone
TA_OnCanStartGame
TA_OnCanJoinGame
TA_OnSize
TA_OnPing
TA_OnTick
TA_OnText
TA_OnPlayerSlotChange
TA_OnPlayer
TA_OnPlayerInfoNeeded
TA_OnPlayerClick
TA_OnGetPlayerMenu
TA_OnDoPlayerMenu
TA_OnPacket
TA_OnMouse

API General:
TA_Log
TA_IsModerator
TA_SendPacket
TA_IsKeyDown
TA_Print
TA_MouseLoc
TA_MaxPlayerSlots
TA_NthPlayerSlot
TA_PlayerName
TA_NumCards
TA_NthCardId
TA_GetCardProperty
TA_SetCardProperty
TA_SetState
TA_GetMsec

API Graphics:
TA_SetRenderMode
TA_FillSolidRect
TA_LineTo
TA_DrawText
TA_Ellipse
TA_Polygon
TA_CreateImage
TA_DestroyImage
TA_LoadImage
TA_EraseImage
TA_CopyImage
TA_StretchImage
TA_GetImageSize
TA_GetPixel
TA_SetPixel
TA_DrawFace

API Sound:
TA_PlayWAV
TA_PlayMIDI

API Playing Cards:
TA_StockCardsInfo
TA_DrawStockCard
TA_StockDeckShuffle
TA_StockDeckPeek
TA_StockDeckTake

API Bags:
TA_SetBagValue
TA_GetBagValue
TA_NumBagItems
TA_GetNthBagItem
TA_DeleteBagItems

API EditBox
TA_EditBoxCreate
TA_EditBoxDestroy
TA_EditBoxShow
TA_EditBoxSetRect
TA_EditBoxSetText
TA_EditBoxGetText

TurnAbout is one of the toys which can be played in Arcadia. It is a user-programmable, cards-metaphor, open-API, Lua-scripted, board game engine.. thing.

This page documents the API (Applications Programming Interface) by which you can create a new Deck Style Script (written in lua) and thereby make a brand new game (or extend an old one) to be played inside TurnAbout.

THE INFORMATION BELOW CAN BE ASSUMED TO BE INCOMPLETE, AND POSSIBLY IN ERROR. THE API IS STILL IN DEVELOPMENT. IF YOU HAVE SUGGESTIONS, PLEASE POST IN THE ARCADIA FORUM.

  Event-Driven   Events   Services   Graphics      
Overview

The idea is that when a player picks a 'deck' to play in TurnAbout, that implies a deck style and for every deck style there is a game, a game whose basic functionality is written in a lua script. Please see TurnAbout's web page for some hints on creating a new deck style. This page is concerned with the contents of your lua script.

Your deck style will have a name, and your lua script will have the *same* name. That name must be a legal file name and will be located in a directory under your current Arcadia Serial Number (so that people don't mess up each other's scripts). So, there is exactly one lua file you should be editing, and that is:

.../arcadia/toys/toy10/Assets/Styles/<your serial number>/styleName/styleName.script

Where 'styleName' is the name you gave your new deck style. Before you can play your game, you will need to create at least one card in your deck style, and a deck containing at least one card from your deck style. Then you can select that deck on the TurnAbout toy options dialog, and the next time you press START GAME, you will be playing YOUR game.

Eventually, script files will be shared automatically, but for now you will have to share them manually. Script files are not allowed to read or write to disk, the goal being to NOT allow a style script to act as a virus, spybot, or other negative energy creation. If you feel this security is not being properly imposed, please let me know ASAP.

You might be thinking that your lua script should be an infinite loop (a game loop) constantly getting user input, doing caclulations, advancing game state, and rendering. You would be wrong. The main loop still belongs to Arcadia/TurnAbout and you must be completely 'event-driven'

Game State

The TurnAbout engine is in one of the following states at any given time:

  • PICK DECK (the moderator is picking one of his or her decks, no lua script is loaded, and no players have JOINed the game.
  • JOIN GAME (the moderator has picked the deck, people are fetching the deck, the script, and any assets they need. Once they have fetched the files, they can press their JOIN GAME button to get assigned a slot in the not-yet-started game. Since your script has been loaded, you can be rendering the screen as you see fit, perhaps indicating the current player slot list, asset fetching status, etc. You can send packets which are seen by anyone who has finished fetching (and loading) their copy of the script.)
  • GAME IN PROGRESS (this is actually several possible states, depending on how you want to organize things. TurnAbout offers you various sub states you might enjoy, like rolling dice, having arcadia faces walk around the stonehenge board, etc. If your script doesn't need these features, then you can just consider it being 'in-game'. This also goes for 'GAME OVER' which is something your script decides has happened. Just because the game is over doesn't mean you have to stop rendering the screen. You could show high scores, etc. What really counts is when the game is STOPPED. At that point your script is unloaded and everyone returns the the PICK DECK state and waits for the moderator to pick another game.
Event-Driven? What's That?

That means that your lua script is not one big program, it is a zillion little functions called 'event handlers' Your event handlers will be 'called' from TurnAbout when it has something important to pass along to you. You might do arbitraily complicated things inside your event handler, but you must always be thinking in terms of 'returning' as soon as possible, and never have an infinite loop in your event handler.

The time you take in your event handler, to get the job done, will be entirely perceived by the players as 'lag' so don't let them catch you spinning idly!

So, you never call something modal like "Get Input From User" and wait forever for him to type something. Instead, you wait to be called on your event handler "OnUserTypedSomething" (not the real event name)

Unlike Well of Souls, however, every player has a copy of the script, and every player will get event notifications. It is up to your script to 'do the right thing' and have only some actions take place on the moderator's computer, while other actions happen on all computers.

About Functions, Lua Functions in Particular

So, your lua script is a bunch of functions. These functions can be grouped into three categories:

  • Event Handlers (TA_OnXXX) These are called BY TurnAbout when it wants to tell you something important.
  • Service Requests (TA_xxxx) These don't actually appear inside your file, but you can call them when you want to ask TurnAbout to do something for you.
  • General Functions (do NOT start with TA_) These are functions you compose for your own purposes.

So, when you write code, never start your function name with TA_ unless it is an official TurnAbout event handler or service request.

The Official TA_ functions require special arguments and may return one or more values. You must exactly match the needs of those functions or things will go horribly awry (including the possibility of crashing TurnAbout/Arcadia -- but not in a way to actually cause damage to the computer -- just inconvenience to the player -- who will quickly learn never to play your deck style again.)

You might find insight into the effective use of TA_ functions by examing the style scripts provided in serial number 00000001.

Mandatory TA_OnXXX Event Handlers

Your Style Script MUST define the following functions. They are how TurnAbout tells your script that important things have happened. Your script does NOT have the luxury of running a continuous game loop. Your script is event-driven and must return from each event as rapidly as it can, or the game will feel laggy to the player.

Once Again, YOUR SCRIPT must define these functions, which will be called BY TurnAbout at the appropriate time, and your functions must then return immediately to TurnAbout and not hang around waiting for anything at all. You CAN, of course, request services as part of handling the event, though you should watch out for possible catch-22 situations.

When you create a new style card (using the TurnAbout Card Editor), a starting script is made for you with this functions already defined. Your job then is to add meat to the empty bones of that starting script.

-----------------
--
TA_OnLoaded
--
-- Called once when style script is first loaded (might be before startGame button pressed)
-- This is a good place to completely clean out your global variables, in preperation for a new game
-- But you will probably also want to initialize most state in TA_OnStartGame
--
--
Arguments:
-- You are given 4 numbers: Your serial number (player on this PC), the moderator's serial number
-- (which could change during the game), and the width and height (in pixels) of the screen
-- area available to your game. This area can change as the player resizes his windows.
--
--
Your Function Returns: nothing

function TA_OnLoaded( mySerNum, moderatorSerNum, width, height )
end

 

-----------------
--
TA_OnStartGame
--
-- Called once when the moderator pushes the StartGame button (or for latecomers it is called
-- after they choose to join a game in progress)
--
--
Arguments:
--You are given two numbers: The serial numbers of the player on this PC, and the moderator.
--
--
Your Function Returns: nothing

function TA_OnStartGame( mySerNum, moderatorSerNum )
end

 

-----------------
--
TA_OnStopGame
--
-- Called once if the moderator aborts the game in progress. You should clean up after yourself
-- here, but your script will also be unloaded after this, so you will be tempted not to. Close your
-- Image Buffers, if nothing else.
--
--
Arguments:
--You are given two numbers: The serial numbers of the player on this PC, and the moderator.
--
--
Your Function Returns: nothing

function TA_OnStopGame( mySerNum, moderatorSerNum )
end

 

-----------------
--
TA_OnStateAnimationDone
--
-- If you use the TA_SetState command to initiate a stock animation (like rolling a die, or advancing a
-- gamepiece), you will eventually get called back on this event handler to let you know the animation has
-- completed (on the local PC).
--
--
Arguments:
-- * stateNumber used in the TA_SetState command.
--
--
Your Function Returns: nothing

function TA_OnStateAnimationDone( stateNumber )
end

 

-----------------
--
TA_OnCanStartGame
--
-- Called periodically during the 'Join Game' state to see whether or not to offer the START GAME
-- button to the moderator. Only the moderator sees a start game button (and does NOT see a
-- Join Game button.) You might want to suppress the start game button until enough players
-- have joined.
--
-- NOTE: You can safely return 1 at all times and it doesn't mean the start game button will be on
-- screen all the time. You are only
vetoing it during the Join Game state (before the game has been
-- launched)
--
--
Arguments:
--You are given two numbers: The serial numbers of the player on this PC, and the moderator.
--
--
Your Function Returns:
-- * 1 - yes, it is ok to show the START GAME button to the moderator
-- * 0 - no, hide the start game button

function TA_OnCanStartGame( mySerNum, moderatorSerNum )

return 1

end

 

-----------------
--
TA_OnCanJoinGame
--
-- Called periodically during the 'Join Game' state to see whether or not to offer a join game
-- button to the local player. Normally you should just return 1, but you might return 0 if
-- your game does not allow latecomers and the game has already started.
--
--
Arguments:
--You are given two numbers: The serial numbers of the player on this PC, and the moderator.
--
--
Your Function Returns:
-- * 1 - yes, it is ok to show the JOIN GAME button to this player
-- * 0 - no, hide the join game button

function TA_OnCanJoinGame( mySerNum, moderatorSerNum )

return 1

end

 

-----------------
--
TA_OnSize
--
-- Called whenever the user drags the window to a new size, or uses the splitter bar.
-- Could be called many times a second, you might want to just note the new size
-- and actually implement the change in a later call to TA_OnTick
--
-- Note: Please see the
Graphics section below for more information on rendering your game
-- screen. You probably care a lot about handling changes in size to the game screen
-- since you will probably want to scale things to fit nicely in the new window.
--
--
Arguments:
-- You are given two numbers: the new width and height (in pixels) of the game's screen area.
--
--
Your Function Returns: nothing

function TA_OnSize( width, height )
end

 

-----------------
--
TA_OnPing
--
-- TurnAbout may call this function if it worries that you are not right in the head. Do not
-- expect it to be called, but do provide it.
--
--
Arguments:
-- You are given a number which has no particular meaning to you.
--
--
Your Function Returns: the number it was given

function TA_OnPing( count )

return count

end

 

-----------------
--
TA_OnTick
--
-- This function will be called many times a second, though not necessarily regularly.
-- You should use the 'msec' value to decide if enough time has passed since the last
-- time you really needed to do something in this handler.
--
--
Arguments:
-- You are given a number: milliseconds since some unknown start time (probably since
-- your computer was rebooted. You should keep track of changes in the msec value so
-- as to tell when, for example, 1000 msec have elapsed since you last did <something>
--
--
Your Function Returns: nothing

glLastTick = 0 -- initialize this somewhere. I like to put 'gl' on the front of global values
...

function TA_OnTick( msec )

if ( msec >= (glLastTick + 50) ) then

-- This limits us to no more than 20 times a second, no matter how fast
-- the user's computer is
glLastTick = msec
DoSomethingTwentyTimesASecond()

end

end

Note: Calls fo TA_OnTick() will be truly chaotic and influenced by everything else happening on the computer (for example, they may stop entirely when the user loads a large file, starts some other program running, or even drags/re-sizes a window around on the screen. You can NOT depend on any sort of regularity, nor are you guaranteed to be called every millisecond, so don't sit around waiting for a PARTICULAR millisecond.

-----------------
--
TA_OnText
--
-- If the player types something in the arcadia chat window, and then presses [enter],
-- this function will be called to give you 'first peek' at what they typed.
-- You might use this to accept typed commands from the player. (only the local
-- player's text is delivered in this way)
--
--
Arguments:
-- You are given a number and two strings: the serial number of the local player, their
-- Arcadia Account name, and the text of what they just typed.
--
--
Your Function Returns:
-- One of three things, depending on what you want done with the text after you've
-- looked at it:
-- * You don't care, let it be sent as chat:
return 0, ""
-- * You have swallowed the text, do NOT send it as chat:
return 1, ""
-- * You want chat sent, but not what they typed:
return: 2, "send this instead"
--
-- NOTE: You must return TWO VALUES in all cases: a number, *and* a string. Lua allows that.

function TA_OnText( serNum, playerName, text )

return 0, "" -- In general, you do not care

end

 

-----------------
--
TA_OnPlayerSlotChange
--
-- Each player in the game is mainly identified by their serial number, but they also have
-- a 'slot number' and this function is called when a player is assigned to a slot number.
-- in theory, a slot number less than 1 means they left their existing slot, but do not
-- count on that for now. Don't count on this at all, really, but it's nice in the pre-game
-- start period to be able to maintain a record of who is playing. Still, you will probably
-- rely on service requests to really know what is happening with the slots.
--
--
Arguments:
-- You are given 2 numbers and a string: the slot number (1-8) of the player (or < 1 if
-- they are leaving the game.. maybe), the serial number of the player, and the Arcadia
-- name of the player.
--
--
Your Function Returns: nothing

function TA_OnPlayerSlotChange( slotNum, serNum, playerName )
end

 

----------------------------------------------------------
--
TA_OnPlayer
--
-- Turnabout wants to tell me that someone has entered or left the server
-- in case I need to remove them from a game in progress, or sync them
-- up to current game state. As far as sync goes, I might choose to wait
-- until they formally request sync via a game packet
--
--
Arguments:
-- You are given two numbers. The SerNum of the player in question, and their new state.
--
-- state:
-- 0 - they entered
-- 1 - they left (on purpose)
-- 2 - they 'disappeared' (crashed or lost connection or ???)
--
--
Your Function Returns: nothing

function TA_OnPlayer( serNum, state )

if ( state == 0 ) then
-- he entered
else
-- he left
end

end

----------------------------------------------
--
TA_OnPlayerInfoNeeded( serNum, col )
--
-- Arcadia maintains a list of players in the lower right corner of the screen. For each of these players
-- there are several columns of information. You may add a few additional columns to this display to use for
-- your own purposes. For each column you will specify a label, a width, and a text string for each player.

--
-- TA_OnPlayerInfoNeeded provides two purposes. It lets you specify the name of the column, and its width in
-- pixels. It also lets you specify the text (and color) of the column entry for a specific player serNum
--
--
TurnAbout will call YOU when it is ready for this information. If you know the text should change
-- (for example, new score information is available), then call
TA_UpdatePlayerInfo( serNum ) to let TurnAbout
-- know it needs to ask you for the information the next time it is convenient to do so.
--
-- Your columns are numbered starting with 0, and you will be asked about each possible column in turn.
-- If you return an empty string for the column label, then that column will not be created (note: you are
-- only given one chance to define your columns, this will happen just after your script is loaded. So
-- you must be immediately prepared to provide your column definitions.
--
-- You are adding columns in addition to the default arcadia columns, so in the example above, your columns
-- begin just after the "Vers." column. So "Rating" is column 0, "Empire" is column 1, etc.
--
--
Arguments:
--
-- * SerNum of the player whose 'row' of the table you are to provide information about.
-- If this serNum is 0, then you are being asked for the column width and label
--
-- * Column Number (0 being your first column)
--
--
Your Function Returns:
--
-- * column label For example: "Score"
-- * width (in pixels) For example: 60
-- * text (only used if serNum ~= 0) For Example: "1234 (winner!)"
-- * color (of the player's text. Column label is always black) For Example: "ff0000" <-- red
--
-- Now, I can see you thinking "I will ask this to be repainted constantly and do some color/text animation
-- and it will be cool!" Please don't do that. It will flicker.
--

function TA_OnPlayerInfoNeeded( serNum, col )

if( col == 0 ) then

-- column 0 is my style's RATING column
if( serNum == 0 ) then

-- just provide the label and with information in general
return "Rating", 60, "", ""

else

-- return the current rating of this player
local score = GetCurrentRating( serNum )
return "Rating", 60, score, "00ff00" -- in green

end

end
return "", 0, "", "" -- for whatever reason, I do not need or want this column

end

--------------------------------------------
--
TA_OnGetPlayerMenu( slot, serNum, playerName )
--
TA_OnDoPlayerMenu( slot, serNum, playerName )
--
-- This pair of events lets you add a few additional commands to the
-- right-clickup popup menu in the arcadia player list. The "Get" event
-- allows you to specify the text of the menu command (if any) and whether
-- it should be checked or dimmed. The "Do" event is your notification
-- that the user has selected your menu option and you should now perform
-- it.
--
-- The "Get" event will be called once for each possible 'slot'
-- and you should return the empty string ("") for any slots you do not
-- wish to populate with a menu command.
--
--
Arguments:
--
-- * slot number (0 for the first/top menu command)
-- * serNum of the player whose row was right-clicked upon
-- * playerName (for your convenience, the name of the player is also provided)
--
--
Your Get Function Returns:
--
-- * command text For Example: ("Boot " .. playerName .. " from server.")
-- * checked For Example: 1 (if you want a check mark to appear next to the command) 0, if not
-- * dimmed For Example: 1 (if you want the menu entry to be 'dimmed')
--

function TA_OnGetPlayerMenu( slot, serNum, playerName )

if ( slot == 0 ) then

-- I have one menu command to offer the moderator
if(
TA_IsModerator( glMySerNum ) ) then

return ("Boot " .. playerName .. " from game!" ), 0, 0

end

end

return "", 0, 0 -- this is not a menu command from me

end

-- Your Do function returns:
--
-- * validMenuCommand - return 1 if you expected this command, 0 otherwise.
--
-- Note that a dimmed menu item is not necessarily a disabled menu item, so it is your
-- responsibility to ignore inappropriate commands
--

function TA_OnDoPlayerMenu( slot, serNum, playerName )

if( slot == 0 ) then

-- slot 0 is the only menu option I provide
-- and I only offer it to the moderator, and not on myself
if( TA_IsModerator( glMySerNum ) and (glMySerNum ~= serNum ) ) then

-- Call some function to actually do the work
BootPlayerFromGame( serNum )

end

end

-- this is not a menu command I am supporting, so let turnabout know I didn't do anything
return 0 -- this is not one of my menu commands

end

--------------------------------------------------
--
TA_OnPlayerClick( serNum, numClicks )
--
-- The user may from time to time click on a row in the Arcadia Player list. This
-- event notifies you when that happens. You might want to use this as a means to
-- select a particular player as.. oh.. a target.. or show extra info.. or highlight
-- their position. Whatever. Including nothing
--
--
Arguments:
--
-- * serNum (serial number of the player in that row -- they may not have joined the game
-- so you need to consider whether they are a player or a spectator
-- SerNum = 0 means they clicked in the area outside actual player rows
-- (you might use that as a means to 'de-select' whatever you selected before)
-- * numClicks This will be 1 or 2, indicating a single click or a double click
--
-- Note that right-clicks trigger the popup menu, so they are not reported here.
-- Note also that double clicks open the Arcadia Diary (you can't stop that) so
-- double click is not a very good 'special command' indication to you.
--
--
Your Do function returns: nothing
--

function TA_OnPlayerClick( serNum, numClicks )

if ( (serNum ~= glMySerNum) and (numClicks == 1) ) then

SetCurrentTarget( serNum )

end

end

-----------------
--
TA_OnPacket
--
-- When you use the TA_SendPacket() service request to send a packet to one or more
-- players, this function will be called on the PC of each player that receives that packet.
-- It merely passes along the arguments provided in the original call to TA_SendPacket
--
--
Arguments:
--
-- * serNumSender: You are given the serialNumber from which the packet was received (often this will be
-- the moderator, and one of the num values will be the serial number of the actual player the packet
-- contains information about.
-- * nums and strs: You also get the 4 numbers and three
-- string values which you included in the original call to
TA_SendPacket
--
--
Your Function Returns: nothing

function TA_OnPacket( serNumSender, num1, num2, num3, num4, str1, str2, str3 )

if ( TA_IsModerator( serNumSender ) ) then

-- I only accept packets from the moderator
if( num1 == 47 ) then

-- packet 47 is my 'pulled trigger' packet and I keep the weapon type in num2
-- and the intended target number in num3
HandleTrigger( num2, num3 )

end

end

end

 

-----------------
--
TA_OnMouse
--
-- Called when the local player clicks the mouse inside the main display window (above the chat)
-- The arguments tell you if it was a left or right mouse event and whether the button was being
-- pressed or released.
--
-- You are also given the x,y value (in pixels, relative to the top/left corner of the main display)
--
-- NOTE: You can use TA_MouseLoc() to find the current location of the mouse at any time.
--
--
Arguments:
-- You are given 4 numbers:
-- * buttonId (0 = left mouse button, 1 = right mouse button)
-- * clickType ( 0 = mouse UP, 1 = mouse DOWN )
-- * x,y Coordinares at which the mouse was clicked
--
--
Your Function Returns: nothing

function TA_OnMouse( buttonId, clickType, x, y )

if( buttonId == 0 and clickType == 1 ) then

TA_Print( "You just clicked on: " .. x .. ", " .. y )

end

end

Available TA_xxxx Service Requests

Your event handlers can call external functions provided by TurnAbout to carry out various actions on your behalf. Feel free to suggest additional functions if you feel there is a compelling need.

Unlike the Event handlers, you do NOT provide function bodies for these functions. They have been provided FOR you, and you can just CALL them when you need to. The documentation that follows is an example usage of each function, but normally you would call these functions from inside your own event handlers.

You do NOT have to call ANY of these functions, if you do not WANT to, but you probably do.

------------
--
TA_Log( text )
--
-- This function logs some boring text. Generally intended to help you debug your program. You can
-- not specify font size or color. It is added to the 'funpack' log window, and also to the main chat
-- window.
--
-- Since you have no single-stepping debugger available to you, you will need to use this function
-- to understand what is going wrong when your script stops working. This involves peppering your
-- script with TA_Log() messages which let you know which functions got called and what arguments
-- were passed to them, or anything else which would help you understand what the problem is.
--
--
Arguments:
-- You provide a string you would like to have logged
--
--
Values Returned To You: none
--
--
Example Usage:

TA_Log( "I am about to do something that might crash and would like to document how far I made it" )

 

------------
--
TA_IsModerator( serNum )
--
-- This function checks a serial number for you and returns nil (false) if it is NOT the serial
-- number of the current moderator. Remember,
in Lua 0 is true (not false!) Only nil is false.
--
--
Arguments:
-- You provide a number: the serial number you would like to check.
--
--
Values Returned To You: nil (false) or 1 (true)
--
--
Example Usage:

if ( TA_IsModerator( serNum ) ) then

TA_Log( "hey, serNum " .. serNum .. " *is* the moderator, I should obey him!" )

end

 

------------
--
TA_SendPacket( to, num1, num2, num3, num4, str1, str2. str3 )
--
-- This function sends a packet to one or more players in the game. The num and
-- string arguments will be delivered to the targeted players via the TA_OnPacket
-- event handler when the packet arrives on their PC.
--
--
Arguments:
-- You provide a 'to' number which indicates who will receive the packet:
-- * 0 means "send to all players"
-- * -1 means "send just to the moderator" (which assumes you are NOT the moderator)
---- anything else is assumed to be a player serial number and only that player gets the packet
-- Also, you provide 4 nums, and three strings, which will be delivered to the
-- targeted players.
--
-- NOTE: While strings may contain any ascii you like, they must be relatively short (say
-- around 100 characters each maximum). The nums are integers and must be in the
-- range +/- 2 billion. If you need to send a floating point value, either send it as a string,
-- or use some special trick, like "123 in a num really means 1.23 and I will divide the value by 100
-- when I receive it". If you don't NEED a num, use
0, and if you don't NEED a string, use ""
--
-- NOTE: You never receive a packet that you sent yourself. Often you will want to pretend you
-- did, so as to stay synced to the other players.
--
--
Values Returned To You: none
--
--
Example Usage:

TA_Log( "I will sent my birthday to the moderator" )
TA_SendPacket( -1, 11, 2, 2004, 0, "Billy", "Was Born", "" )

 

------------
--
TA_IsKeyDown( virtKeyCode )
--
-- This function checks to see if the user is currently holding down a particular keyboard key (or
-- mouse button). You need to know the Microsoft "Virtual Key Code" for the keyboard key you want.
--
--
Arguments:
-- You provide the virtual key code for the key you care about. Please note this is NOT the ASCII
-- Value of the character on that key, and that some keys have different virtCodes depending on if
-- they are on the main keyboard or the numpad, etc. Good Luck finding the key codes! Use Google!
--
--
Values Returned To You:
-- returns 1 (true) if the key is DOWN, and nil (false) if it is UP.
-
--
Example Usage:

TA_Log( "I wonder if they are holding down the F5 Key right Now" )
if( TA_IsKeyDown( <keyNum for F5> ) ) then

TA_Log( "Why yes, they are!" )

end

And here is a list of popular Virtual Key Codes: (um, translated to DECIMAL since that is what lua wants)

1 - Left mouse button 37 - LEFT 96 - numpad 0
2 - right mouse button 38 - UP 105 - numpad 9
16 - shift key 39 - RIGHT 112 - F1
17 - ctrl Key 40 - DOWN 113 - F2 ...
27 - ESCape 45 - INSERT  
32 - SPACE 46 - DELETE  
33 - PgUp 48 - "0"  
34 - PgDn 47 - "9"  
35 - END 65 - "A"  
36 - HOME 90 - "Z"  

The full list (in HEX) can be found here (had to break url in two to make it fit!):

http://msdn.microsoft.com/library/default.asp?
url=/library/en-us/winui/WinUI/WindowsUserInterface/UserInput/VirtualKeyCodes.asp

NOTE: At present, this still works even when turnAbout is not the foreground window.. so if you bring notepad to the front and start typing in it, your mini-game will continue to react to the keystrokes. I may or may not remove that 'feature'

------------
--
TA_Print( text )
--
-- This function prints text to the chat window, and allows you a little bit of stylistic control
-- over its appearance (font name, color, size and bold, italic, and underline).
--
--
Arguments:
-- You provide a string with the text you want added to the chat window. Angle brackets can be
-- used to indicate simple font decoration
--
--
Values Returned To You: none
--
--
Example Usage:

TA_Print( "Dear <b>Player</b>, I <i>love</i> <color=FF0000><size=200>YOU" )

Will display: "Dear Player, I love YOU"

The special font decorations are:

// usage: TA_Print( string )
// Supports special tokens:
// <b> bold </b>
// <i> italic </i>
// <u> underlined </u>
// <size=90> (font size, 90 is normal size, 250 is so large as to be less than useful)
// <font=name> (font name, who knows what happens if they don't have the font.. something ugly)
// <color=RRGGBB> (in hex, like a web page, but no quotes)

------------
--
TA_MouseLoc( )
--
-- This returns the location of the mouse cursor, in pixels, relative to the top left corner of the
-- main graphical display area.
--
-- (0,0) is top left corner, (width, height) is lower right corner
--
-- NOTE: Use the TA_OnMouse() event for real time notification of mouse button clicks
--
--
Arguments: none.
--
--
Values Returned To You:
-- You are given two numbers, the x and y, in pixels.
Note that you must have
-- two variables ready to receive the result
.
--
--
Example Usage:

-- Now, WHERE is that Mouse cursor?
-- we need TWO variables to receive the results.
local x
local y
x, y = TA_MouseLoc( )

 

------------
--
TA_MaxPlayerSlots()
--
-- This function returns 8, the max number of players supported by TurnAbout. You
-- should act surprised each time you call it, like mayber someday it will say something else.
-- It probably won't.
--
--
Arguments: none
--
--
Values Returned To You: 8
-- Well, ok, returns the maximum number of player slots. You can then interate from 1 to this
-- number to get information about each slot.
--
--
Example Usage:

local numSlots = TA_MaxPlayerSlots()
for i=1, numSlots do
end

 

------------
--
TA_NthPlayerSlot( n )
--
-- Provides information about a given player slot Remember that Lua counts from 1, not zero
-- so N is a legal max value
--
--
Arguments:
-- You provide a value of N between 1 and TA_MaxPlayerSlots (8), inclusive
--
--
Values Returned To You:
-- This function returns THREE values to you, two numbers and a string, in the order:
---- slotState, serNumOfPlayerInSlot, ArcadiaNameOfPlayerInSlot
--
-- NOTE: an empty slot will have a slot state and sernum set to 0. a state value of 1
-- means it is a human player, while a state of 2 is a bot. (bots have negative serNums
-- which imply which bot brain is in use)
--
--
Example Usage:

local numSlots = TA_MaxPlayerSlots()
local state
local serNum
local name
for n=1, numSlots do

state, serNum, name = TA_NthPlayerSlot( n )
TA_Print( "Slot " .. i .. ", is in state " .. state .. ", with sernum "
.. serNum .. ", and name: " .. name)

end

 

------------
--
TA_PlayerName( serNum )
--
-- Sometimes you want the ArcadiaName of a player, and you only have their serial number.
--
--
Arguments:
-- You provide the serial number of a player.
--
--
Values Returned To You:
-- You are given their name, as a string
--
-- NOTE: It can only look up the name of players who are there right now.
--
--
Example Usage:

local serNum = 47
local name = TA_PlayerName( serNum )
TA_Print( "Hello, " .. name .. ", did you know your serNum was " .. serNum .. "?" )

 

------------
--
TA_UpdatePlayerInfo( serNum )
--
-- Say you have reason to believe that the PlayerInfo columns need to be updated (see
-- the TA_OnPlayerInfoNeeded event for details). Use this function to tell TurnAbout/Arcadia
-- to refresh one or more lines of that list box.
--
-- Note: a serNum value of zero will cause all rows to be updated. Otherwise only the row
-- for the player serNum you specify will be updated. This will update all columns of that row.
--
--
Arguments:
-- You provide the serial number of a player, or 0 for 'all players'.
--
--
Values Returned To You: none
--
--
--
Example Usage:

UpdateAllScores() -- say this updates some lua tables
-- Ask TurnAbout to refresh the player list.
-- In response to this, I will get a call on my TA_OnPlayerInfoNeeded event
TA_UpdatePlayerInfo( 0 )

 

------------
--
TA_NumCards( propertyName, propertyValue )
--
-- A Turnabout game is always launched using the moderator's "deck" which has some
-- number of cards in it. These cards then have properties which can be used to save
-- and load data into the script.
--
-- This function can either tell you how many cards are in the deck total, or just how
-- many cards there are with a particular property setting
--
--
Arguments:
-- You provide a property name and value (both are strings) which is used to 'filter out' cards that
-- do not have that setting on them. If you want ALL the cards, use "" for the
-- property name and value.
--
--
Values Returned To You:
-- You are given a number which tells you how many cards are in the deck with that
-- property value.
--
--
Example Usage:

local numCardsInDeck = TA_NumCards( "", "" )
local numSpecial = TA_NumCards( "Special", "true" )
TA_Print( "while there are " .. numCardsInDeck .. " cards in the deck, only "
.. numSpecial .. "are special." )

NOTE: There is no standard property called "Special." This was just an example. As the deck style creator, you define what properties your cards have.

------------
--
TA_NthCardId( n, propertyName, propertyValue )
--
-- After calling TA_NumCards(), you can use a value of N between 1 and that returned value
-- to get the 'cardId' of the Nth card in the deck. Note that you should provide the same
-- property name and value to TA_NthCardId() as you did to TA_NumCards() for it to make
-- any sense.
--
--
Arguments:
-- In addition to the property name and value to be used as a filter (see TA_NumCards()), you
-- also provide a value of N which should be between 1 and TA_NumCards() (inclusive)
--
--
Values Returned To You:
-- You will be given a string cardId (looks something like like "00000001_23") which identifies the
-- card at that position in the (filtered) deck. If you provide a bad value of N, then you will get nil,
-- so you should probably check for that.
--
--
Example Usage:

local cardId = TA_NthCardId( 4, "Special", "true" )
if ( cardId ) then

TA_Print( "I guess 4 was a legal value for N" );

end

 

------------
--
TA_GetCardProperty( cardId, propertyName )
--
-- Given a cardId and property name (both are strings), it will return the current value of
-- that property on the specified card in the current game deck. This is not necessarily
-- synchronized for all players (unless you send packets to keep it synchronized)
--
--
Arguments:
-- You provide the cardId (probably from TA_NthCardId() and property name you care about.
--
--
Values Returned To You:
-- You are given the (string) value of that property. Or nil if no such card or property exists.
--
--
Example Usage:

local numMonsters = TA_NumCards( "type", "monster" )
for n=1,numMonsters do

local cardId = TA_NthCardId( n, "type", "monster" )
local monsterName = TA_GetCardProperty( cardId, "Name" )
TA_Print( "Monster #" .. n .. " has the name: " .. monsterName )

end

NOTE: "type" and "Name" are not necessarily standard card properties (ok NAME is!) and are used here purely as an example. For example, a game where you define a type of card to represent a monster.

------------
--
TA_SetCardProperty( cardId, propertyName, propertyValue )
--
-- This lets you change the value for a property on a card in the deck. This only affects
-- the temporary copy of the deck used in the game, and does not permanently alter
-- properties of the moderator's starting deck.
--
--
Arguments:
-- You provide a cardId, a property Name, and a property Value
--
--
Values Returned To You: none
--
--
Example Usage:

-- This monster is a doofus!
TA_SetCardProperty( cardId, "Status", "Doofus" )
-- And also, it's dead!
TA_SetCardProperty( cardId, "RemainingHitPoints", "0" )

NOTE: Changing a card property only happens on the PC which executes the lua script which makes it happen. Unlike WoS, however, all players have a copy of the script and have their event handlers called for the same reasons. Hence you might need to send packets to keep properties in sync, if you care. Usually your game will have most of the logic take place on the moderator's PC only.

In such a case, when you decided the monster was a doofus, you would probably send a packet to all players which implied that, and then the event handler on each player's PC would locally set the property on their own copy of the deck.

------------
--
TA_SetState( stateNumber )
--
-- This lets you command TurnAbout to start some important state or substate. This really needs more
-- documentation than shown here.
--
--
Arguments:
-- You provide a new state value:
-- * 0 - Stop the Game (this is suicide, your script is unloaded, state returns to PICK DECK)
-- * 1 - Join Game (have the current player add themselves to the Join Game list..)
-- * 2 - Start Game (moderator only), end the JOIN GAME state and start the game proper
-- * 3 - No State Please (for example, shuts off the roll dice message which otherwise hangs forever
--
--
Values Returned To You: none
--
--
Example Usage:

-- Game over dude, game over!
TA_SetState( 0 )

------------
--
TA_GetMsec( )
--
-- Fetches the current msec value (using the same clock as used in the TA_OnTick event. Just
-- in case you need to know. Remember: no fair looping until some future msec. You MUST return
-- from your functions as quickly as possible or you will block the game.
--
--
Arguments: none
--
--
Values Returned To You: current msec value
--
--
Example Usage:

-- what msec is it RIGHT NOW?
local msec =
TA_GetMsec( 0 )

Graphics Services

So, you want to write a game which looks as amazing as Warpath, Well of Souls, or Empyrion? (i.e. 256 color 2D), well then here is the graphics support library for YOU! (Um, that was supposed to be sort of tongue and cheek.)

All drawing (rendering, painting, whatever) is done to "Image Buffers" and each image buffer is identified by a unique handle value. Handle zero is the 'main screen' (the area just above the chat window) and is the only image buffer seen by the user. Your job is to fill that image buffer with appropriate graphic goodness, given the primitive 2D, 256 color, rendering commands which follow.

First, however, you must tell TurnAbout that you are interested in being "THE" renderer for your game, so somewhere in your script you must first call TA_SetRenderMode( 1 ) once. (You only have to call it again when you want it to change)

After that, you can render directly to Image Buffer 0 (it won't ever flicker, there is yet another layer of buffering before it is really seen by the user) or render to extra Image Buffers that you create and then copy those image buffers to the main screen (sprite animation, for example).

------------
--
TA_SetRenderMode( mode )
--
-- The display window above the chat area can be rendered in one of several modes. More
-- modes later, I hope.
--
-- Call this function once in your TA_OnLoaded() handler (you can call it at any time you
-- like, of course). TurnAbout will immediately switch to the mode you select
--
--
Arguments:
-- You provide a mode:
-- * 0 - default (TurnAbout Draws what it likes)
-- * 1 - custom (Nothing is drawn except what your script draws)
--
--
Values Returned To You: none
--
--
Example Usage:

function TA_OnLoaded( serNum, modSerNum, width, height )

-- My Game wants to control the graphical display area completely!
TA_SetRenderMode( 1 )

end

 

------------
--
TA_FillSolidRect( handle, left, top, right, bottom, color )
--
-- You would probably be shocked if you knew how often I draw rectangles. This is your basic building
-- block. This function draws a solid color rectangle (quickly) at the pixel coordinates you specify in the
-- image buffer you specify. Use the TA_GetImageSize() function if you have forgotten the dimensions
-- of you Image Buffer.
--
--
Arguments:
-- You provide a handle, 4 numbers defining a rectangle, and a color (see TA_Print() for color format)
-- NOTE: Here the 4 rectangle values are provided as individual numbers, not as a table
--
--
Values Returned To You: none
--
--
Example Usage:

-- draw a red rectangle on the main screen
TA_FillSolidRect( 0, 20, 20, 200, 150, "ff0000" )

 

------------
--
TA_LineTo( handle, x, y, width, color )
--
-- This lets you draw a straight line of the given color to the x,y position (in pixels) of your choice
-- use a line width of