--------------------------------------------------------------------------
- Web resources

http://www.lua.org/
http://luaforge.net/projects/luabinaries/ (Lua Compiler builds)
http://luaforge.net/projects/luaedit/ (Editing and Debugging tool)
http://luaforge.net/projects/chunkspy/ (Lua Disassembler)
http://luaforge.net/projects/luadec/ (Lua Decompiler - beta)

--------------------------------------------------------------------------
- Lua Primitive

Opcode: 0x7E
Operands: STR# (2 bytes), index + 1 (2 bytes), flags (2 bytes),
    param 0 (3 bytes), param 1 (3 bytes), param 2 (3 bytes)

STR# is usually 0x130
index = file name of chunk to call (without the extension)
+ 4: flags - 1 = extern, 2 = private, 4 = semi-global, 8 = pass in params
+ 6: param 0 owner
+ 7: param 0 value
+ 9: param 1 owner
+10: param 1 value
+12: param 2 owner
+13: param 2 value

Note: Flag 1 clear = the script is in the description of the indicated string.

--------------------------------------------------------------------------
- File naming

filename.objLua - a chunk that can be called at run time
filename.globalObjLua - a chunk that defines a global Lua object

File names should describe in some detail what the script does (see the
built-in script names for example).

Note: external chunks are all stored in ObjectScripts.package since EP3.

--------------------------------------------------------------------------
- About EPs

The Lua interface is presumably backward compatible, so all functions and
classes should continue to work in later EPs. If your code requires
EP-specific objects or features, you may need to perform that check in
the code. (See nGameState.IsEPInstalled)

EP1 = University
EP2 = Nightlife
EP3 = Open For Business
EP4 = Pets
EP5 = Seasons
EP6 = Bon Voyage

Note that EP2 presents Lua as a kind of experimental feature, so all Lua
hacks should require EP3 or newer. Also note that Family Fun SP and/or
Glamour Life SP can be used in place of EP3, though you won't be able to
use EP3-specific objects or features.

Implementations are noted in [] before each function and class.

--------------------------------------------------------------------------
Global functions
--------------------------------------------------------------------------
- behavior tree environment

[EP2] objectId = GetStackObjectId()

[EP2] value = GetTemp(tempNum)
[EP2] SetTemp(tempNum, value)

[EP2] value = GetLocal(localNum)
[EP2] SetLocal(localNum, value)

[EP2] value = GetTreeParameter(paramNum)
[EP2] SetTreeParameter(paramNum, value)

[EP2] SetScriptReturnValue(bool)

[EP3] value = GetPrimitiveParameter(paramNum) <- from Lua Primitive (see above)

---------------------------------------
- static data

[EP2] string = GetString(instance, index, group) <- group is hash value of name *
[EP2] value = GetConstant(instance, index)

[EP3] value = GetNumConstants(instance)

[EP3] value = GetConstantWithGuid(guid, instance, index)
[EP3] value = GetNumConstantsWithGuid(guid, instance)

[EP3] table = GetConstantsTableByGuid(guid, instance)

* Note that hash values apply to external as well as internal resources. For
example, "Live.package" can be accessed by group 2140586628 (0x7F96C284).

---------------------------------------
- data operators

[EP2] ClearFlag(value, flagNum) <- flagNum is 1 to 16 (i.e. 2^(x-1))
[EP2] SetFlag(value, flagNum)
[EP2] bool = IsFlagSet(value, flagNum)

[EP2] ClearBit(value, bitNum) <- bitNum is same as flagNum
[EP2] SetBit(value, bitNum)
[EP2] bool = IsBitSet(source, bitNum)

[EP2] value = BitShiftRight(value, shiftValue)
[EP2] value = BitShiftLeft(value, shiftValue)

[EP2] value = BitwiseXOr(value, value)
[EP2] value = BitwiseOr(value, value)
[EP2] value = BitwiseAnd(value, value)

[EP3] value = RoundFloat(value) <- used for math.round(value)

---------------------------------------
- object management

[EP2] string = GetObjectName(objectId)

[EP2] objectId = GetRunningObjectId() <- "Me" object
[EP2] objectId = GetRunningOnObjectId() <- current object

[EP2] ObjectAssert(x) <- raise error if x is 0 (i.e. false/nil)
[EP2] ObjectError(string) <- raise error with message

[EP2] guid = CreateObjectGUID(guidHi, guidLo)
[EP3] guidHi, guidLo = SplitObjectGUID(guid)

[EP3] string = GetCatalogName(guid)
[EP3] string = GetCatalogDescription(guid)

[EP3] objectId = GetObjectIdInSlot(objectId, slotNum)

[EP6] groupId = GetObjectGroupID(objectId)

---------------------------------------
- object manipulation

[EP2] value = GetObjectData(objectId, dataIndex) <- see ObjData
[EP2] SetObjectData(objectId, dataIndex, value)

[EP2] value = GetObjectAttribute(objectId, index) <- see STR# 0x100
[EP2] SetObjectAttribute(objectId, index, value)

[EP2] value = GetObjectSemiAttribute(objectId, index) <- see STR# 0x100 (in SemiGlobal)
[EP2] SetObjectSemiAttribute(objectId, index, value)

[EP2] value = GetNumObjectArrays(objectId)

[EP2] array = GetObjectArrayCopy(objectId, arrayNum)
[EP2] SetObjectArray(objectId, arrayNum, array)

[EP2] value = GetObjectDefinitionField(guid, defIndex) <- see ObjDef
[EP3] SetObjectDefinitionField(guid, defIndex, value)

[EP4] MultiplyAdValues(value1 [, value2])

---------------------------------------
- person/neighbor data

[EP2] value = GetPersonData(personId, personDataIndex) <- see PersonData
[EP2] SetPersonData(personId, personDataIndex, value)

[EP2] value = GetNeighborPersonData(neighborId, personDataIndex)
[EP3] SetNeighborPersonData(neighborId, personDataIndex, value)

[EP3] value = GetNeighborData(neighborId, neighborDataIndex) <- see NeighborData

[EP3] value = GetNeighborRelationship(neighborId1, neighborId2, varIndex) <- see RelVars
[EP3] SetNeighborRelationship(neighborId1, neighborId2, varIndex, value)

[EP3] value = GetPersonMotive(personId, motiveIndex) <- see MotiveIndex
[EP3] SetPersonMotive(personId, motiveIndex, value)

---------------------------------------
- misc.

[EP3] value = GetSimulatorGlobal(index) <- see SimulatorGlobal
[EP3] SetSimulatorGlobal(index, value)

[EP3] guid = GetMasterSelector(guid)

[EP3] RunTree(treeName, flags[, param...]) <- flags: 0 = global, not 0 = ?
[EP3] RunTreeWithGuid(guid, treeName[, param...])

[EP3] SetCacheable(bool)
[EP3] SetCacheableTemps(start, end) <- ?

[EP3] OverrideTreeTable(objectId, value1, value2, bool) ?

[EP4] value = KissingPointsUnlock() <- returns < 0 if everything is unlocked
[EP4] value = KissingPointsNumLeft()

--------------------------------------------------------------------------
Predefined environments
--------------------------------------------------------------------------
- nWorld

[EP2] nWorld.MoveObjectToLocation(objectId, tileX, tileY, level)

[EP2] posZ = nWorld.GetTerrainElevationForXY(posX, posY)
[EP2] posZ = nWorld.GetTerrainElevationForObject(objectId)

[EP2] objList = nWorld.GetObjectsOnTile(tileX, tileY, level)
[EP2] posX, posY, posZ = nWorld.GetObjectLocation(objectId)
[EP2] tileX, tileY, level = nWorld.GetObjectTile(objectId)

[EP2] count = nWorld.GetNumLevels()
[EP2] level = nWorld.GetMaxLevel()
[EP2] level = nWorld.GetMinLevel()

[EP2] value = nWorld.GetNumTilesX()
[EP2] value = nWorld.GetNumTilesY()

[EP2] tileX = nWorld.GetMinTileX()
[EP2] tileY = nWorld.GetMinTileY()
[EP2] tileX = nWorld.GetMaxTileX()
[EP2] tileY = nWorld.GetMaxTileY()

[EP2] size = nWorld.GetLotSizeX()
[EP2] size = nWorld.GetLotSizeY()

[EP2] posX = nWorld.GetMinX()
[EP2] posY = nWorld.GetMinY()
[EP2] posX = nWorld.GetMaxX()
[EP2] posY = nWorld.GetMaxY()

[EP2] bool = nWorld.IsOnLot(objectId)

[EP3] bool = nWorld.HasRoof(tileX, tileY, level)
[EP3] bool = nWorld.HasSolidFloor(tileX, tileY, level)

[EP3] tileList = nWorld.GetObjectTiles(objectId)

[EP5] posZ = nWorld.GetWaterElevationForXY(posX, posY)
[EP5] posZ = nWorld.GetWaterElevationForObject(objectId)

[EP5] bool = nWorld.HasSolidGround(tileX, tileY, level)

[EP5] bool = nWorld.HasDriveway(tileX, tileY, level)
[EP5] bool = nWorld.HasStage(tileX, tileY, level) <- ?
[EP5] bool = nWorld.HasStageAny(tileX, tileY, level)

[EP5] bool = nWorld.IsOutsideForWeather(tileX, tileY, level)
[EP5] bool = nWorld.IsLocked(tileX, tileY, level)
[EP5] bool = nWorld.IsLoadBearing(tileX, tileY, level) <- ?

[EP5] bool = nWorld.IsPoolOnTile(tileX, tileY)
[EP5] bool = nWorld.IsWaterOnTile(tileX, tileY)
[EP5] bool = nWorld.IsDeckOnTile(tileX, tileY)
[EP5] bool = nWorld.IsWaterOnEntireTile(tileX, tileY)

[EP5] value = nWorld.GetSnowAccumulationLevelOnTile(tileX, tileY, level)

[EP5] nWorld.FindLocationForObject(objectId, ?) <- ?

[EP5] bool = nWorld.IsWallBetweenPoints(?) <- ?

[EP6] bool = nWorld.IsBeachLocation(tileX, tileY, level)

---------------------------------------
- nGameState

[EP2] state = nGameState.GetCurrentState()
[EP2] bool = nGameState.GetSaveLotEnabled()
[EP2] bool = nGameState.GetTransitionsEnabled()

[EP2] neighborhoodId, houseId = nGameState.GetLotTripInfo()

[EP3] value = nGameState.GetProperty(propName)
[EP3] nGameState.SetProperty(propName, value)

[EP3] nGameState (properties):
    luaLotValue, luaBusinessAwardLotName, luaBusinessAwardOwnerName,
    luaObjectPrice, luaObjectValue, luaDialogString,
    maxTotalSims, maxTotalHumans, maxTotalPets, PetsFreeWill <- any xProp configs/cheats

[EP3] bool = nGameState.IsEPInstalled(epNum) <- epNum: 1 = EP1, 2 = EP2 etc.
[EP3] list = nGameState.GetInstalledEps()

---------------------------------------
- nMessaging

[EP3] nMessaging.PostMessage(gameMessage [, arg...]) <- ?
[EP3] nMessaging.SubscribeMessage(objectId, gameMessage, treeName) <- treeName = name of handler
[EP3] nMessaging.UnsubscribeMessage(objectId, gameMessage) <- ?

(messages):
    kMsgImposterUpdateNeeded = 221,
    init_reward_points = 1355356298,
    badge_gain_level = 2424924040,
    set_learning_level = 4054578884

---------------------------------------
- nUI

[EP2] nUI.ShowTextNotification(string) <- unused (?)
[EP2] nUI.DebugTNS(string) <- unused (?)

[EP3] bool = nUI.InvalidateSimThumbnail(guid)

[EP4] nUI.OpenProgressDialog(uiInstance) <- see ui.package
[EP4] nUI.CloseProgressDialog()
[EP4] nUI.ShowProgressDialogControl(uiId, bool)

---------------------------------------
- nBusiness

[EP3] bool = nBusiness.LotHasBusiness(lotId)
[EP3] nBusiness.CreateBusiness()
[EP3] nBusiness.RemoveBusiness()

--------------------------------------------------------------------------
Cached classes
--------------------------------------------------------------------------
- CachedNeighbor

[EP2] cNeighbor = CachedNeighbor.new(neighborId)

[EP2] guid = cNeighbor:getGUID()

[EP2] value = cNeighbor:getPersonData(index) <- see PersonData
[EP2] cNeighbor:setPersonData(index, value)

[EP2] value = cNeighbor:getOutfitProperty(outfitIndex, outfitPropIndex)

[EP3] string = cNeighbor:getName() <- given name
[EP3] cNeighbor:setName(string)
[EP3] string = cNeighbor:getSurname() <- this individual's family name
[EP3] cNeighbor:setSurname(string)
[EP3] string = cNeighbor:getBio()
[EP3] cNeighbor:setBio(string)

[EP3] string = cNeighbor:getFullName()

---------------------------------------
- CachedPerson

[EP2] cPerson = CachedPerson.new(personId)

[EP2] guid = cPerson:getGuid()

[EP2] value = cPerson:getPersonData(personDataName) <- see PersonData
[EP2] cPerson:setPersonData(personDataName, value)

[EP2] value = cPerson:getNumQueuedInteractions()
[EP2] objectId = cPerson:getQueuedInteractionObjectId(qIndex)
[EP2] ciIndex = cPerson:getQueuedInteractionId(qIndex)

[EP3] value = cPerson:getMotive(index) <- see MotiveIndex
[EP3] cPerson:setMotive(index, value)

[EP3] bool = cPerson:cancelQueuedInteraction(qIndex)

[EP6] value = cPerson:getNumSubQueuedInteractions()
[EP6] objectId = cPerson:getQueuedSubInteractionObjectId(qIndex)
[EP6] ciIndex = cPerson:getQueuedSubInteractionId(qIndex)

[EP6] bool = cPerson:isAccessibleRoom(roomId)
[EP6] cPerson:unlockVacationCollectible(index)

---------------------------------------
- CachedFamily

[EP3] cFamily = CachedFamily.new(familyId)

[EP3] familyId = cFamily:getId()

[EP3] string = cFamily:getName()

[EP3] value = cFamily:getNumMembers()
[EP3] list = cFamily:getMembers() <- list of neighborIds
[EP3] bool = cFamily:isNeighborInFamily(neighborId)

[EP3] lotId = cFamily:getCurrentLotId()
[EP3] lotId = cFamily:getLotId()

[EP3] value = cFamily:getLastSavedFunds()
[EP3] value = cFamily:getFunds()

[EP5] cFamily:addMemberClothing(neighborId)

[EP6] lotId = cFamily:getVacationLotId()
[EP6] cFamily:setVacationLotId(lotId)

--------------------------------------------------------------------------
Non-cached classes
--------------------------------------------------------------------------
- ObjectDefinition

[EP2] objDefinition = ObjectDefinition.new()

[EP2] value = objDefinition:getField(index) <-  see ObjDef
[EP2] value = objDefinition:get32BitField(index) ?

--------------------------------------------------------------------------
- ObjectManager

[EP2] GlobalObjManager = ObjectManager.new() <- this is defined in Global.lua

[EP2] objList = GlobalObjManager:getObjectIds(query)
[EP2] personList = GlobalObjManager:getPersonIds()
[EP2] neighborList = GlobalObjManager:getNeighborIds()

[EP2] bool = GlobalObjManager:verifyNeighborId(neighborId)
[EP2] bool = GlobalObjManager:verifyObjectId(objectId)

[EP2] guidList = GlobalObjManager:getObjectDefinitionGUIDs()

[EP2] bool = GlobalObjManager:isWallBetweenObjects(objectId1, objectId2)
[EP2] value = GlobalObjManager:getDirectionToObject(objectId1, objectId2)
[EP2] value = GlobalObjManager:getDistanceBetweenObjects(objectId1, objectId2)

[EP2] guid = GlobalObjManager:getObjectGUIDFromObjectId(objectId)
[EP2] personId = GlobalObjManager:getPersonIdFromGUID(guid)
[EP2] objectId = GlobalObjManager:getObjectIdFromGUID(guid)

[EP3] bool = GlobalObjManager:isValidObjectGUID(guid)

[EP3] GlobalObjManager (query values):
    kQuery_All = 0, kQuery_ByGUID = 1, kQuery_ForPartsofMultiTileObject = 2,
    kQuery_ByObjectDataField = 3, kQuery_ByAccessableRooms = 4,
    kQuery_ByAccessibleRooms = 4

[EP5] objectId = GlobalObjManager:createNewObject(guid)
[EP5] GlobalObjManager:removeObjectInstance(objectId)

---------------------------------------
- NeighborhoodManager

[EP2] xNeighborhoodManager = NeighborhoodManager.new()

[EP2] neighborhoodList = xNeighborhoodManager:getNeighborhoodIds()

[EP2] count = xNeighborhoodManager:getNumNeighborhoodsOfType(type) <- see NeighborhoodType
[EP2] type = xNeighborhoodManager:getNeighborhoodType(neighborhoodId)
[EP2] type = xNeighborhoodManager:getCurrentNeighborhoodType()

[EP3] neighborhoodId = xNeighborhoodManager:getNeighborhoodIdFromLotId(lotId)
[EP3] lotList = xNeighborhoodManager:getLotIdsInAllNeighborhoods()
[EP3] lotList = xNeighborhoodManager:getLotIdsByNeighborhood(neighborhoodId)

[EP3] bool = xNeighborhoodManager:isValidNeighborhood(neighborhoodId)

[EP5] season = xNeighborhoodManager:getSeasonOfQuadrant(neighborhoodId, quadrant) <- see Seasons

---------------------------------------
- NeighborDataTable

[EP3] xNeighborDataTable = NeighborDataTable.new()

[EP3] xNeighborDataTable:setTableName() <- ?
[EP3] xNeighborDataTable:getTableName() <- ?

[EP3] bool = xNeighborDataTable:hasTableValue(tableId, key)
[EP3] xNeighborDataTable:setTableValue(tableId, key, value)
[EP3] value = xNeighborDataTable:getTableValue(tableId, key)
[EP3] xNeighborDataTable:removeTableValue(tableId, key)

[EP3] xNeighborDataTable:setTableFromCopy() <- ?

[EP3] xNeighborDataTable:getTableCopy() <- ?
[EP3] xNeighborDataTable:getTableValues() <- ?
[EP3] xNeighborDataTable:getTableKeys() <- ?
[EP3] xNeighborDataTable:getTableIds() <- ?

[EP3] xNeighborDataTable:removeAll() <- ?

[EP3] bool = xNeighborDataTable:hasTable(tableId)
[EP3] xNeighborDataTable:clearTable() <- ?
[EP3] xNeighborDataTable:removeTable() <- ?
[EP3] xNeighborDataTable:newTable(tableId, neighborId)

[EP4] xNeighborDataTable:setTableValueAsInt(tableId, key, value)

---------------------------------------
- ObjectDataTable

[EP3] xObjectDataTable = ObjectDataTable.new()

[EP3] xObjectDataTable:setTableName() <- ?
[EP3] xObjectDataTable:getTableName() <- ?

[EP3] bool = xObjectDataTable:hasTableValue(tableId, key)
[EP3] xObjectDataTable:setTableValue(tableId, key, value)
[EP3] value = xObjectDataTable:getTableValue(tableId, key)
[EP3] xObjectDataTable:removeTableValue(tableId, key)

[EP3] xObjectDataTable:setTableFromCopy() <- ?

[EP3] xObjectDataTable:getTableCopy() <- ?
[EP3] xObjectDataTable:getTableValues() <- ?
[EP3] xObjectDataTable:getTableKeys() <- ?
[EP3] xObjectDataTable:getTableIds() <- ?

[EP3] xObjectDataTable:removeAll() <- ?

[EP3] bool = xObjectDataTable:hasTable(tableId)
[EP3] xObjectDataTable:clearTable() <- ?
[EP3] xObjectDataTable:removeTable() <- ?
[EP3] xObjectDataTable:newTable(tableId, objectId)

[EP4] xObjectDataTable:setTableValueAsInt(tableId, key, value)

---------------------------------------
- BusinessInfo

[EP3] xBusinessInfo = BusinessInfo.new(lotId)

[EP3] flags = xBusinessInfo:getBusinessFlags()
[EP3] xBusinessInfo:setBusinessFlags(flags)

[EP3] value = xBusinessInfo:getWholesaleMultiplier()
[EP3] xBusinessInfo:setWholesaleMultiplier(value)

[EP3] bool = xBusinessInfo:isEmployee(neighborId)
[EP3] xBusinessInfo:addEmployee(neighborId)
[EP3] xBusinessInfo:removeEmployee(neighborId)

[EP3] dataList = xBusinessInfo:getAllEmployeeData()
[EP3] idList = xBusinessInfo:getEmployeeIds()
[EP3] neighborId = xBusinessInfo:getEmployeeDataById(id)

[EP3] bool = xBusinessInfo:isCustomer(neighborId)
[EP3] xBusinessInfo:addCustomer(neighborId)
[EP3] xBusinessInfo:removeCustomer(neighborId)

[EP3] dataList = xBusinessInfo:getAllCustomerData()
[EP3] idList = xBusinessInfo:getCustomerIds()
[EP3] neighborId = xBusinessInfo:getCustomerDataById(id)

[EP3] list = xBusinessInfo:getTotals()
[EP3] value = xBusinessInfo:getTotalProfit()

[EP3] list = xBusinessInfo:getAllPnLData()
[EP3] data = xBusinessInfo:getCurrentPnLData()

[EP3] value = xBusinessInfo:getRemoteIncomeDecay()
[EP3] xBusinessInfo:setRemoteIncomeDecay(value)

[EP3] value = xBusinessInfo:getHighestRank()
[EP3] xBusinessInfo:setHighestRank(value)
[EP3] value = xBusinessInfo:getRank()
[EP3] xBusinessInfo:setRank(value)

---------------------------------------
- Inventory

[EP2] xInventory = Inventory.new(type[, id]) <- see gInventoryTypes

[EP2] tokenList = xInventory:getTokens()
[EP2] tokenList = xInventory:getTokensByGUID(guid)
[EP2] tokenList = xInventory:getTokensByFlags(flag) <- see gTokenFlags

[EP2] token = xInventory:findToken(guid)

[EP2] count = xInventory:countTokens()
[EP2] count = xInventory:countTokensByGUID(guid) <- ?
[EP2] count = xInventory:countTokensByFlags(flag) <- ?

[EP2] xInventory:removeTokensMarkedForDeletion()
[EP2] xInventory:removeTokensOfGUID(guid) <- ?

[EP2] token = xInventory:addToken(guid)

[EP3] token = xInventory:getTokenAtIndex(index)

[EP3] token = xInventory:copyToken(index, type[, id]) <- ?
[EP3] xInventory:copyCountedToken(?) <- ?

[EP3] guidList = xInventory:getTokenArchiveGUIDS(index)

[EP5] tokenList = xInventory:getSingularTokens()
[EP5] tokenList = xInventory:getSingularTokensByGUID(guid)
[EP5] tokenList = xInventory:getSingularTokensByFlags(flag)
[EP5] tokenList = xInventory:getSingularTokensByCategory(category) <- see gTokenCategories

[EP5] tokenList = xInventory:getCountedTokens()
[EP5] tokenList = xInventory:getCountedTokensByGUID(guid)
[EP5] tokenList = xInventory:getCountedTokensByFlags(flag)

[EP5] token = xInventory:addTokenWithCategory(guid, category) <- ?

---------------------------------------
- Token

[EP2] value = Token:countProperties()
[EP2] Token:clearProperties()  <- ?
[EP2] value = Token:getProperty(index)
[EP2] Token:setProperty(index, value)
[EP2] list = Token:getPropertiesCopy()
[EP2] Token:setProperties(list)
[EP2] value = Token:popProperty() <- ?
[EP2] Token:pushProperty(value) <- ?

[EP5] Token:setCategory(category) <- see gTokenCategories

---------------------------------------
- Neighborhood

[EP3] xNeighborhood = Neighborhood.new()

[EP3] bool = xNeighborhood:isValidLot(lotId)
[EP3] value = xNeighborhood:getLotValue(lotId)

[EP3] neighborId = xNeighborhood:getLotOwner(lotId)
[EP3] setLotOwner(lotId, neighborId)

[EP3] type = xNeighborhood:getLotType(lotId)
[EP3] string = xNeighborhood:getLotName(lotId)

[EP3] list = xNeighborhood:getLotIds() <- ?
[EP3] list = xNeighborhood:getLotIdsInAllNeighborhoods()
[EP3] hoodId = xNeighborhood:getNeighborhoodIdFromLotId(lotId)

---------------------------------------
- WeatherInfo

[EP5] xWeatherInfo = WeatherInfo.new()

[EP5] season = xWeatherInfo:getSeason() <- see Seasons
[EP5] xWeatherInfo:setSeason(season)
[EP5] quadrant = xWeatherInfo:getSeasonQuadrant()
[EP5] xWeatherInfo:setSeasonQuadrant(quadrant)
[EP5] value = xWeatherInfo:getSeasonDaysStandard()
[EP5] xWeatherInfo:setSeasonDaysStandard(value)
[EP5] value = xWeatherInfo:getSeasonDaysAdditional()
[EP5] xWeatherInfo:setSeasonDaysAdditional(value)
[EP5] value = xWeatherInfo:getPrecipitationType() <- see PrecipitationType
[EP5] xWeatherInfo:setPrecipitationType(value)
[EP5] value = xWeatherInfo:getPrecipitationIntensity() <- see PrecipitationIntensity
[EP5] xWeatherInfo:setPrecipitationIntensity(value)
[EP5] value = xWeatherInfo:getAccumulationLevel() <- see AccumulationLevel
[EP5] xWeatherInfo:setAccumulationLevel(value)
[EP5] value = xWeatherInfo:getAccumulationType() <- same as PrecipitationType
[EP5] xWeatherInfo:setAccumulationType(value)
[EP5] value = xWeatherInfo:getTemperature() <- +/- 100
[EP5] xWeatherInfo:setTemperature(value)
[EP5] value = xWeatherInfo:getSkyClarity() <- see SkyClarity
[EP5] xWeatherInfo:setSkyClarity(value)
[EP5] value = xWeatherInfo:getPondFrozenState() <- see PondFrozenState
[EP5] xWeatherInfo:setPondFrozenState(value)
[EP5] bool = xWeatherInfo:isCameraIndoors()

--------------------------------------------------------------------------
Scripted Globals
--------------------------------------------------------------------------
- Attraction

[EP2] count = CountSetBits(value)
[EP2] result = GetPersonalityDifferencePoints(value1, value2)
[EP2] score = CalculateTurnOnOffScore(cPerson1, cPerson2)
[EP3] count = CalculateTurnOnOffCount(cPerson1, cPerson2)

- Fishing

[EP5] value = fmod(dividend, divisor)

- Global

[EP2] GlobalObjManager = ObjectManager.new()
[EP3] math.round = RoundFloat()
[EP3] TempTable = {}
[EP3] TempN = 0

- Math

[EP6] bool = Math.InRange(bound1, bound2, value, orEqual)

- QuickSort

[EP3] Quicksort(arrayNum, arrayList, startIndex, stopIndex)
[EP3] Swap(arrayList, index1, index2)

--------------------------------------------------------------------------
- Scripted Predefined Environments
--------------------------------------------------------------------------
- Badges

[EP3] value = nBadges.getBadgeLevel(neighborId, badgeIdName) <- see nBadges.BadgeIds

- BusinessLotsController

[EP3] nBusinessLotsController.removeEmployeeJobData(neighborId, lotId)
[EP3] nBusinessLotsController.cleanupLot(lotId)
[EP3] nBusinessLotsController.cleanupNeighborhood(neighborhoodId)

- ConnectedColumns

[EP2] objectId = ConnectedColumns.FindMarkerObjectID()
[EP2] bool = ConnectedColumns.MarkerForTheseColumns(objectId, columnId1, columnId2)
[EP2] bool = ConnectedColumns.CanConnectDir(columnId1, columnId2, tileX, tileY, level)
[EP2] objectId = ConnectedColumns.ConnectByDir(objectId1, guid, direction, objectId2, posZ)
[EP3] bool = ConnectedColumns.FindObjectID(objectId2, tileX1, tileY1, level, objectId1, tileX2, tileY2)
[EP3] ConnectedColumns.ConnectSingle(objectId1, guid, objectId2, posZ)

- DisablingFunctions

[EP3] nDisabled.DisplayDisableContainedObjects(objectId)
[EP3] nDisabled.DisplayEnableContainedObjects(objectId)
[EP3] nDisabled.DisplayDisableObject(objectId)
[EP3] nDisabled.DisplayEnableObject(objectId)

- DrivewayGlobals

[EP2] objectId = Driveway.FindDrivewayTile(objList, subIndex)
[EP2] objectId = Driveway.GetDrivewayOnTile(tileX, tileY, level, subIndex)
[EP2] objectId = Driveway.FindAdjacentDriveway(objectId, subIndex)
[EP2] objectId = Driveway.CheckBackwards(objList)
[EP2] objectId = Driveway.CheckForwards(objList)

- EmployeeManagementController

[EP3] bool = nEmployeeManagement.isInArray(value, array [, limit])
[EP3] bool = nEmployeeManagement.isPerson(objectId)
[EP3] array = nEmployeeManagement.stripForSaleFromArray(array)
[EP3] bool = nEmployeeManagement.isManager(personId, lotId)
[EP3] bool = nEmployeeManagement.isOwner(neighborId, lotId)
[EP3] familyId = nEmployeeManagement.getOwnerFamily(lotId)
[EP3] bool = nEmployeeManagement.isOwnerOrFamily(personId, lotId)
[EP3] bool = nEmployeeManagement.isEmployee(personId, lotId)
[EP3] bool = nEmployeeManagement.shouldSimPerformAI(personId, lotId)
[EP3] bool = nEmployeeManagement.isEmployeeWorking(personId)
[EP3] bool = nEmployeeManagement.isJobBeingPerformed(assignmentId, unused)
[EP3] bool = nEmployeeManagement.sortManagers(personId1, personId2)
[EP3] personId = nEmployeeManagement.getBestManager(list1, list2)
[EP3] bool = nEmployeeManagement.sortJobObjects(jobObj1, jobObj2)
[EP3] jobObj = nEmployeeManagement.jobObjectData(unused)
[EP3] objectId = nEmployeeManagement.getBestObjectForJob(jobId, objectId)
[EP3] bool = nEmployeeManagement.canSimCraftObject(arg, arg, arg, arg, arg)
[EP3] bool = nEmployeeManagement.sortCraftables(craftObj1, craftObj2)
[EP3] craftObj = nEmployeeManagement.getBestCraftableObjectForJob(jobId, neighborId)
[EP3] bool = nEmployeeManagement.isValidRestaurant()
[EP3] bool = nEmployeeManagement.isSimDining(neighborId)
[EP3] value = nEmployeeManagement.getAverageMotive(motiveIndex, notJustVisitors)
[EP3] value = nEmployeeManagement.getJobSeverity(jobId)
[EP3] value = nEmployeeManagement.getJobPriority(jobId)
[EP3] jobList = nEmployeeManagement.getAvailableJobsByPriority()
[EP3] bool = nEmployeeManagement.sortEmployees(arg, arg)
[EP3] list = nEmployeeManagement.getBestEmployeesForJob(jobId, list, list, lotId)

- Fishing

[EP5] Fishing.GetReelInTile(objectId, direction)
[EP5] bool = Fishing.CanFishHere(tileX, tileY [, level])
[EP5] bool = Fishing.EligibleForEmitter(posX, posY [, posZ])
[EP5] Fishing.PlaceFXEmitters()
[EP5] Fishing.ChooseFishType(badgeLevel, recastType, lureType)
[EP5] bool = Fishing.IsValidDestination(object1, object2)

- GarageGlobals

[EP2] Garage.FindGarageTile(drivewayList, value)

- HidingFunctions

[EP3] nHidden.HideContainedObjects(objectId)
[EP3] nHidden.ShowContainedObjects(objectId)

- Inventory

[EP3] tokenList, count = nInventory.GetShoppingTokens(neighborId)
[EP3] tokenList, count = nInventory.GetSimShoppingTokens(neighborId)
[EP3] value = nInventory.GetShoppingAmount(tokenList)
[EP3] value = nInventory.CanAffordShoppingInventory(personId, tokenList)
[EP3] value = nInventory.GetWholesaleAmount(tokenList)
[EP3] count = nInventory.GetShoppingTokenCount(neighborId)
[EP3] nInventory.AddTokensAsPurchase(neighborId, tokenList)
[EP3] nInventory.UpdateRemoteBusinessData(lotId, familyId)
[EP5] nInventory.MakeTokenLeftover(index)

- Motives

[EP4] nMotives.GetBaseValue(index, age, species, decay)
[EP4] value = nMotives.GetBonus(index, persondata, species, personId, decay)

- NPC Constants

[EP2] guid = NPCTypeToGUID[type]
[EP2] guid = NPCTypeToOutfitGUID[type]
[EP3] bool = NPCIsValidVisitor[guid]

- PetFunctions

[EP4] objectList, count = nPet.FindPetPeeObjects(personId, arg)
[EP4] objectId, distance = nPet.FindClosestPee(personId)
[EP4] count = nPet.CountPeeLocations(personId)
[EP4] objectList = nPet.FindPeeTargetsInRange(personId)
[EP4] objectId = nPet.FindObjectToPeeOn(personId)

- Poker (EP3+)

[EP3] bool = Poker.SimpleSort(value1, value2)
[EP3] Poker.TrueClear(list)
[EP3] count = Poker.hasX(list, match, resultList)
[EP3] bool = Poker.Straight(list, resultList, index)
[EP3] bool = Poker.Flush(list, resultList, index)
[EP3] value = Poker.GetBestOdds(value, index)

- Puddle

[EP5] bool = Puddle.IsOnTerrain(objectId)
[EP5] bool = Puddle.DoesAdjacentPuddleExist(objectId)
[EP5] bool = Puddle.IsSurroundedByPuddles(objectId)
[EP5] bool = Puddle.AnyPuddlesOnTile(tileX, tileY, level)
[EP5] objectId = Puddle.GetPuddleOnTile(tileX, tileY, level)
[EP5] array = Puddle.FillArrayWithAdjacentPuddles(objectId, array)
[EP5] array = Puddle.FillArray_FillTile(tileX, tileY, level, objectId, array)

- Shop2Functions

[EP3] value = Shop2.OwnerEmployeeMultBonus(personId)
[EP3] value = Shop2.GetAverageMotiveBonus(table, index)
[EP3] value = Shop2.GetLotAverageMotiveScore(objectList, index)

- Time (see below for class)

[EP3] xTime = nTime.Now()
[EP3] table = nTime.NowTable()

- Vacation

[EP6] index = gVacationParty.GenerateVacationParty(inventory, familyId, initialLength)
[EP6] index = gVacationParty.AddSimNIDToVacationParty(neighborId, inventory, familyId, isGuest)
[EP6] index = gVacationParty.RemoveSimNIDFromVacationToken(token, neighborId, isGuest)
[EP6] index = gVacationParty.FindTokenIndexByVacationPartyID(inventory, familyId)
[EP6] index = gVacationParty.GetPropertyIndexForSimNID(token, neighborId)
[EP6] list = gVacationParty.GetMainPartySimNIDs(token)
[EP6] value = gVacationParty.GetVacationPartyTokenProperty(inventory, familyId, index)
[EP6] gVacationParty.SetVacationPartyTokenProperty(inventory, familyId, index, value)

--------------------------------------------------------------------------
Scripted Classes
--------------------------------------------------------------------------
- Neighbor

[EP2] xn = Neighbor.new(neighborId)
[EP2] value = xn:getPersonData(index)
[EP3] value = xn:GetLivePersonData(index)
[EP3] value = xn:GetNeighborData(index)
[EP3] personId = xn:GetObjectID()
[EP3] bool = xn:IsAlive()
[EP3] bool = xn:IsScheduled()
[EP3] bool = xn:IsTownie()
[EP3] bool = xn:IsServiceNPC()
[EP3] bool = xn:IsKnownByCurrentFamily()
[EP3] bool = xn:IsYoungAdult()
[EP3] bool = xn:IsDownTownie()
[EP4] bool = xn:IsPet()

- NeighborDataTable

[EP3] xGNDT = GenericNeighborDataTable.new(sim, tableId[, newTable]) <- see gNeighborDataTableID
[EP3] xGNDT:SetProperty(key, value)
[EP3] value = xGNDT:GetProperty(key)
[EP3] xGNDT:RemoveProperty(key)
[EP3] bool = xGNDT:HasProperty(key)
[EP4] xGNDT:SetPropertyAsInt(key, value)

- ObjectDataTable

[EP3] xGDT = GenericDataTable.new(obj, tableId[, newTable]) <- see gObjectDataTableID
[EP3] xGDT:SetProperty(key, value)
[EP3] value = xGDT:GetProperty(key)
[EP3] xGDT:RemoveProperty(key)
[EP3] bool = xGDT:HasProperty(key)
[EP4] xGDT:SetPropertyAsInt(key, value)

- Time

[EP3] xTime = nTime.Time.new(year, month, day, hour, minute, second)
[EP3] value = xTime:GetMonths()
[EP3] value = xTime:GetDays()
[EP3] value = xTime:GetHours()
[EP3] value = xTime:GetMinutes()
[EP3] value = xTime:GetSeconds()
[EP3] value = xTime:GetTicks()
[EP3] bool = xTime:IsValid()
[EP3] xTime:Reduce() <- check values for overflow, increment as needed
[EP3] xTime = xTime:__sub(xTime) <- overrides sub operator

--------------------------------------------------------------------------
Global tables
--------------------------------------------------------------------------

[EP5] AccumulationLevel:
    None, Light, Heavy

[EP2] Aspiration:
    1 = 1, 2 = 2, 4 = 3, 8 = 4, 16 = 5, 32 = 6, 64 = 7, 128 = 8, 256 = 9

[EP3] GenericDataTable.Bandatron:
    "Current Points", Mood, Hunger, Comfort, Bladder, Energy, Fun,
    Social, Hygiene, Environment, Shopping, Cost

[EP3] GenericDataTable.BusinessAwardTable:
    "Lot Name", "Owner Name"

[EP4] GenericDataTable.MostRecentLearnedBehavior:
    GUID, Time

[EP3] GenericDataTable.SalesTable:
    "For-Sale Price", "Object Value", "Object Name", "Object Description",
    "Object Creator", "Original Price", "Force Good Deal"

[EP3] gHiddenFlags:
    "Hide Models", "Hide Sounds", "Hide Effects", "Hide Attached Lights",
    "Hide Vox", "Hide Because Contained"

[EP5] gInventoryTypes:
    1 = Inventory.kTypeGlobal, 2 = Inventory.kTypeLot, 3 = Inventory.kTypeFamily,
    4 = Inventory.kTypeNeighbor, 5 = Inventory.kTypeGameWide

[EP6] gLotZoningType:
    residential, community, dorm, fraternity, "secret society",
    hotel, vacationSecretLot

[EP3/4] gNeighborDataTableID:
    "Business Rewards", Tokens,
    / "Learned Behaviors", "Lycanthropy Saved Traits"

[EP3/4] gObjectDataTableID:
    "Sales Info", "Bandatron Customer", "Customer Info", Tokens,
    "Business Award Info",
    / "Pet Ownership", "Most Recent Learned Behavior"

[EP3] gRemoteBusinessProps:
    "Token GUID", "kRemoteBusinessInvCategory", "Inv Category", "Lot ID",
    "Has Been Visited?", "Has Manager?", "Amount Div", "Amount Mod",
    "Times Delivered", "Has Been Called?", "Times Called", "Business Rank",
    "Call Time"

[EP3] gShoppingTokenProps:
    "Neighbor ID", "Dollar Amount Div", "Dollar Amount Mod", "Wholesale Cost Div",
    "Wholesale Cost Mod", "Special Flag", "Extra Data 2"

[EP5/6] gTokenCategories:
    None, Leftovers,
    / VacationPartyInfo

[EP5] gTokenFlags:
    1 = InventoryToken.kFlagVisible, 2 = InventoryToken.kFlagMemory,
    3 = InventoryToken.kFlagMarkedForDeletion, 4 = InventoryToken.kFlagShopping

[EP3/5/6] Messages:
    "Business Info Updated", "Live Mode Changed",
    / "Season Changed", "Update Motive Panel", "UI Mode Set",
    / "EnableSave"

[EP3] MotiveIndex:
    Shopping, "Scratch/Chew", Mood, Energy, Comfort, Hunger, Hygiene,
    Bladder, "Sleep State", Environment, Social, Fun

[EP3] nBadges.BadgeIds:
    "Toy Making", "Flower Arranging", Robotery, Sales, "Cash Register", Stocking,
    Cosmetology, Security

[EP3] nBadges.BadgeTokenGUID:
    "Cash Register", Cosmetology, "Flower Arranging", Robotery, Sales,
    Security, Stocking, "Toy Making", "Boost Badge"

[EP3] NeighborData:
    "person instance id", "belongs in house", "person age",
    "relationship raw score", "relationship score", "friend count",
    "house number", "has telephone", "has baby", "family friend count",
    "has Computer"

[EP3/6] NeighborhoodType:
    unknown, primary, university, downtown, suburb,
    / asia, mountains, tropics, unknown

[EP3] nFood.CookTypes:
    undefined, "Bake - Toaster Oven", "Bake - Oven", "Microwave",
    "Fry - Stovetop", "Simmer - Stovetop", "Flambe", "Fry/Bake", "Bake/Flambe",
    "Grill - Poke'n'Turn", "Grill - Slow", unused, "unused 12", "unused 13",
    "unused 14", "unused 15", "unused 16"

[EP3] nFood.MenuTimeFlags:
    undefined, Breakfast, Lunch, Dinner

[EP3] nFood.MenuTimes:
    "Breakfast Hour", "Breakfast Minute", "Lunch Hour", "Lunch Minute",
    "Dinner Hour", "Dinner Minute"

[EP3] nFood.MenuTypes:
    undefined, Snack, "Serve Snack", Meal, "Serve Meal", Grill,
    "Serve Grill", Dessert, "Serve Dessert"

[EP3] nFood.ModelStates:
    "Ingredients Tray", "In Hand", Counter, Dish, "Dish - Group",
    "Bake Pan", "Bake Pan - Group", "Fry Pan", "Large Pot", "Mix Bowl",
    "Toaster Tray", "Toaster Tray - Group", Stove, Grill, "Toaster Oven",
    Microwave, "Food Processor", Fridge

[EP3] nFood.PrepTypes:
    undefined, "Cereal Pour", Chop, "unused (Marinate)", Mix,
    Pattyform, "unused (Pie Make)", Sandwich, Season, Stuff,
    "Chop/Mix", "Chop/Season", "Chop/Stuff", "unused (Chop/Mix/Piemake)",
    "unused 14", "unused 15", "unused 16"

[EP3] nFood.ReachTypes:
    Ingredients, Drink, "Bag Snack", "Food Dish"

[EP3] nFood.SemiAttributes:
    State, "Food Pts - Original", "Food Pts - Current", "Type (Single/Group)",
    "Prep Type", "Cook Types", "Menu Type Flags", "Menu Time Availability",
    "Fridge Reach Type - Single", "Stage Progress", "Obj Quality",
    "Food Pts - Max Possible", "Eat Type", "Group Meal Serving Count",
    "Chef Ngh ID", "Obj ID\tPrep/Cook Obj ID", "Obj Time Modifier",
    "State Flags", "Birth Year", "Birth Month", "Birth Day","Birth Hour",
    "Birth Minute", "Chef Skill", "Text Notification ID", "Menu ID",
    "Fridge Reach Type - Group", "Meal ID", "Owner ID", "Debug?",
    "Preferred Cook Obj ID", "Preferred Cook Obj GUID 1", "Preferred Cook Obj GUID 2",
    "Original Chef Ngh ID", "Cook Type - Chosen", "Cook Types - Failed"

[EP3] nFood.SemiTuning:
    "Std Lockout Count", "Fixed Prep Pt %", "Fixed Cook Pt %", "Fixed Prep Time %",
    "Fixed Cook Time %", "Skill for AutoPush/Balloon", "High Skill % >=",
    "Med Skill % >=", "Fitness Inc per Pt over 100", "Cook Time before Failure %",
    "Fail Probability - High", "Fail Probability - Med", "Fail Probability - Low",
    "Food $/Units - $", "Food $/Units - Units", "Fail Probability - Fire %",
    "crapness for spoiled", "Restaurant Price / Wholesale Price"

[EP3] nFood.StateFlags:
    undefined, Burnt, Spoiled, "One Time Update?", "Started Fire?"

[EP3] nFood.TuningTables:
    Tuning, "Tuning - Ads", "Cook - Food Pts - Max", "Cook - Time - Max"
    "Cook - Time - Max - Group", "Cook - Skill Gain Rate",
    "Cook Skill Gain Rate - Group", "Model State - Indicies", "SG - Tuning"

[EP3] nFood.TuningVars:
    "Food Pts - Base", "Food Unit Cost - Single", "Food Unit Cost - Group",
    "Hunger Pts/Loop", "Menu - Req. Skill - Single", "Menu - Req. Skill - Group",
    "Food Pts - Max Prep Pts", "Prep Time Max - Single", "Prep Time Max - Group",
    "Prep - Skill Gain Rate", "Prep - Skill Gain Rate - Group",
    "Group Meal Serving Count", "Food Difficulty", "Spoil Time - Hours",
    "Max Skill - Pts/Time - Single", "Max Skill - Pts/Time - Group",
    "Menu - Max Skill - Single", "Menu - Max Skill - Group", "Restaurant Price"

[EP3] nTokens.TokenType:
    Token_Business_Object_I_Want, Token_Timestamp

[EP2/3/4] ObjData:
    graphic, direction, "container id", "slot number", "allowed height flags",
    "wall adjacency flags", "Stop Base Interaction", "Niceness Score", flags, 
    "footprint index", "route penalty", "object id", "target id",
    "wall placement flags", "Maintain Level", "Repair Level", "light source", 
    "walk style", "sim age", "lead tile object ID", "tree table entry", 
    "birth minute", "Door route blocker flags", "rotation notches", 
    "birth hour", "lockout count", "Sitting Value", weight, "support strength", 
    room, "room placement", "prep value", "cook value", "surface value", 
    "Hidden Flags", temperature, "dispose value", "wash dish value", 
    "eating surface value", "dirty level", "flag field 2", "current value", 
    "placement flags", "movement flags", "maximum grade", "birth year", 
    "birth month", "birth day", "age in months", "Trash Units", 
    "hide interaction", "lighting contribution", "primitive result", 
    "portal penalty", "primitive result id", "Target Slot Count", disabled, 
    "Render Alpha (maximum)", "object version", category, "simulate on pause", 
    "serving surface value", "use count", "exclusive placement flags", 
    "gardening value", "wash hands value", "function score", "slot count", 
    "Shadow Type", "wall cutout flags", "Vehicle Speed", "Render Flags", 
    "Render Alpha", "Render Red", "Render Green", "Render Blue", 
    "Water Utility Usage Per Hour", "Energy Utility Usage  Per Hour", 
    "Look At Score", "SemiAttribute Count", "Object Link Forward", 
    "Object Link Backward", "Placement Flags 2", DaysTillBreak, Flammibility, 
    "Hurry Speed", "Crapness Score", "Disable All Interactions", 
    "Portal Link 1 From Slot ID", "Portal Link 1 To Slot ID", 
    "Portal Link 1 To Object ID", "Portal Link 1 To Object GUID Lower Word", 
    "Portal Link 1 To Object GUID Upper Word", "Portal Link 2 From Slot ID", 
    "Portal Link 2 To Slot ID", "Portal Link 2 To Object ID", 
    "Portal Link 2 To Object GUID Lower Word", "Portal Link 2 To Object GUID Upper Word", 
    "flags field 3", "Gift From Neighbor ID", "Gift To Neighbor ID", 
    "UI Icon Flags", "Last Tick Rendered",
    / "Invisible wall placement flags", "Interaction UI Priority",
    "Wholesale Purchase Cost", "For Sale Flags", "Tree Table Override Data",
    / "Anim Offset X", "Anim Offset Y", "Anim Offset Z", 
    "Anim Offset Z Rotation", "Pet Awareness Value"

[EP2/3] ObjDef:
    version, guid, "original guid", "model guid", "type attribute guid", 
    "diagonal selector guid", "non diagonal selector guid", "proxy guid", 
    "job object guid", "valid ep bit field", 
    "version_1 - Read Only", "version_2 - Read Only", "initial stack size", 
    "Default Wall Adjacent Flags", "Default Placement Flags", 
    "Default Wall Placement Flags", "Default Allowed Height Flags", 
    "Interaction Table ID", "interaction group", type, "Multi-Tile master id",
    "Multi-Tile sub index", "Use Default Placement flags", "Look At Score", 
    "guid_1 - Read Only", "guid_2 - Read Only", "Item Is Unlockable", 
    "Catalog Use Flags", price, "body strings id", "slots id", 
    "diagonal selector guid 1 - Read Only", "diagonal selector guid 2 - Read Only", 
    "grid-aligned selector guid 1 - Read Only", "grid-aligned selector guid 2 - Read Only", 
    "Object ownership flags", "Ignore GlobalSim field in CAS Lot", 
    "Cannot Move Out With", Hauntable, "Proxy GUID 1", "Proxy GUID 2", "slot group", 
    "Aspiration Flags", "Memory Nice/Bad", "sale price", "initial depreciation", 
    "daily depreciation", "self depreciating", "depreciation limit", 
    "room sort flags", "function sort flags", "catalog strings id", "global sim object", 
    "ToolTip Name Type - 0 default", "Template Version", "Niceness Multiplier", 
    "No Duplicate On Placement", "Want Category", "No New Name from Template", 
    "object version", "Default Thumbnail ID", "motive effects id", 
    "Job Object GUID 1", "Job Object GUID 2", "catalog popup id", 
    "Ignore Current Model Index In Icons", "level offset", "shadow type", 
    "num attributes", "number of object arrays", "For Sale Flags", "front direction", 
    "Unused 62", "Multi-Tile lead object", "Valid EP Flags 1", "Valid EP Flags 2", 
    "chair entry flags", "tile width", "inhibit suit copying", "build mode type", 
    "original guid 1 - Read Only", "original guid 2 - Read Only", 
    "object model guid 1 - Read Only", "object model guid 2 - Read Only", 
    "build Mode Subsort", "Selector Category", "Selector Sub-Category", 
    "footprint mask", "extend footprint", "Object Size", "Unused 80", 
    "Unused - wall style sprite id (Sims1)", ratingHunger, ratingComfort, 
    ratingHygiene, ratingBladder, ratingEnergy, ratingFun, ratingRoom, 
    ratingSkillFlags, "num type attributes", "misc flags", 
    "Unused - type attr guid 1 (Sims1)", "Unused - type attr guid 2 (Sims1)", 
    "Function Sub-Sort", "Downtown Sort", "Keep Buying", "Vacation Sort", 
    "Reset Lot Action", "3D Object Type", "Community Sort", "Dream Flags", 
    "Thumbnail Flags",
    / "Unused 103", "Unused 104", "Unused 105", "Unused 106", "Unused 107"

[EP2] OutfitEyeColor:
    Unknown, Custom, Green, Brown, "Light Blue", "Dark Blue", Gray, Alien

[EP2] OutfitHairColor:
    Unknown, Custom, Black, Brown, Blond, Red, Grey, Dyed

[EP2/4] OutfitProperty:
    "Hair Color", "Skin Color", "Eye Color", "Facial Hair", Glasses,
    Makeup, "Full Face Makeup", Hat, Tattoos, "Nose Ring",
    / "Pet Collar"

[EP2] OutfitSkinColor:
    Unknown, Custom, Light, Medium, "Medium Dark", Dark, Alien, Zombie

[EP2/5] OutfitType:
    Casual1, Casual2, Casual3, Swimsuit, Formal, Pajamas, Underwear,
    Naked, "Gym Clothes", Maternity, "Try-on",
    0 = 1, 1 = 128, 2 = 8, 3 = 512, 4 = 32, 5 = 16, 6 = 1024,
    7 = 1, 8 = 256, 9 = 2, 10 = 4, 11 = 64,
    / "Naked Overlay", Outerwear, 12 = 2048, 13 = 4096

[EP2/3/4/6] PersonData:
    "Sitting?", "Money Amount over Head", "Personality Nice", "Personality Active",
    "kEP1 - Current Grade", "Personality Playful", "Personality Outgoing",
    "Personality Neat", "Current Outfit", "Cleaning Skill", "Cooking Skill",
    "Charisma Skill", "Mechanical Skill", "xxxi: Exercise ( Hot Date )",
    "xxxi: Food ( Hot Date )", "Creativity Skill", "xxxi: Parties  ( Hot Date )",
    "Body Skill", "Logic Skill", "Group Talk State Flags", "xxxi: Style ( Hot Date )",
    "ci: Current Interaction Index", "Gender Pref - Male", "Gender Pref - Female",
    "Job Data", "Interaction Data Field #1", "ci: Sub Queue Interaction Count",
    "tick counter", "Interaction Data Field #2", "Motives Static?",
    "Censorship Flags", "neighbor id", "Person Type", Priority, "Greet Status",
    "visitor schedule", "autonomy level", "route slot", "route multi slot index",
    "route status", "route goal", "Look At Object ID", "Look At Slot ID",
    "Look At State", "Look At Time Remaining", "cn: Next Queued Interaction Index",
    Aspiration, "Original Neat Personality Type", "Original Nice Personality",
    "Original Active Personality", "Original Outgoing Personality",
    "Original Playful Personality", "Sim UI Icon Flags",
    "FindBestAction result Interaction Object ID", "Memory Score", "route start slot",
    "School Grade", "Job Promotion Level", "Person Age", "Social Menu Obj ID",
    "skin color", "family number", "route result", "job performance",
    "Is Swimming?", "Gender(0=male/1=female)", private, "lingering house number",
    "Ghost Flags (Routing Behavior)", PTO, zodiac, "non-interruptible",
    "cn: Next Queued Interaction Continuation?", "footprint extension",
    "Render Display Flags", "ci: Sub Queue Master Interaction Object ID",
    "ci: Sub Queue Master Interaction Index", "cn: Next Sub Queue Interaction Index",
    "cn: Next Sub Queue Interaction Object ID", "cn: Next Queued Interaction Object ID",
    "ci: Current Interaction Object ID", "Body Flags", "Fatness [0-1000]",
    "kEP1 - Current GPA", "PersonData Flags 1", "xxxi:Teen Life Score(unused)",
    "xxxi:Adult Life Score(unused)", "xxxi:Elder Life Score(unused)",
    "Voice Type", "Job Object GUID1", "Job Object GUID2", "Age Days Left",
    "Days in Previous Age", "Decay Hunger per Day", "Decay Comfort per Day",
    "Decay Bladder per Day", "Decay Energy per Day", "Decay Hygiene per Day",
    "unused( was Social Family Decay)", "Decay Social per Day", "Decay Shopping per Day",
    "Decay Fun per Day", "ci: Current Running Interaction Index",
    "ci: Current Running Object ID", "Motive - Power", "Work Outfit Index",
    "Decay Scratch-Chew per Day", "School Object GUID 1", "School Object GUID 2",
    "ci: Current Interaction GUID", "Interactions Linked Deleted",
    "Romance Skill", "LocoWeight 0", "LocoWeight 1", LocoPersonalityIndex,
    LocoPersonalityWeight, LocoMoodIndex, LocoMoodWeight,
    "Motives Not Included in Mood", "Outfit Source GUID1", "Outfit Source GUID2",
    "Environment Score Override", "Fitness Preference", Pension,
    "i: Politics", "i: Money", "i: Environment", "i: Crime", "i: Entertainment",
    "i: Culture", "i: Food", "i: Health", "i: Fashion", "i: Sports",
    "i: Paranormal", "i: Travel", "i: Work", "i: Weather", "i: Animals",
    "i: School", "i: Toys", "i: Sci-Fi", "i: Unused", "i: Unused", "i: Unused",
    "i: Unused", "i: Unused", "i: Unused", "i: Unused", "i: Unused", "i: Unused",
    "i: Unused", "i: Unused", "i: Unused", "Unselectable Sim", "NPC Type",
    "Age Duration", "ci: Sub Queue Interaction Object ID", "Selection Flags",
    "PersonData Flags 2", "Aspiration Score", "Aspiration Reward Points Spent (/10)",
    "Aspiration Score Raw (/10)", "Mood Booster", "Current Interaction Joinable",
    "Unlinked?", "Interaction Autonomous", "Retired Job GUID1", "Retired Job GUID2",
    "Retired Job Level", "kEP1 - College Major GUID#1", "kEP1 - College Major GUID#2",
    "kEP1 - Time Left In Grading Period", "kEP1 - Semester Info Flags",
    "kEP1 - College Semester", "kEP1 - Young Adult( 0=no, 1=yes )",
    "kEP1 - Influence Bar Level", "kEP1 - Influence Minimum", "kEP1 - Influence Score",
    "route start slot owner ID", "Attraction Traits 1", "Attraction Traits 2",
    "Attraction Turn Ons 1", "Attraction Turn Ons 2", "Attraction Turn Offs 1",
    "Attraction Turn Offs 2", Species, "Countdown Timer ID", "Perfume Duration",
    "Date Timer", "Date Score", "Date Unlock Count", "Love Potion Duration",
    "Aspiration Score Lock", "Date Neighbor ID",
    / "Ownable Lot Job - Lot Id", "Ownable Lot Job - Salary",
    "Ownable Lot Job - Flags", "Ownable Lot Job - Assignment Id",
    / "Pet Traits",
    / "Time Left In Vacation", "Attraction Turn Ons 3", "Attraction Turn Offs 3",
    "Attraction Traits 3"

[EP4] PetTraits:
    Gifted, Doofus, Hyper, Lazy, Independant, Friendly,
    Aggressive, Cowardly, Pigpen, Finicky

[EP5] PondFrozenState:
    Unfrozen, Frozen

[EP5] PrecipitationIntensity:
    None, Light, Heavy, Torrential

[EP5] PrecipitationType:
    None, Snow, Rain, Hail

[EP3] RelVars:
    STR, Flags, LTR, FamilyInfo, Sync, ChildhoodFlags, TeenFlags,
    AdultFlags, AttractionScore

[EP3] RelFlags:
    Crush, Love, Engaged, Married, Friend, BestFriend, GoingSteady,
    Enemy, Contact, FamilialSet, StandardSet

[EP3] RelMasks:
    Crush, Love, Engaged, Married, Friend, BestFriend, GoingSteady,
    Enemy, Contact, FamilialSet, StandardSet

[EP3] RelFamilial:
    Parent, Child, Sibling, Grandparent, Grandchild, "Uncle/Aunt"
    "Nephew/Niece", Cousin, Spouse

[EP3/4/5/6] ReservedFamilyIDs:
    "Service NPCs", Townies, Orphans, DownTownies, "Reserved ID Min",
    "Bob the Builder",
    / Strays, "Orphan Pets", "Display Pets - Available", "Display Pets - In Use",
    / "Garden Club",
    / Tourists, Asia, Mountains, Tropics

[EP2] Scope:
    Private = 0, SemiGlobal = 1, Global = 2

[EP5] Seasons:
    Spring, Summer, Fall, Winter

[EP3] SimulatorGlobal:
    Hour, "Day of Month", "Zoom Level(S/M/L)", "Selected Person ID", "Time Of Day", 
    Minute, Second, Month, Year, "Current Family", "Current House", Unused, 
    "Last GZ Button ID", "Budget Mod 10000", "Budget Div 10000", "Current Language", 
    Speed, Paused, "Held Sim Speed", Mode, "Game Edition", "Inhibit Move In", 
    "Lot Has House", "Lot Size", "Current SKU", "Debug flags", "Tutorial State", 
    "Indoor Tiles", "Days Running", "Maximum Day Number", "Free Will", 
    "House radio station", "Interrupt On(Simless Build Mode in sims 1.x)", 
    "Demo Flags(Machine Level in sims 1.x)", "Day Of Week", 
    "Parental Control (non zero =  on)", "Current Interaction GUID", 
    "Utility Available Flags", "Utility Bill - Energy", "Utility Bill - Water", 
    "Current Neighborhood ID", "Lot Zoning", "Allow Aging", "Last Neighborhood ID", 
    "Lot Entry Method", "Cinematic Camera off/on", "Lot Value Div 1000", 
    "Lot Value Mod 1000", "Objects Value Div 1000", "Object Value Mod 1000", 
    "Max Visitors", "Object Error Flags", "Camera Busy", "Instant Write Once Flags", 
    "Neighborhood Type"

[EP3] SkillIndex:
    Cleaning, Cooking, Charisma, Mechanical, Creativity, Body, Logic

[EP5] SkyClarity:
    Clear, Cloudy

[EP4] Species:
    Human, "Large Dog", "Small Dog", Cat

--------------------------------------------------------------------------
Notes
--------------------------------------------------------------------------

value - a numeric value, usually a 16-bit signed integer
bool - a boolean value (i.e. false or true)
string - an array of characters
guid - a numeric 32-bit value
index - a positive numeric value, usually a table reference
shiftValue - a positive non-zero numeric value, usually 1 to 15
tempNum - Temp (T[]) index
paramNum - Param index
localNum - Local index
objList - a table of objectId values
neighborhoodList - a table of neighborhoodId values
tokenList - a table of xToken values
searchMode - 1 = with GUID, 2 = get all parts of objectId (k-v)
tileX, tileY, level - numeric positional values

---------------------------------------
- Supported libraries

math, string, table

--------------------------------------------------------------------------
- Examples
---------------------------------------
-- here's a simple way to do some complicated variable swapping

local count = GetPrimitiveParameter(0)

-- this swaps the values of the local and temp variables for 0 to count - 1

if count == 0 then
    SetScriptReturnValue(false)
else
    SetScriptReturnValue(true)
    for x = 0, count - 1 do
        local t = GetTemp(x)
        SetTemp(x, GetLocal(x))
        SetLocal(x, t)
    end
end

---------------------------------------
-- retrieve daily wage value for a particular job
-- 
-- param 0 is some JobData object
-- param 1 is the job position (0 to 10)
-- daily wage is returned in Temp 0

local job = GetPrimitiveParameter(0)
local pos = GetPrimitiveParameter(1)

local guid = GlobalObjManager:getObjectGUIDFromObjectId(job)
SetTemp(0, GetConstantWithGuid(guid, 4096, pos))

---------------------------------------
-- large expression
-- 
-- take the value from Local 0 and 1
-- add param 0, multiply by param 1, divide by param 2
-- store the result into Local 0 and 1
-- 
-- note:
-- Local 0 = high value (0 to 9999 -> 0 to 99990000)
-- Local 1 = low value (0 to 9999)

local x = GetLocal(0) * 10000 + GetLocal(1)
x = x + GetPrimitiveParameter(0)
x = x * GetPrimitiveParameter(1) / GetPrimitiveParameter(2)
SetLocal(0, x / 10000)
SetLocal(1, math.round(math.mod(x, 10000)) )

---------------------------------------
-- set to next neighbor sorted - slow but functional
-- action string creator
-- 
-- Temp 0 = previous neighborId/0
-- returns False if no next was found
-- returns True if found, Temp 0 = neighborId, $PropertyGlobalString[0x133:6] = name

local function stnn_cmp(e1, e2)
    local cn1 = CachedNeighbor.new(e1)
    local cn2 = CachedNeighbor.new(e2)
    local s1 = cn1:getSurname() .. " " .. cn1:getName()
    local s2 = cn2:getSurname() .. " " .. cn2:getName()
    return s1 < s2
end

local pid = GetTemp(0) -- previous neighborId

local nlist = GlobalObjManager:getNeighborIds()

table.sort(nlist, stnn_cmp) -- sort list by names

local x = -1 -- find index of previous id
if pid == 0 then
    x = nil
else
    for i,v in nlist do
        if v == pid then x = i end
    end
end

local nid = nil
if x ~= -1 then x, nid = next(nlist, x) end -- get next id

-- create pie menu string

SetScriptReturnValue(false)

if nid ~= nil then
    SetTemp(0, nid) -- Temp 0 = next neighborId

    local cn = CachedNeighbor.new(nid)
    local sname = cn:getSurname()
    local fname = cn:getName()

    local s = fname .. " " .. sname
    if sname == "" then
        s = fname
    end
    nGameState.SetProperty("luaDialogString", s)
    SetScriptReturnValue(true)
end

---------------------------------------
-- Spawn cheat stuff
-- 
-- Local 2 = index
-- returns guid in Temp 0/Local 1 (hi), Local 0 (lo)
-- use "$GUIDCatalogNameLocal:0:1" to make the action strings
-- 
-- hex to integer converter

local function hex2int(hex)
    local v = 0
    local x = 1

    if string.sub(hex, 1, 2) == "0x" then x = 3 end

    while string.byte(hex, x) ~= nil do
        local c = string.byte(hex, x) - 48
        if c > 9 then c = c - 7 end
        if c > 32 then c = c - 32 end
        x = x + 1
        v = (v * 16) + c
    end

    return v
end

-- using hex values because they are pretty much universal outside Lua for GUIDs

local guids = { "0xAE8D50B2","0x4E9FBE5D","0xD24D09FD","0xAEB9F591","0xCEA505BB",
    "0xD1CD15C8","0xCC58DF85","0x0C6E194A","0x8C4D2997","0xD24CE39C","0xF24CFF80",
    "0x324D0D87","0x124E3138","0x524E1066","0x8EE9B9CC","0xEEAE16BD","0xF1A0515D",
    "0xAF6BEF67","0xADAD4846","0x4DA7F9CE","0xED9BEC86","0x0DAC06C5","0x0D99632D",
    "0x706A717C","0x8CB284A3","0xADACE67A","0x4C2148B0","0xCC20426A","0x6C2979FB",
    "0xCC16D816","0x6C6CE31F","0x2DBA063D","0xADAC1188","0xAC314A3A","0x6DA6AF29",
    "0x12422517","0xB3281ED8","0x7354D27E","0x1354D261","0x5354D1FA","0xD354D23C",
    "0xB354D1C5","0x3354D105","0x735F2371","0x535F2CBE","0x135F2CAF","0x135F2CA4",
    "0x5090CDCF" }

local x = GetLocal(2) + 1
SetLocal(2, x) 

if x <= table.getn(guids) then
    local hi, lo = SplitObjectGUID(hex2int(guids[x]))
    SetTemp(0, hi)
    SetLocal(1, hi)
    SetLocal(0, lo)
    SetScriptReturnValue(true)
else
    SetScriptReturnValue(false)
end

---------------------------------------

