Skip to content
Toby edited this page Sep 8, 2015 · 13 revisions

Introduction

CorsixTH is coded in a mixture of Lua 5.1 and C++, along with a tiny smidgen of C. All high-level logic is written in Lua, and all the C/C++ code is bootstrapping Lua, or providing libraries for Lua code to use. This provides an environment where high-level logic can be written quickly in a modern garbage-collected language, and low-level code which needs to be fast can still be written in C/C++. Other advantages of Lua include:

  • Stack traces whenever an error occurs (stack traces are hard to do in portable C)
  • Much more difficult to cause segmentation faults / memory access violations
  • Easier for non-coders to edit
  • Compiler not required to make changes

Bootstrapping of Lua

When the CorsixTH executable is launched, execution starts in main.cpp's main. This creates a Lua state with standard libraries loaded, transfers control to the Lua C function l_main, and catches any errors.

l_main (still in main.cpp) adds various libraries to package.preload for require to find. Finally, it loads and transfers control to CorsixTH.lua, passing the command line arguments as parameters.

This is the end of the hardcoded initialisation; all further initialisation is performed by Lua code. Execution continues in Lua mode until the application finishes (except for when Lua calls back into C/C++).

CorsixTH.lua redefines the standard dofile function to load from the Lua subdirectory and only do a file a maximum of one time. It proceeds to load Lua/strict.lua, Lua/class.lua, and Lua/app.lua. Finally it creates an instance of the App class, assigns it to the global TheApp, calls setCommandLine and then init on the instance, and ends by calling run.

C/C++ Libraries visible to Lua

Lua 5.1 Standard Libraries

All of the Lua 5.1 standard libraries (basic library, coroutine, string, table, math, io, os, and debug) are available to Lua scripts.

Lua File System

The semi-standard LuaFileSystem library will always be available via require "lfs". This can be used to iterate directories and perform other file system actions which are not available in the standard os or io libraries.

RNC decompression

To decompress the original Theme Hospital data files, the RNC library will always be available via require "rnc".

rnc.decompress(string)

Takes RNC compressed data as a string argument, and returns a string containing decompressed data, or nil and an error message if the input is not RNC compressed, or an error occurred during decomprssion.

SDL

An interface to SDL is always available via require "sdl", and is used to handle events, create windows, and play music.

sdl.init([["audio",]("video",]) [["*"]("timer",]))

Initialises the SDL components specified via string arguments, or all components if "*" is an argument. Returns true on success and false on error.

sdl.getFPS()

If the frame rate is being tracked (which it isn't by default, but it can be by calling sdl.trackFPS), then returns (as an integer) the number of frames rendered in the last 1000 milliseconds. If the frame rate is not being tracked, then nil is returned.

sdl.trackFPS([false])

Enables or disables frame rate tracking.

sdl.limitFPS([false](false])))

If called with no arguments, or true, then frames are only rendered when required (which is the default behaviour if limitFPS is never called). If called with false, then frames are rendered all the time except for when there are events to handle. Should only be called when comparing rendering engines or other similar situations. Note that the DX9 rendering engine is also limited to the screen refresh rate unless CORSIX_TH_DX9_UNLIMITED_FPS is defined in C.

sdl.mainloop(thread)

Waits for events to occur, and calls the given coroutine to handle each one. Also calls the coroutine every 30 milliseconds to handle a timer event, and calls it with a frame event whenever a frame needs to be rendered.

The coroutine should yield true if a repaint is required in response to the event. If the coroutine finishes execution, then mainloop will return, passing the return values of the coroutine. If the coroutine has an error, then mainloop will also return, passing the error message.

sdl.getTicks()

Returns the number of milliseconds since the SDL library initialization. Note that this value wraps if the program runs for more than ~49 days.

sdl.wm.setCaption(string)

Sets the window title to the given string.

sdl.wm.setIconWin32()

On Windows, sets the window icon to the icon contained as a resource in the executable and returns true if successful. On other platforms, or in the event of an error, returns false. Note that this must be called after sdl.video.setMode.

sdl.wm.showCursor([true])

If called with no arguments, or false, then the operating system cursor is hidden. If called with any other value, the operating system cursor is shown.

sdl.audio.loaded

Boolean value which is set to true if audio functions are available, and false is they are not.

sdl.audio.init([frequency [, num_channels [, buffer_size]]](true])))

Initialises the SDL_Mixer library using the given settings. Note that buffer_size must be a power of 2. Returns true, or false and an error string.

sdl.audio.transcodeXmiToMid(xmi_data)

TODO

sdl.audio.loadMusic(midi_data)

TODO

sdl.audio.loadMusicAsync(midi_data, callback)

TODO

sdl.audio.playMusic(music [num_loops](,))

TODO

sdl.audio.stopMusic()

TODO

sdl.audio.pauseMusic()

TODO

sdl.audio.resumeMusic()

TODO

sdl.audio.setMusicVolume(volume)

TODO

Theme Hospital library

A selection of Theme Hospital related classes and functions will always be available via {{{require "TH"}}}.

TH.LoadStrings(string)

Expects the contents of a Theme Hospital strings file as a string argument, and returns a two-dimensional array of strings. The first dimension is the section number (1-based), and the second dimension is the string number within that section (1-based). In the event of an error, false is returned.

TH.map

Wraps the C++ class THMap .

Lua method C++ function(s) Glue function
load THMap::loadFromTHFile l_map_load
size THMap::getWidth , **` THMap::getHeight ** l_map_getsize
getCell THMap::getNode l_map_getcell
getCellFlags THMap::getNode l_map_getcellflags
setCellFlags THMap::getNode l_map_setcellflags
setCell THMap::getNode l_map_setcell
setWallDrawFlags THMap::setAllWallDrawFlags l_map_setwallflags
updateRoomBlueprint THMap::getWidth , THMap::getHeight , THMap::getNodeUnchecked l_map_updateblueprint
updateShadows THMap::updateShadows l_map_updateshadows
{{{markRoom}}} {{{THMap::getWidth}}}, {{{THMap::getHeight}}}, {{{THMap::getNodeUnchecked}}}, {{{THMap::updatePathfinding}}}, {{{THMap::updateShadows}}} {{{l_map_mark_room}}}
{{{unmarkRoom}}} {{{THMap::getWidth}}}, {{{THMap::getHeight}}}, {{{THMap::getNodeUnchecked}}}, {{{THMap::getOriginalNodeUnchecked}}}, {{{THMap::updatePathfinding}}}, {{{THMap::updateShadows}}} {{{l_map_unmark_room}}}
{{{setSheet}}} {{{THMap::setBlockSheet}}} {{{l_map_set_sheet}}}
{{{draw}}} {{{THMap::draw}}} {{{l_map_draw}}}
{{{hitTestObjects}}} {{{THMap::hitTest}}} {{{l_map_hittest}}}
TH.palette

Wraps the C++ class THPalette .

Lua method C++ function(s) Glue function
load THPalette::loadFromTHFile l_palette_load
TH.bitmap

Wraps the C++ class THRawBitmap .

Lua method C++ function(s) Glue function
`` load ` THRawBitmap::loadFromTHFile l_rawbitmap_load
setPalette THRawBitmap::setPalette l_rawbitmap_set_pal
draw THRawBitmap::draw l_rawbitmap_draw
TH.sheet

Wraps the C++ class THSpriteSheet .

Lua method C++ function(s) Glue function
metamethod {{{__len}}} {{{THSpriteSheet::getSpriteCount}}} {{{l_spritesheet_count}}}
{{{load}}} {{{THSpriteSheet::loadFromTHFile}}} {{{l_spritesheet_load}}}
{{{setPalette}}} {{{THSpriteSheet::setPalette}}} {{{l_spritesheet_set_pal}}}
{{{size}}} {{{THSpriteSheet::getSpriteCount}}}, {{{THSpriteSheet::getSpriteSizeUnchecked}}} {{{l_spritesheet_size}}}
{{{draw}}} {{{THSpriteSheet::drawSprite}}} {{{l_spritesheet_draw}}}
TH.font

Wraps the C++ class THFont .

Lua method C++ function(s) Glue function
{{{sizeOf}}} {{{THFont::getTextSize}}} {{{l_font_get_size}}}
{{{setSheet}}} {{{THFont::setSpriteSheet}}} {{{l_font_set_spritesheet}}}
{{{setSeparation}}} {{{THFont::setSeparation}}} {{{l_font_set_sep}}}
{{{draw}}} {{{THFont::getTextSize}}}, {{{THFont::drawText}}} {{{l_font_draw}}}
{{{drawWrapped}}} {{{THFont::drawTextWrapped}}} {{{l_font_draw_wrapped}}}
TH.layers

Wraps the C++ class THLayers_t .

Lua method C++ function(s) Glue function
metamethod {{{__index}}} {{{THLayers_t::iLayerContents}}} {{{l_layers_get}}}
metamethod {{{__newindex}}} {{{THLayers_t::iLayerContents}}} {{{l_layers_set}}}
TH.anims

Wraps the C++ class THAnimationManager .

Lua method C++ function(s) Glue function
{{{load}}} {{{THAnimationManager::loadFromTHFile}}} {{{l_anims_load}}}
{{{setSheet}}} {{{THAnimationManager::setSpriteSheet}}} {{{l_anims_set_spritesheet}}}
{{{getFirstFrame}}} {{{THAnimationManager::getFirstFrame}}} {{{l_anims_getfirst}}}
{{{getNextFrame}}} {{{THAnimationManager::getNextFrame}}} {{{l_anims_getnext}}}
{{{setAnimationGhostPalette}}} {{{THAnimationManager::setAnimationAltPaletteMap}}} {{{l_anims_set_alt_pal}}}
{{{draw}}} {{{THAnimationManager::drawFrame}}} {{{l_anims_draw}}}
TH.animation

Wraps the C++ class THAnimation .

Lua method C++ function(s) Glue function
{{{setAnimation}}} {{{THAnimation::setFlags}}}, {{{THAnimation::setAnimation}}} {{{l_anim_set_anim}}}
{{{setMorph}}} {{{THAnimation::setMorphTarget}}} {{{l_anim_set_morph}}}
{{{setFrame}}} {{{THAnimation::setFrame}}} {{{l_anim_set_frame}}}
{{{getAnimation}}} {{{THAnimation::getAnimation}}} {{{l_anim_get_anim}}}
{{{setTile}}} {{{THAnimation::removeFromTile}}}, {{{THAnimation::attachToTile}}} {{{l_anim_set_tile}}}
{{{getTile}}} {{{THAnimation::getPrevious}}} {{{l_anim_get_tile}}}
{{{setFlag}}} {{{THAnimation::setFlags}}} {{{l_anim_set_flag}}}
{{{setPartialFlag}}} {{{THAnimation::setFlags}}}, {{{THAnimation::getFlags}}} {{{l_anim_set_flag_partial}}}
{{{getFlag}}} {{{THAnimation::getFlags}}} {{{l_anim_get_flag}}}
{{{makeVisible}}} {{{THAnimation::setFlags}}}, {{{THAnimation::getFlags}}} {{{l_anim_make_visible}}}
{{{makeInvisible}}} {{{THAnimation::setFlags}}}, {{{THAnimation::getFlags}}} {{{l_anim_make_invisible}}}
{{{setTag}}} {{{l_anim_set_tag}}}
{{{getTag}}} {{{l_anim_get_tag}}}
{{{setPosition}}} {{{THAnimation::setPosition}}} {{{l_anim_set_position}}}
{{{getPosition}}} {{{THAnimation::getX}}}, {{{THAnimation::getY}}} {{{l_anim_get_position}}}
{{{setSpeed}}} {{{THAnimation::setSpeed}}} {{{l_anim_set_speed}}}
{{{setLayer}}} {{{THAnimation::setLayer}}} {{{l_anim_set_layer}}}
{{{setHitTestResult}}} {{{l_anim_set_hitresult}}}
{{{tick}}} {{{THAnimation::tick}}} {{{l_anim_tick}}}
{{{draw}}} {{{THAnimation::draw}}} {{{l_anim_draw}}}
TH.pathfinder

Wraps the C++ class THPathfinder .

Lua method C++ function(s) Glue function
{{{findDistance}}} {{{THPathfinder::findPath}}}, {{{THPathfinder::getPathLength}}} {{{l_path_distance}}}
{{{isReachableFromHospital}}} {{{THPathfinder::findPathToHospital}}}, {{{THPathfinder::getPathEnd}}} {{{l_path_is_reachable_from_hospital}}}
{{{findPath}}} {{{THPathfinder::findPath}}}, {{{THPathfinder::pushResult}}} {{{l_path_path}}}
{{{findIdleTile}}} {{{THPathfinder::findIdleTile}}}, {{{THPathfinder::getPathEnd}}} {{{l_path_idle}}}
{{{findObject}}} {{{THPathfinder::visitObjects}}} {{{l_path_visit}}}
{{{setMap}}} {{{THPathfinder::setDefaultMap}}} {{{l_path_set_map}}}
TH.cursor

Wraps the C++ class THCursor .

Lua method C++ function(s) Glue function
{{{load}}} {{{THCursor::createFromSprite}}} {{{l_cursor_load}}}
{{{use}}} {{{THCursor::use}}} {{{l_cursor_use}}}
{{{setPosition}}} {{{l_cursor_position}}}
TH.surface

Wraps the C++ class THRenderTarget .

Lua method C++ function(s) Glue function
{{{fillBlack}}} {{{THRenderTarget::fillBlack}}}, {{{THRenderTarget::getLastError}}} {{{l_surface_fill_black}}}
{{{startFrame}}} {{{THRenderTarget::startFrame}}}, {{{THRenderTarget::getLastError}}} {{{l_surface_start_frame}}}
{{{endFrame}}} {{{THRenderTarget::endFrame}}}, {{{THRenderTarget::getLastError}}} {{{l_surface_end_frame}}}
{{{nonOverlapping}}} {{{THRenderTarget::startNonOverlapping}}}, {{{THRenderTarget::finishNonOverlapping}}} {{{l_surface_nonoverlapping}}}
{{{mapRGB}}} {{{THRenderTarget::mapColour}}} {{{l_surface_map}}}
{{{drawRect}}} {{{THRenderTarget::fillRect}}}, {{{THRenderTarget::getLastError}}} {{{l_surface_rect}}}
{{{takeScreenshot}}} {{{THRenderTarget::takeScreenshot}}}, {{{THRenderTarget::getLastError}}} {{{l_surface_screenshot}}}
TH.soundArchive

Wraps the C++ class THSoundArchive .

Lua method C++ function(s) Glue function
metamethod __len {{{THSoundArchive::getSoundCount}}} {{{l_soundarc_count}}}
{{{load}}} {{{THSoundArchive::loadFromTHFile}}} {{{l_soundarc_load}}}
{{{getFilename}}} {{{THSoundArchive::getSoundFilename}}} {{{l_soundarc_filename}}}
{{{getDuration}}} {{{THSoundArchive::getSoundDuration}}} {{{l_soundarc_duration}}}
{{{getFileData}}} {{{THSoundArchive::loadSound}}} {{{l_soundarc_filedata}}}
TH.soundEffects

Wraps the C++ class THSoundEffects .

Lua method C++ function(s) Glue function
setSoundArchive THSoundEffects::setSoundArchive l_soundfx_set_archive
play THSoundEffects::playSound , THSoundEffects::playSoundAt l_soundfx_play
setSoundEffectsOn THSoundEffects::setSoundEffectsOn l_soundfx_sound_effects_on
setSoundVolume THSoundEffects::setSoundEffectsVolume l_soundfx_set_sound_volume
setCamera THSoundEffects::setCamera l_soundfx_set_camera
Clone this wiki locally