├── .gitignore ├── LICENSE ├── README.md └── source ├── api ├── math.lua ├── string.lua └── table.lua ├── checkTimers.lua ├── classes ├── DataHandler.lua ├── EventHandler.lua ├── PlayerFinder.lua ├── SystemLooping.lua ├── Timers.lua └── TouchSensor.lua ├── commands ├── !ban.lua ├── !coin.lua ├── !errorlogs.lua ├── !givebadge.lua ├── !givecar.lua ├── !giveorb.lua ├── !hour.lua ├── !image.lua ├── !insert.lua ├── !jail.lua ├── !job.lua ├── !lootbox.lua ├── !move.lua ├── !movetome.lua ├── !place.lua ├── !profile.lua ├── !qp.lua ├── !quest.lua ├── !roomlog.lua ├── !setgravity.lua ├── !setwind.lua ├── !shop.lua ├── !sidequest.lua ├── !snow.lua ├── !spawn.lua ├── !teleport.lua ├── !title.lua ├── !trade.lua ├── !unban.lua ├── !update.lua ├── !updatesidequest.lua └── !whitelist.lua ├── dayPeriods.lua ├── events ├── ChatCommand.lua ├── EmotePlayed.lua ├── FileLoaded.lua ├── Keyboard.lua ├── Loop.lua ├── Mouse.lua ├── NewPlayer.lua ├── PlayerBonusGrabbed.lua ├── PlayerDataLoaded.lua ├── PlayerDied.lua ├── PlayerLeft.lua ├── PlayerRespawn.lua └── TextAreaCallback.lua ├── furnitures └── IDS.lua ├── gameHour.lua ├── houseSystem ├── _expansions.lua ├── _houses.lua ├── _new.lua ├── _plants.lua ├── _terrainsPositions.lua ├── gardening.lua ├── genHouseFace.lua ├── genHouseGrounds.lua ├── loadHouse.lua ├── loadTerrains.lua └── removeHouse.lua ├── init.lua ├── initialization ├── configCrops.lua ├── configDaveOffers.lua ├── configFiles.lua ├── configMine.lua ├── configPlaces.lua ├── configRecipes.lua ├── configRoom.lua ├── configShops.lua ├── configTimers.lua └── configVehicles.lua ├── interfaces ├── errorAlert.lua ├── modernUI │ ├── modernUI.lua │ ├── showATM_Machine.lua │ ├── showAvailableTradingPlayers.lua │ ├── showBadgeInterface.lua │ ├── showBagIcons.lua │ ├── showDaveOffers.lua │ ├── showHousePermissions.lua │ ├── showHouseSettings.lua │ ├── showHouseSlotsToChoose.lua │ ├── showHouses.lua │ ├── showJobInterface.lua │ ├── showLevelOrb.lua │ ├── showMill.lua │ ├── showNPCShop.lua │ ├── showNewLevelOrb.lua │ ├── showPlayerItems.lua │ ├── showPlayerVehicles.lua │ ├── showProfileInterface.lua │ ├── showQuestInterface.lua │ ├── showRecipes.lua │ ├── showRewardInterface.lua │ ├── showSettingsMenu.lua │ └── showUpdateLog.lua ├── toRewrite │ └── oldInterface.lua └── tradeSystem.lua ├── items ├── bag.lua ├── checkAmount.lua ├── chest.lua ├── drop.lua ├── itemInfo.lua └── itemList │ ├── bagItems.lua │ └── recipes.lua ├── jobs ├── cop │ └── arrest.lua ├── fisher │ ├── _biomes.lua │ └── fish.lua ├── jobData.lua ├── jobState.lua └── thief │ └── rob.lua ├── lifeStats.lua ├── map ├── game.lua ├── loadMap.lua └── lobby.lua ├── misc ├── badges.lua ├── bagIcons.lua ├── bankCodes.lua ├── communityFlag.lua └── jobRewards.lua ├── npcs ├── gameNpcs │ ├── addCharacter.lua │ ├── daveOffers.lua │ ├── setOrder.lua │ ├── talk.lua │ ├── updateDialogBox.lua │ └── updateDialogs.lua ├── npcDialogs.lua └── shops │ └── loadShop.lua ├── places ├── _checkLocation │ └── isInHouse.lua ├── _placesData.lua ├── bank │ ├── _properties.lua │ └── robbingAssets.lua ├── events.lua ├── hospital │ ├── _properties.lua │ ├── hospitalize.lua │ └── loadFloor.lua └── mine │ ├── _perlin.lua │ ├── _properties.lua │ └── grid.lua ├── playerData ├── _dataStructure.lua ├── _dataToSave.lua ├── _localDataStructure.lua ├── dataToLoad │ └── storeFurniture.lua └── player.lua ├── quests ├── mainquest.lua ├── mainquest_init.lua ├── sidequest.lua └── sidequest_init.lua ├── ranking ├── load.lua └── save.lua ├── recipeSystem.lua ├── social ├── addLootDrop.lua ├── freezePlayer.lua ├── setNightMode.lua └── showPlayerLevel.lua ├── sounds └── soundList.lua ├── specialBackgrounds.lua ├── tips.lua ├── translations ├── _langIDS.lua ├── _merge.lua ├── _translationSystem.lua ├── ar.lua ├── br.lua ├── de.lua ├── en.lua ├── es.lua ├── fr.lua ├── he.lua ├── hu.lua ├── id.lua ├── pl.lua ├── ru.lua └── tr.lua ├── vehicles ├── _IDS.lua ├── giveCar.lua └── vehicles.lua └── versionLogs.lua /.gitignore: -------------------------------------------------------------------------------- 1 | source/syncGame.lua 2 | *.DS_Store 3 | builder.lua 4 | source/.DS_Store 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020-2022 Chrystian Gabriel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Mycity logo 4 | 5 |

6 | 7 | # About 8 | 9 | > Mycity is a game that is city-like. In it houses can be bought and various jobs and quests are available. 10 | > 11 | > The game was released in 2017 and it's built using Lua. It runs in [Transformice](https://www.transformice.com) at any *#mycity* room. 12 | 13 | # Languages 14 | 15 | > Mycity is available in 10 languages: 16 | ``` 17 | > AR 18 | > BR/PT 19 | > EN 20 | > ES 21 | > FR 22 | > HE 23 | > HU 24 | > ID 25 | > PL 26 | > RU 27 | > TR 28 | ``` 29 | > If you want to add a new language, feel free to add a new PR! 30 | > Translation files can be found in ``source > translations`` 31 | 32 | ### changelog 33 | 34 | > ☑️ First build launched 35 | > 36 | > ☑️ Added a new crop: Banana Plant 37 | > 38 | > ☑️ V3.0.4 released 39 | > 40 | > ☑️ Season 2 ended 41 | > 42 | > ☑️ V3.0.4b released 43 | > 44 | > ☑️ Indentation fixes (blank spaces) 45 | > 46 | > ☑️ Added 9 new files 47 | > 48 | > ☑️ V3.0.5 released 49 | > 50 | > ☑️ Added Quest 05 files 51 | > 52 | > ☑️ V3.1.0 released 53 | > 54 | > ☑️ Quest 05 released 55 | > 56 | > ☑️ V3.1.1 released 57 | > 58 | > ☑️ V3.2.0 released 59 | > 60 | > ☑️ V3.3.0 released - Halloween Event 2020 61 | > 62 | > ☑️ New Trading System 63 | > 64 | > ☑️ V3.4.0 released - Christmas Event 2020 65 | > -------------------------------------------------------------------------------- /source/api/math.lua: -------------------------------------------------------------------------------- 1 | math_hypo = function(x1, y1, x2, y2) 2 | return ((x2-x1)^2 + (y2-y1)^2)^0.5 3 | end 4 | 5 | math_range = function(polygon, point) 6 | local oddNodes = false 7 | local j = #polygon 8 | for i = 1, #polygon do 9 | if (polygon[i].y < point.y and polygon[j].y >= point.y or polygon[j].y < point.y and polygon[i].y >= point.y) then 10 | if (polygon[i].x + ( point.y - polygon[i].y ) / (polygon[j].y - polygon[i].y) * (polygon[j].x - polygon[i].x) < point.x) then 11 | oddNodes = not oddNodes; 12 | end 13 | end 14 | j = i; 15 | end 16 | return oddNodes 17 | end -------------------------------------------------------------------------------- /source/api/string.lua: -------------------------------------------------------------------------------- 1 | string_nick = function(name) 2 | if not name then return end 3 | local var = name:lower():gsub('%a', string.upper, 1) 4 | for i, v in next, ROOM.playerList do 5 | if i:find(var) then 6 | return i 7 | end 8 | end 9 | end 10 | 11 | string_replace = function(name, args) 12 | for i, v in next, args do 13 | if i == '{1}' then 14 | args[i] = ''..v..'' 15 | else 16 | args[i] = translate(v, name) 17 | end 18 | end 19 | local str = translate('multiTextFormating', name) 20 | return (gsub(str, '{.-}', args, #str /3)) 21 | end 22 | 23 | string_toTable = function(x) 24 | return (type(x) == "table" and x or {x}) 25 | end -------------------------------------------------------------------------------- /source/api/table.lua: -------------------------------------------------------------------------------- 1 | table_find = function(tbl, val) 2 | for i = 1, #tbl do 3 | if tbl[i] == val then 4 | return i 5 | end 6 | end 7 | return false 8 | end 9 | 10 | table_copy = function(obj, seen) 11 | if type(obj) ~= 'table' then return obj end 12 | if seen and seen[obj] then return seen[obj] end 13 | local s = seen or {} 14 | local res = setmetatable({}, getmetatable(obj)) 15 | s[obj] = res 16 | for k, v in next, obj do 17 | res[table_copy(k, s)] = table_copy(v, s) 18 | end 19 | return res 20 | end 21 | 22 | table_concatFancy = function(tbl, sepMiddle, sepFinal, j) 23 | sepFinal = sepFinal or sepMiddle or '' 24 | j = j or #tbl 25 | return table_concat(tbl, sepMiddle, 1, j - 1) .. sepFinal .. tbl[j] 26 | end 27 | 28 | table_getLength = function(tbl) 29 | local length = 0 30 | for _ in next, tbl do 31 | length = length + 1 32 | end 33 | return length 34 | end 35 | 36 | table_merge = function(this, src) 37 | for k, v in next, src do 38 | if this[k] then 39 | if type(v) == "table" then 40 | this[k] = string_toTable(this[k]) 41 | table_merge(this[k], v) 42 | else 43 | this[k] = this[k] or v 44 | end 45 | else 46 | this[k] = v 47 | end 48 | end 49 | end 50 | 51 | table_randomKey = function(tbl) 52 | local key 53 | local counter = 0 54 | for k in next, tbl do 55 | counter = counter + 1 56 | if random() < (1 / counter) then 57 | key = k 58 | end 59 | end 60 | return key 61 | end -------------------------------------------------------------------------------- /source/checkTimers.lua: -------------------------------------------------------------------------------- 1 | local workingTimerState = { 2 | stop = -1, 3 | start = 0, 4 | tryLimit = 2, 5 | setBroken = 3, 6 | setVerified = 4, 7 | broken = 5 8 | } 9 | local workingTimer = workingTimerState.start 10 | do 11 | checkWorkingTimer = function() 12 | if workingTimer == workingTimerState.broken then 13 | updateDialogs(10) -- Function used in timers is now used in eventLoop 14 | timersLoop(500) 15 | elseif workingTimer > workingTimerState.tryLimit then 16 | if workingTimer == workingTimerState.setBroken then 17 | workingTimer = workingTimerState.broken 18 | --errorHandler('Timers', 'Error') 19 | chatMessage("[Timers Disruption] Some game animations may be affected.") 20 | elseif workingTimer == workingTimerState.setVerified then 21 | workingTimer = workingTimerState.stop 22 | end 23 | -- Chunk below executes once, verification finished 24 | elseif workingTimer > workingTimerState.stop then 25 | if workingTimer < workingTimerState.tryLimit then 26 | workingTimer = workingTimer + 0.5 27 | if workingTimer == workingTimerState.tryLimit then 28 | workingTimer = workingTimerState.setBroken 29 | end 30 | end 31 | end 32 | end 33 | system.newTimer(function() 34 | workingTimer = workingTimerState.setVerified 35 | end, 1000, false) 36 | end -------------------------------------------------------------------------------- /source/classes/PlayerFinder.lua: -------------------------------------------------------------------------------- 1 | local playerFinder = { 2 | requests = {} 3 | } 4 | 5 | playerFinder.checkIfIsOnline = function(target, fn) 6 | if ROOM.playerList[target] then return fn() end 7 | playerFinder.requests[target] = fn 8 | loadPlayerData(target) 9 | end -------------------------------------------------------------------------------- /source/classes/SystemLooping.lua: -------------------------------------------------------------------------------- 1 | -- system.looping, made by Bolodefchoco#0000 2 | system.looping = function(f, ticks, ...) 3 | local timers, index = { }, 0 4 | local addTimer = function(_, ...) 5 | index = index + 1 6 | timers[index] = system.newTimer(f, 1000, true, ...) 7 | end 8 | 9 | local seconds = 1000 / ticks 10 | for timer = 0, 1000 - seconds, seconds do 11 | system.newTimer(addTimer, 1000 + timer, false, ...) 12 | end 13 | 14 | return timers 15 | end -------------------------------------------------------------------------------- /source/classes/Timers.lua: -------------------------------------------------------------------------------- 1 | -- Timers, made by Laagaadoo#0000 2 | local List = {} 3 | local timerList = {} 4 | local timersPool 5 | do 6 | function List.new () 7 | return {first = 0, last = -1} 8 | end 9 | timersPool = List.new() 10 | function List.pushleft (list, value) 11 | local first = list.first - 1 12 | list.first = first 13 | list[first] = value 14 | end 15 | 16 | function List.pushright (list, value) 17 | local last = list.last + 1 18 | list.last = last 19 | list[last] = value 20 | end 21 | 22 | function List.popleft (list) 23 | local first = list.first 24 | if first > list.last then 25 | return nil 26 | end 27 | local value = list[first] 28 | list[first] = nil -- to allow garbage collection 29 | list.first = first + 1 30 | return value 31 | end 32 | 33 | function List.popright (list) 34 | local last = list.last 35 | if list.first > last then 36 | return nil 37 | end 38 | local value = list[last] 39 | list[last] = nil -- to allow garbage collection 40 | list.last = last - 1 41 | return value 42 | end 43 | function addTimer(callback, ms, loops, label, ...) 44 | local id = List.popleft(timersPool) 45 | if id then 46 | local timer = timerList[id] 47 | timer.callback = callback 48 | timer.label = label 49 | timer.arguments = {...} 50 | timer.time = ms 51 | timer.currentTime = 0 52 | timer.currentLoop = 0 53 | timer.loops = loops or 1 54 | timer.isComplete = false 55 | timer.isPaused = false 56 | timer.isEnabled = true 57 | else 58 | id = #timerList+1 59 | timerList[id] = { 60 | callback = callback, 61 | label = label, 62 | arguments = {...}, 63 | time = ms, 64 | currentTime = 0, 65 | currentLoop = 0, 66 | loops = loops or 1, 67 | isComplete = false, 68 | isPaused = false, 69 | isEnabled = true, 70 | } 71 | end 72 | return id 73 | end 74 | 75 | function getTimerId(label) 76 | local found 77 | for id = 1, #timerList do 78 | local timer = timerList[id] 79 | if timer.label == label then 80 | found = id 81 | break 82 | end 83 | end 84 | return found 85 | end 86 | 87 | function pauseTimer(id) 88 | if type(id) == 'string' then 89 | id = getTimerId(id) 90 | end 91 | 92 | if timerList[id] and timerList[id].isEnabled then 93 | timerList[id].isPaused = true 94 | return true 95 | end 96 | return false 97 | end 98 | 99 | function resumeTimer(id) 100 | if type(id) == 'string' then 101 | id = getTimerId(id) 102 | end 103 | 104 | if timerList[id] and timerList[id].isPaused then 105 | timerList[id].isPaused = false 106 | return true 107 | end 108 | return false 109 | end 110 | 111 | function removeTimer(id) 112 | if type(id) == 'string' then 113 | id = getTimerId(id) 114 | end 115 | 116 | if timerList[id] and timerList[id].isEnabled then 117 | timerList[id].isEnabled = false 118 | List.pushright(timersPool, id) 119 | return true 120 | end 121 | return false 122 | end 123 | function clearTimers() 124 | local timer 125 | repeat 126 | timer = List.popleft(timersPool) 127 | if timer then 128 | table_remove(timerList, timer) 129 | end 130 | until timer == nil 131 | end 132 | function timersLoop(delay) 133 | for id = 1, #timerList do 134 | local timer = timerList[id] 135 | if timer.isEnabled and timer.isPaused == false then 136 | if not timer.isComplete then 137 | timer.currentTime = timer.currentTime + delay 138 | if timer.currentTime >= timer.time then 139 | timer.currentTime = 0 140 | timer.currentLoop = timer.currentLoop + 1 141 | if timer.loops > 0 then 142 | if timer.currentLoop >= timer.loops then 143 | timer.isComplete = true 144 | removeTimer(id) 145 | end 146 | end 147 | if timer.callback ~= nil then 148 | timer.callback(timer.currentLoop, table_unpack(timer.arguments)) 149 | end 150 | end 151 | end 152 | end 153 | end 154 | end 155 | end -------------------------------------------------------------------------------- /source/classes/TouchSensor.lua: -------------------------------------------------------------------------------- 1 | local TouchSensor = { 2 | sensors = {}, 3 | } 4 | do 5 | TouchSensor.add = function(tokenType, x, y, id, angle, icon, target, callback, respawn) 6 | if not TouchSensor.sensors[id] then 7 | TouchSensor.sensors[id] = { 8 | type = tokenType, 9 | x = x, 10 | y = y, 11 | angle = angle, 12 | icon = icon, 13 | target = target, 14 | callback = callback, 15 | respawn = respawn, 16 | } 17 | end 18 | TFM.addBonus(tokenType, x, y, id, angle, icon, target) 19 | end 20 | 21 | TouchSensor.remove = function(id, player) 22 | TFM.removeBonus(id, player) 23 | if not player then 24 | TouchSensor.sensors[id] = nil 25 | end 26 | end 27 | 28 | TouchSensor.triggered = function(player, id) 29 | local self = TouchSensor.sensors[id] 30 | if not self then 31 | return alert_Error(player, 'error', 'TouchSensor failed: invalid id') 32 | end 33 | if self.callback then 34 | self.callback(player) 35 | end 36 | if self.respawn then 37 | TFM.addBonus( 38 | self.type, 39 | self.x, 40 | self.y, 41 | id, 42 | self.angle, 43 | self.icon, 44 | player 45 | ) 46 | else 47 | TouchSensor.remove(id, player) 48 | end 49 | end 50 | end -------------------------------------------------------------------------------- /source/commands/!ban.lua: -------------------------------------------------------------------------------- 1 | chatCommands.ban = { 2 | permissions = {'admin', 'mod'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) or args[1] 5 | room.bannedPlayers[#room.bannedPlayers+1] = target 6 | killPlayer(target) 7 | translatedMessage('playerBannedFromRoom', target) 8 | room.fileUpdated = true 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!coin.lua: -------------------------------------------------------------------------------- 1 | chatCommands.coin = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[2]) 5 | local amount = tonumber(args[1]) or 0 6 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 7 | giveCoin(amount, target) 8 | chatMessage('[•] Done! $'..amount..' set to '..target..'.', player) 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!errorlogs.lua: -------------------------------------------------------------------------------- 1 | chatCommands.errorlogs = { 2 | event = function(player, args) 3 | local gameVersion = 'v'..table_concat(version, '.') 4 | modernUI.new(player, 520, 300, 'Error Logs - '..gameVersion..' ['..versionLogs[gameVersion].releaseDate..']', ''..table_concat(room.errorLogs, '\n'), 'errorUI') 5 | :build() 6 | end 7 | } -------------------------------------------------------------------------------- /source/commands/!givebadge.lua: -------------------------------------------------------------------------------- 1 | chatCommands.givebadge = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) 5 | local badge = tonumber(args[2]) 6 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 7 | if not badges[badge] then chatMessage('[•] Unknown Badge.', player) return end 8 | 9 | giveBadge(target, badge) 10 | chatMessage('[•] Done! Badge '..badge..' given to '..target..'.', player) 11 | end 12 | } 13 | 14 | -------------------------------------------------------------------------------- /source/commands/!givecar.lua: -------------------------------------------------------------------------------- 1 | chatCommands.givecar = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) 5 | local carID = tonumber(args[2]) 6 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 7 | if not mainAssets.__cars[carID] then return chatMessage('[•] Unknown Vehicle.', player) end 8 | 9 | giveCar(target, carID) 10 | chatMessage('[•] Done! '..mainAssets.__cars[carID].name..' given to '..target..'.', player) 11 | end 12 | } -------------------------------------------------------------------------------- /source/commands/!giveorb.lua: -------------------------------------------------------------------------------- 1 | chatCommands.giveorb = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) 5 | local orb = tonumber(args[2]) 6 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 7 | if not mainAssets.levelIcons.star[orb] then chatMessage('[•] Unknown Orb.', player) return end 8 | 9 | giveLevelOrb(target, orb) 10 | chatMessage('[•] Done! Orb '..orb..' given to '..target..'.', player) 11 | end 12 | } 13 | -------------------------------------------------------------------------------- /source/commands/!hour.lua: -------------------------------------------------------------------------------- 1 | chatCommands.hour = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | room.currentGameHour = args[1] or 0 5 | chatMessage('' ..updateHour(player, true)) 6 | end 7 | } -------------------------------------------------------------------------------- /source/commands/!image.lua: -------------------------------------------------------------------------------- 1 | local commandImages = {} 2 | chatCommands.image = { 3 | permissions = {'admin'}, 4 | event = function(player, args) 5 | local image = args[1] or '' 6 | local imgType = args[2] or '!10' 7 | local x = args[3] or -100 8 | local y = args[4] or -100 9 | 10 | commandImages[#commandImages+1] = addImage(image, imgType, x, y) 11 | chatMessage('Image ID: '..#commandImages..'\n' .. 12 | ' Ξ url: '..image..'\n' .. 13 | ' Ξ type: '..imgType..'\n' .. 14 | ' Ξ x: '..x..'\n' .. 15 | ' Ξ y: '..y 16 | , player) 17 | end 18 | } 19 | chatCommands.removeimage = { 20 | permissions = {'admin'}, 21 | event = function(player, args) 22 | local id = tonumber(args[1]) 23 | if commandImages[id] then 24 | removeImage(commandImages[id]) 25 | commandImages[id] = nil 26 | chatMessage('image removed!', player) 27 | end 28 | end 29 | } 30 | -------------------------------------------------------------------------------- /source/commands/!insert.lua: -------------------------------------------------------------------------------- 1 | chatCommands.insert = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local item = args[1] 5 | local amount = tonumber(args[2]) or 1 6 | if not bagItems[item] then return end 7 | addItem(item, amount, player) 8 | end 9 | } -------------------------------------------------------------------------------- /source/commands/!jail.lua: -------------------------------------------------------------------------------- 1 | chatCommands.jail = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) 5 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 6 | chatMessage('[•] arresting '..target..'...', player) 7 | arrestPlayer(target, 'Colt') 8 | end 9 | } 10 | 11 | -------------------------------------------------------------------------------- /source/commands/!job.lua: -------------------------------------------------------------------------------- 1 | chatCommands.job = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player, args) 4 | local job = args[1] 5 | local target = string_nick(args[2]) 6 | if not players[target] then target = player end 7 | if not jobs[job] then return end 8 | job_invite(job, target) 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!lootbox.lua: -------------------------------------------------------------------------------- 1 | chatCommands.lootbox = { 2 | permissions = {'admin'}, 3 | event = function(player) 4 | local x = random(0, 12000) 5 | addLootDrop(x, 7200, 20) 6 | for i, v in next, ROOM.playerList do 7 | movePlayer(i, x, 7600, false) 8 | end 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!move.lua: -------------------------------------------------------------------------------- 1 | chatCommands.move = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player, args) 4 | if not args[1] or not args[2] then return end 5 | local target1 = string_nick(args[1]) or '' 6 | local target2 = string_nick(args[2]) 7 | local originalName = args[2] 8 | if not target2 then 9 | target2 = target1 10 | target1 = player 11 | originalName = args[1] 12 | end 13 | if players[target1] then 14 | if gameNpcs.characters[originalName] then 15 | local _place = gameNpcs.characters[originalName].place or 'town' 16 | chatMessage('[•] teleporting to [NPC] '..originalName..' ('.._place..')...', player) 17 | movePlayer(player, gameNpcs.characters[originalName].x+50, gameNpcs.characters[originalName].y+50, false) 18 | players[target1].place = _place 19 | elseif players[target2] then 20 | chatMessage('[•] ['..target1 .. '] teleporting to ['.. target2 ..'] ('..players[target2].place..')...', player) 21 | movePlayer(target1, ROOM.playerList[target2].x, ROOM.playerList[target2].y, false) 22 | players[target1].place = players[target2].place 23 | else 24 | chatMessage('[•] $playerName not found. ('..target2..')', player) 25 | end 26 | else 27 | chatMessage('[•] $playerName not found. ('..target1..')', player) 28 | end 29 | end 30 | } -------------------------------------------------------------------------------- /source/commands/!movetome.lua: -------------------------------------------------------------------------------- 1 | chatCommands.movetome = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player, args) 4 | if not args[1] then return end 5 | local target = string_nick(args[1]) 6 | if players[target] then 7 | chatMessage('[•] ['..target .. '] teleporting to ['.. player .. '] ('..players[player].place..')...', player) 8 | movePlayer(target, ROOM.playerList[player].x, ROOM.playerList[player].y, false) 9 | players[target].place = players[player].place 10 | else 11 | chatMessage('[•] $playerName not found.', player) 12 | end 13 | end 14 | } 15 | -------------------------------------------------------------------------------- /source/commands/!place.lua: -------------------------------------------------------------------------------- 1 | chatCommands.place = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player, args) 4 | if places[args[1]] then 5 | places[args[1]].exitF(player) 6 | end 7 | end 8 | } -------------------------------------------------------------------------------- /source/commands/!profile.lua: -------------------------------------------------------------------------------- 1 | chatCommands.profile = { 2 | event = function(player, args) 3 | local target = string_nick(args[1]) 4 | openProfile(player, target) 5 | end 6 | } 7 | chatCommands.perfil = table_copy(chatCommands.profile) 8 | chatCommands.profil = table_copy(chatCommands.profile) -------------------------------------------------------------------------------- /source/commands/!qp.lua: -------------------------------------------------------------------------------- 1 | chatCommands.qp = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[2]) 5 | local amount = tonumber(args[1]) or 0 6 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 7 | giveDiamond(amount, target) 8 | savedata(target) 9 | chatMessage('[•] Done! QP$'..amount..' set to '..target..'.', player) 10 | end 11 | } -------------------------------------------------------------------------------- /source/commands/!quest.lua: -------------------------------------------------------------------------------- 1 | chatCommands.quest = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local quest = tonumber(args[1]) 5 | if not lang['en'].quests[quest] then return chatMessage('[•] invalid quest ID.', player) end 6 | local questStep = tonumber(args[2]) or 0 7 | local target = string_nick(args[3]) 8 | if not players[target] then target = player end 9 | if players[target].questStep[1] < quest and _QuestControlCenter[players[target].questStep[1]].reward then 10 | _QuestControlCenter[players[target].questStep[1]].reward(target) 11 | end 12 | players[target].questStep[1] = quest 13 | players[target].questStep[2] = questStep 14 | players[target].questLocalData.step = 0 15 | savedata(target) 16 | 17 | _QuestControlCenter[quest].active(target, 0) 18 | 19 | chatMessage('[•] quest '..quest..':'..questStep..' set to '..target..'.', player) 20 | end 21 | } -------------------------------------------------------------------------------- /source/commands/!roomlog.lua: -------------------------------------------------------------------------------- 1 | chatCommands.roomlog = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player) 4 | players[player].roomLog = not players[player].roomLog 5 | chatMessage('[•] roomLog status: '..tostring(players[player].roomLog), player) 6 | end 7 | } -------------------------------------------------------------------------------- /source/commands/!setgravity.lua: -------------------------------------------------------------------------------- 1 | chatCommands.setgravity = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local gravity = tonumber(args[1]) 5 | room.map.gravity = gravity 6 | TFM.setWorldGravity(room.map.wind, room.map.gravity) 7 | 8 | chatMessage('[•] Done! Map gravity set to '..gravity..'.', player) 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!setwind.lua: -------------------------------------------------------------------------------- 1 | chatCommands.setwind = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local wind = tonumber(args[1]) 5 | room.map.wind = wind 6 | TFM.setWorldGravity(room.map.wind, room.map.gravity) 7 | 8 | chatMessage('[•] Done! Map wind set to '..wind..'.', player) 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!shop.lua: -------------------------------------------------------------------------------- 1 | chatCommands.shop = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | showNPCShop(player, args[1]) 5 | end 6 | } -------------------------------------------------------------------------------- /source/commands/!sidequest.lua: -------------------------------------------------------------------------------- 1 | chatCommands.sidequest = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local nextQuest = tonumber(args[1]) 5 | if not sideQuests[nextQuest] then return chatMessage('[•] invalid sidequest ID.', player) end 6 | local target = string_nick(args[2]) 7 | if not players[target] then target = player end 8 | 9 | sideQuest_new(target, nextQuest) 10 | savedata(target) 11 | chatMessage('[•] Done! Side Quest '..nextQuest..' set to '..target..'.', player) 12 | end 13 | } -------------------------------------------------------------------------------- /source/commands/!snow.lua: -------------------------------------------------------------------------------- 1 | chatCommands.snow = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player, args) 4 | local duration = tonumber(args[1]) or 0 5 | local snowballPower = tonumber(args[2]) or 0 6 | 7 | TFM.snow(duration, snowballPower) 8 | chatMessage('[•] Done! Snowing for '..duration..' seconds', player) 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!spawn.lua: -------------------------------------------------------------------------------- 1 | chatCommands.spawn = { 2 | permissions = {'admin', 'mod', 'helper'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) 5 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 6 | chatMessage('[•] moving '..target..' to spawn...', player) 7 | players[target].place = 'town' 8 | killPlayer(target) 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!teleport.lua: -------------------------------------------------------------------------------- 1 | local _bindMouse = {} 2 | chatCommands.teleport = { 3 | permissions = {'admin'}, 4 | event = function(player) 5 | if not _bindMouse[player] then 6 | _bindMouse[player] = false 7 | end 8 | _bindMouse[player] = not _bindMouse[player] 9 | system.bindMouse(player, _bindMouse[player]) 10 | chatMessage('[•] Done! Teleport '.. (_bindMouse[player] and 'enabled' or 'disabled'), player) 11 | end 12 | } -------------------------------------------------------------------------------- /source/commands/!title.lua: -------------------------------------------------------------------------------- 1 | chatCommands.title = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[2]) 5 | local id = args[1] 6 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 7 | system.giveEventGift(target, id) 8 | 9 | chatMessage('[•] Done! Title '..id..' given to '..target..'.', player) 10 | end 11 | } -------------------------------------------------------------------------------- /source/commands/!trade.lua: -------------------------------------------------------------------------------- 1 | chatCommands.trade = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local player1 = string_nick(args[1]) or player 5 | local player2 = string_nick(args[2]) 6 | if not player2 then return end 7 | tradeSystem.invite(player1, player2) 8 | end 9 | } -------------------------------------------------------------------------------- /source/commands/!unban.lua: -------------------------------------------------------------------------------- 1 | chatCommands.unban = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) or args[1] 5 | for i, banned in next, room.bannedPlayers do 6 | if banned == target then 7 | table_remove(room.bannedPlayers, i) 8 | translatedMessage('playerUnbannedFromRoom', target) 9 | respawnPlayer(target) 10 | room.fileUpdated = true 11 | return 12 | end 13 | end 14 | translatedMessage('[•] '..target..' hadn\'t been banned.', player) 15 | end 16 | } -------------------------------------------------------------------------------- /source/commands/!update.lua: -------------------------------------------------------------------------------- 1 | chatCommands.update = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | if not syncData.connected then return chatMessage('[•] Failed to update. Reason: Data not synced.', player) end 5 | local msg = args[1] and table_concat(args, ' ') or '' 6 | syncData.updating.updateMessage = msg 7 | saveGameData('Sharpiebot#0000') 8 | chatMessage('[•] Update requested. Message: '..msg, player) 9 | end 10 | } -------------------------------------------------------------------------------- /source/commands/!updatesidequest.lua: -------------------------------------------------------------------------------- 1 | chatCommands.updatesidequest = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local value = tonumber(args[1]) 5 | if not value then return chatMessage('[•] invalid value.', player) end 6 | local target = string_nick(args[2]) 7 | if not players[target] then target = player end 8 | 9 | sideQuest_update(target, value) 10 | savedata(target) 11 | chatMessage('[•] Done! Side Quest updated to '..target..'.', player) 12 | end 13 | } -------------------------------------------------------------------------------- /source/commands/!whitelist.lua: -------------------------------------------------------------------------------- 1 | chatCommands.whitelist = { 2 | permissions = {'admin'}, 3 | event = function(player, args) 4 | local target = string_nick(args[1]) 5 | if not players[target] then return chatMessage('[•] $playerName not found.', player) end 6 | players[target].lucky[2] = not players[target].lucky[2] 7 | savedata(target) 8 | chatMessage('[•] Done! '..target..' is '.. (players[target].lucky[2] and 'not' or 'now') ..' whitelisted.', player) 9 | end 10 | } -------------------------------------------------------------------------------- /source/dayPeriods.lua: -------------------------------------------------------------------------------- 1 | loadFound = function(player, house) 2 | local id = tonumber(house) 3 | local align = room.event ~= '' and room.specialBackgrounds[room.event].align or 1919 4 | removeGroupImages(players[player].dayImgs) 5 | local img = background(nil, nil, nil, true) 6 | for i = 1, 3 do 7 | players[player].dayImgs[#players[player].dayImgs+1] = addImage(img, '?1', ((id-1)%id)*1500 - 1200 + (i-1)*align, 320, player) 8 | end 9 | end 10 | 11 | background = function(player, period, rain, getPng) 12 | if not period then period = room.gameDayStep end 13 | local png = nil 14 | local align = nil 15 | local yalign = -1000 16 | 17 | if not room.event or room.event == '' then 18 | align = 1919 19 | local bgColor 20 | if period == 'day' then 21 | png = '1724c10adda.jpg' 22 | bgColor = "#608EC6" 23 | elseif period == 'evening' then 24 | png = '1724c1daa44.jpg' 25 | bgColor = "#FBA676" 26 | elseif period == 'night' then 27 | png = '16baeb0ead4.jpg' 28 | bgColor = "#58235d" 29 | elseif period == 'dawn' then 30 | png = '16b80619ab9.jpg' 31 | bgColor = "#2A287b" 32 | end 33 | 34 | ui.setBackgroundColor(bgColor) 35 | else 36 | png = room.specialBackgrounds[room.event][period] 37 | align = room.specialBackgrounds[room.event].align 38 | ui.setBackgroundColor(room.specialBackgrounds[room.event].uiBackground[period]) 39 | end 40 | 41 | if getPng then return png end 42 | 43 | removeGroupImages(players[player].background) 44 | players[player].background = {} 45 | 46 | if png then 47 | for i = 1, 11 do 48 | players[player].background[#players[player].background+1] = addImage(png, '?1', (i-1)*align, 6405, player) 49 | players[player].background[#players[player].background+1] = addImage(png, '?1', (i-1)*align, 0 + yalign, player) 50 | end 51 | players[player].background[#players[player].background+1] = addImage(png, '?1', 4000, 3000, player) 52 | players[player].background[#players[player].background+1] = addImage(png, '?1', 4000+align, 3000, player) 53 | 54 | for i = 1, 3 do 55 | players[player].background[#players[player].background+1] = addImage(png, '?1', 6700+(i-1)*align, 4830, player) -- police station 56 | players[player].background[#players[player].background+1] = addImage(png, '?1', 4500+(i-1)*align, 4920 + yalign, player) 57 | players[player].background[#players[player].background+1] = addImage(png, '?1', 8230+(i-1)*align, 3900, player) 58 | end 59 | if period == 'night' then 60 | players[player].background[#players[player].background+1] = addImage("16b952d1012.png", "!9999", 4500, 4920 + yalign, player) 61 | end 62 | end 63 | end 64 | 65 | loadDayTimeEffects = function(period) 66 | if period == 'night' then 67 | gameNpcs.hideNPC('Colt') 68 | elseif period == 'day' then 69 | gameNpcs.showNPC('Colt') 70 | removeGroupImages(room.bankImages) 71 | removeGroupImages(room.bank.paperImages) 72 | room.bankBeingRobbed = false 73 | room.bankRobStep = nil 74 | room.bankPassword = random(0,9) .. random(0,9) .. random(0,9) .. random(0,9) 75 | room.dayCounter = room.dayCounter + 1 76 | if room.dayCounter > 0 then 77 | room.bank.paperImages = {} 78 | room.bank.paperCurrentPlace = random(1, #room.bank.paperPlaces) 79 | room.bank.paperImages[#room.bank.paperImages+1] = addImage('16bbf3aa649.png', '!1', room.bank.paperPlaces[room.bank.paperCurrentPlace].x, room.bank.paperPlaces[room.bank.paperCurrentPlace].y) 80 | showTextArea(-3333, ''..string.rep('\n', 10), nil, room.bank.paperPlaces[room.bank.paperCurrentPlace].x, room.bank.paperPlaces[room.bank.paperCurrentPlace].y, 20, 20, 0, 0, 0) 81 | end 82 | end 83 | room.gameDayStep = period 84 | 85 | closePlaces() 86 | for i, v in next, ROOM.playerList do 87 | background(i, room.gameDayStep) 88 | if players[i] then 89 | if players[i].place:find('house_') then 90 | house = players[i].place:sub(7) 91 | loadFound(i, house) 92 | end 93 | end 94 | if period == 'day' then 95 | showTextArea(1029, '

' .. translate('goTo', i) .. '', i, 2670, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.3) 96 | end 97 | end 98 | end -------------------------------------------------------------------------------- /source/events/ChatCommand.lua: -------------------------------------------------------------------------------- 1 | onEvent("ChatCommand", function(player, command) 2 | if player and isExploiting[player] then return end 3 | if room.gameMode then return end 4 | if room.isInLobby then return end 5 | if not players[player].dataLoaded then return end 6 | 7 | local args = {} 8 | for i in command:gmatch('%S+') do 9 | args[#args+1] = i 10 | end 11 | local command = table_remove(args, 1):lower() 12 | if chatCommands[command] then 13 | local continue = false 14 | if not chatCommands[command].permissions then 15 | continue = true 16 | else 17 | for _, role in next, chatCommands[command].permissions do 18 | if table_find(mainAssets.roles[role], player) then 19 | continue = true 20 | break 21 | end 22 | end 23 | end 24 | if continue then 25 | chatCommands[command].event(player, args) 26 | end 27 | end 28 | end) -------------------------------------------------------------------------------- /source/events/EmotePlayed.lua: -------------------------------------------------------------------------------- 1 | onEvent('EmotePlayed', function(player, emote) 2 | if player and isExploiting[player] then return end 3 | if room.gameMode then return end 4 | if room.isInLobby then return end 5 | if emote ~= 11 and players[player].fishing[1] then 6 | stopFishing(player) 7 | end 8 | end) -------------------------------------------------------------------------------- /source/events/FileLoaded.lua: -------------------------------------------------------------------------------- 1 | onEvent("FileLoaded", function(file, data) 2 | local datas = {} 3 | for _data in string.gmatch(data, '[^%|]+') do 4 | datas[#datas+1] = _data 5 | end 6 | 7 | if tonumber(file) == 5 then -- RANKING 8 | if true then return end 9 | mainAssets.fileCopy._ranking = datas[(mainAssets.season%2 == 0 and 1 or 2)] 10 | local rankData = datas[(mainAssets.season%2 == 0 and 2 or 1)] 11 | room.globalRanking = {} 12 | 13 | if rankData then 14 | for name, level, experience, commu, id in string.gmatch(rankData, '([%w_+]+#%d+),(%d+),(%d+),(%w+),(%d+)') do 15 | room.globalRanking[#room.globalRanking+1] = {name = name, level = level, experience = experience, commu = commu, id = id} 16 | end 17 | end 18 | saveRanking() 19 | removeGroupImages(room.rankingImages) 20 | loadRanking() 21 | 22 | elseif tonumber(file) == 30 then -- Christmas 2021 23 | local rankData = datas[1] 24 | room.globalRanking = {} 25 | 26 | if rankData then 27 | for name, level, gifts, commu, id in string.gmatch(rankData, '([%w_+]+#%d+),(%d+),(%d+),(%w+),(%d+)') do 28 | room.globalRanking[#room.globalRanking+1] = {name = name, level = level, gifts = gifts, commu = commu, id = id} 29 | end 30 | end 31 | 32 | saveRanking() 33 | removeGroupImages(room.rankingImages) 34 | loadRanking() 35 | 36 | elseif tonumber(file) == 1 then 37 | local bannedPlayers = datas[1] or table_concat(room.bannedPlayers, ';') 38 | local unrankedPlayers = datas[2] or table_concat(room.unranked, ';') 39 | local admin = datas[3] or '' 40 | local mod = datas[4] or '' 41 | local helper = datas[5] or '' 42 | local moduleTeam = datas[6] or '' 43 | 44 | room.bannedPlayers = {} 45 | for player in string.gmatch(bannedPlayers, '([%w_+]+#%d+),(%w+)') do 46 | room.bannedPlayers[#room.bannedPlayers+1] = player 47 | if players[player] then 48 | killPlayer(player) 49 | end 50 | end 51 | 52 | room.unranked = {} 53 | for player in string.gmatch(unrankedPlayers, '([%w_+]+#%d+),(%w+)') do 54 | room.unranked[#room.unranked+1] = player 55 | end 56 | 57 | for index, role in next, {admin, mod, helper, moduleTeam} do 58 | local _role = (index == 1 and 'admin') or (index == 2 and 'mod') or (index == 3 and 'helper') or 'moduleTeam' 59 | mainAssets.roles[_role] = {} 60 | for player in string.gmatch(role, '([%w_+]+#%d+)') do 61 | mainAssets.roles[_role][#mainAssets.roles[_role]+1] = player 62 | end 63 | end 64 | end 65 | end) -------------------------------------------------------------------------------- /source/events/Keyboard.lua: -------------------------------------------------------------------------------- 1 | onEvent("Keyboard", function(player, key, down, x, y) 2 | if player and isExploiting[player] then return end 3 | if room.gameMode then return end 4 | if room.isInLobby then return end 5 | local playerInfo = players[player] 6 | if not playerInfo then return end 7 | if down then 8 | if playerInfo.canDrive then 9 | if key == 2 or key == 0 then 10 | removeCarImages(player) 11 | playerInfo.driving = true 12 | playerInfo.currentCar.direction = key == 2 and 1 or 2 13 | -- Get the vehicle's data 14 | local vehicleData = mainAssets.__cars[playerInfo.selectedCar] 15 | -- Check if the vehicle has images of the left and right sides 16 | local mirrorImage = playerInfo.currentCar.direction == 2 17 | -- If the vehicle has images from both sides, return them or mirror the main one 18 | local vehicleImage = vehicleData.image 19 | local x = vehicleData.x + (mirrorImage and (vehicleData.size and vehicleData.size[1]) or 0) 20 | local y = vehicleData.y 21 | playerInfo.carImages[#playerInfo.carImages+1] = addImage(vehicleImage, "$"..player, x, y, nil, mirrorImage and -1 or 1) 22 | 23 | elseif key == 3 then 24 | playerInfo.currentCar.direction = 0 25 | elseif key == 1 then 26 | if playerInfo.driving and mainAssets.__cars[playerInfo.selectedCar].type ~= 'boat' then 27 | if mainAssets.__cars[playerInfo.selectedCar].type ~= 'air' then 28 | checkIfPlayerIsDriving(player) 29 | else 30 | playerInfo.driving = true 31 | playerInfo.currentCar.direction = 3 32 | end 33 | end 34 | elseif key == 32 and mainAssets.__cars[playerInfo.selectedCar].type == 'air' then 35 | checkIfPlayerIsDriving(player) 36 | return 37 | end 38 | end 39 | 40 | if key == 32 then 41 | if playerInfo.job == 'fisher' and not playerInfo.fishing[1] then 42 | if not playerInfo.selectedCar or mainAssets.__cars[playerInfo.selectedCar].type ~= 'car' then 43 | local biome = false 44 | for place, settings in next, room.fishing.biomes do 45 | if math_range(settings.location, {x = x, y = y}) then 46 | biome = place 47 | break 48 | end 49 | end 50 | if biome then 51 | playerFishing(player, x, y, biome) 52 | else 53 | chatMessage(''..translate('fishWarning', player), player) 54 | end 55 | end 56 | elseif playerInfo.job == 'police' then 57 | if playerInfo.time > os_time() then return chatMessage(''..translate('copError', player), player) end 58 | if playerInfo.questLocalData.other.arrestRobber then 59 | if math_hypo(x, y, 1930, 8530) <= 60 then 60 | arrestPlayer('Robber', player) 61 | return 62 | end 63 | end 64 | for i, v in next, ROOM.playerList do 65 | if math_hypo(x, y, v.x, v.y) <= 60 and i ~= player and not ROOM.playerList[player].isDead and not v.isDead then 66 | if players[i].job == 'thief' and players[i].robbery.robbing or players[i].robbery.escaped then 67 | if playerInfo.place == players[i].place and not players[i].robbery.usingShield then 68 | arrestPlayer(i, player) 69 | break 70 | end 71 | end 72 | end 73 | end 74 | elseif playerInfo.job == 'thief' then 75 | if not playerInfo.robbery.robbing then 76 | for i, v in next, gameNpcs.robbing do 77 | if gameNpcs.characters[i].visible then 78 | if math_hypo(v.x, v.y, x, y) <= 60 then 79 | startRobbery(player, i) 80 | break 81 | end 82 | end 83 | end 84 | end 85 | end 86 | elseif key <= 3 then 87 | if playerInfo.fishing[1] then 88 | stopFishing(player) 89 | end 90 | 91 | -- "B" Key 92 | elseif key == 66 then 93 | openBag(player) 94 | 95 | -- "C" Key 96 | elseif key == 67 then 97 | -- openSettings(player) 98 | 99 | -- "P" Key 100 | elseif key == 80 then 101 | openProfile(player) 102 | 103 | -- "Q" Key 104 | elseif key == 81 then 105 | openQuests(player) 106 | 107 | elseif key >= 70 and key <= 72 then 108 | local vehicleType = key-69 109 | local car = playerInfo.favoriteCars[vehicleType] 110 | drive(player, car) 111 | end 112 | end 113 | end) -------------------------------------------------------------------------------- /source/events/Loop.lua: -------------------------------------------------------------------------------- 1 | onEvent("Loop", function() 2 | if GAME_PAUSED then return end 3 | if room.gameMode then return end 4 | if room.started then 5 | room.currentGameHour = room.currentGameHour + 1 6 | checkWorkingTimer() 7 | if room.currentGameHour%15 == 0 then 8 | updateHour() 9 | elseif room.currentGameHour == 1440 then 10 | room.currentGameHour = 0 11 | end 12 | HouseSystem.gardening() 13 | end 14 | if ROOM.uniquePlayers >= room.requiredPlayers then 15 | if room.isInLobby then 16 | genMap() 17 | removeTextArea(0, nil) 18 | removeTextArea(1, nil) 19 | end 20 | else 21 | if not room.isInLobby then 22 | genLobby() 23 | removeTextArea(0, nil) 24 | removeTextArea(1, nil) 25 | end 26 | end 27 | end) -------------------------------------------------------------------------------- /source/events/Mouse.lua: -------------------------------------------------------------------------------- 1 | onEvent("Mouse", function(player, x, y) 2 | if player and isExploiting[player] then return end 3 | movePlayer(player, x, y, false) 4 | chatMessage('X: '..x..', Y: '..y, player) 5 | end) -------------------------------------------------------------------------------- /source/events/PlayerBonusGrabbed.lua: -------------------------------------------------------------------------------- 1 | onEvent('PlayerBonusGrabbed', function(player, bonusId) 2 | if player and isExploiting[player] then return end 3 | TouchSensor.triggered(player, bonusId) 4 | end) -------------------------------------------------------------------------------- /source/events/PlayerDied.lua: -------------------------------------------------------------------------------- 1 | onEvent("PlayerDied", function(player) 2 | if player and isExploiting[player] then return end 3 | if room.gameMode then return end 4 | if room.isInLobby or not players[player] or players[player].editingHouse or checkLocation_isInHouse(player) then return end 5 | if table_find(room.bannedPlayers, player) then return end 6 | wasDriving = players[player].driving 7 | checkIfPlayerIsDriving(player) 8 | respawnPlayer(player) 9 | if players[player].place == 'island' then 10 | movePlayer(player, 9350, 1944+room.y, false) 11 | else 12 | players[player].place = 'town' 13 | if wasDriving then 14 | movePlayer(player, 6240, 1944+room.y, false) 15 | end 16 | end 17 | end) -------------------------------------------------------------------------------- /source/events/PlayerLeft.lua: -------------------------------------------------------------------------------- 1 | onEvent("PlayerLeft", function(player) 2 | if player and isExploiting[player] then return end 3 | if room.isInLobby then return end 4 | local playerData = players[player] 5 | if playerData.trading then 6 | tradeSystem.endTrade(tradeSystem.trades[playerData.tradeId], false, player) 7 | end 8 | HouseSystem.new(player):removeHouse() 9 | if playerData.robbery.robbing then 10 | removeTimer(playerData.timer) 11 | arrestPlayer(player, 'AUTO') 12 | giveCoin(-300, player) 13 | end 14 | if playerData.job then 15 | job_fire(player) 16 | end 17 | if playerData.fishing[1] then 18 | stopFishing(player) 19 | end 20 | 21 | if playerData.dataLoaded then 22 | savedata(player, true) 23 | end 24 | setPlayerData(player) 25 | end) -------------------------------------------------------------------------------- /source/events/PlayerRespawn.lua: -------------------------------------------------------------------------------- 1 | onEvent("PlayerRespawn", function(player) 2 | if room.gameMode then return end 3 | if room.isInLobby then return end 4 | if not player then return end 5 | if not players[player] then return end 6 | if not players[player].dataLoaded then return end 7 | if isExploiting[player] then return end 8 | 9 | --[[if lastRevive[player] then 10 | if lastRevive[player] > os_time()-10000 and not players[player].editingHouse then 11 | isExploiting[player] = true 12 | return 13 | end 14 | end]] 15 | lastRevive[player] = os_time() 16 | 17 | local level = players[player].level[1] 18 | for i, v in next, ROOM.playerList do 19 | generateLevelImage(player, level, i) 20 | end 21 | end) -------------------------------------------------------------------------------- /source/gameHour.lua: -------------------------------------------------------------------------------- 1 | hourOfClock = function() 2 | local hour = floor(24 * (room.currentGameHour / 1440)) 3 | local min = (room.currentGameHour % 60) 4 | hour = (hour + 12) % 24 5 | return string.format("%.2d:%.2d", hour, min) 6 | end 7 | 8 | checkGameHour = function(hour) 9 | if hour == '-' then return true end 10 | local time = hourOfClock() 11 | time = time:gsub(':', '') 12 | time = tonumber(time) 13 | hour = hour:gsub(':', '') 14 | local opened, closed = hour:match('(%d+) (%d+)') 15 | return time > tonumber(opened) and time < tonumber(closed) 16 | end 17 | 18 | updateHour = function(player, arg) 19 | local time = hourOfClock() 20 | 21 | if arg then 22 | return time 23 | else 24 | showTextArea(1457, '

'..time, player, 2100-2, 8718-1185+11, 120, 70, 0x1, 0x1, 0) 25 | if time == '17:00' then 26 | loadDayTimeEffects('evening') 27 | elseif time == '19:00' then 28 | loadDayTimeEffects('night') 29 | elseif time == '05:00' then 30 | loadDayTimeEffects('dawn') 31 | elseif time == '07:00' then 32 | loadDayTimeEffects('day') 33 | end 34 | end 35 | end 36 | 37 | formatDaysRemaining = function(calc, ended) 38 | local daysfrom = os.difftime(os_time(), calc) / (24 * 60 * 60) / 1000 39 | if not ended then 40 | return abs(floor(daysfrom)) 41 | else 42 | if floor(daysfrom) >= 0 then 43 | return true 44 | end 45 | end 46 | end -------------------------------------------------------------------------------- /source/houseSystem/_expansions.lua: -------------------------------------------------------------------------------- 1 | HouseSystem.expansions = { 2 | [0] = { 3 | name = 'grass', 4 | png = '16c0abef269.png', 5 | price = 100, 6 | }, 7 | [1] = { 8 | name = 'pool', 9 | png = '16c0abf2610.png', 10 | price = 2000, 11 | add = function(owner, y, terrainID, plotID, guest) 12 | room.houseImgs[terrainID].expansions[#room.houseImgs[terrainID].expansions+1] = addImage('16bc4577c60.png', '!1', (terrainID-1)*1500+737-(175/2) + (plotID-1)*175, y+170-30, guest) 13 | end, 14 | }, 15 | [2] = { 16 | name = 'garden', 17 | png = '16c0abf41c9.png', 18 | price = 4000, 19 | add = function(owner, y, terrainID, plotID, guest) 20 | if players[owner].houseTerrainPlants[plotID] == 0 then players[owner].houseTerrainPlants[plotID] = 1 end 21 | local stage = HouseSystem.plants[players[owner].houseTerrainPlants[plotID]].stages[players[owner].houseTerrainAdd[plotID]] 22 | room.houseImgs[terrainID].expansions[#room.houseImgs[terrainID].expansions+1] = addImage(stage, '!200000', (terrainID-1)*1500+738-(175/2) + (plotID-1)*175, y+170-45-275, guest) 23 | if owner == 'Oliver' then 24 | room.houseImgs[terrainID].expansions[#room.houseImgs[terrainID].expansions+1] = addImage(stage, '?10', 11330 + (plotID-1)*65, 7470+30, guest) 25 | end 26 | end, 27 | }, 28 | } -------------------------------------------------------------------------------- /source/houseSystem/_new.lua: -------------------------------------------------------------------------------- 1 | HouseSystem = { } 2 | HouseSystem.__index = HouseSystem 3 | 4 | HouseSystem.new = function(player) 5 | local self = { 6 | y = 1590, 7 | houseOwner = player, 8 | } 9 | return setmetatable(self, HouseSystem) 10 | end -------------------------------------------------------------------------------- /source/houseSystem/_plants.lua: -------------------------------------------------------------------------------- 1 | HouseSystem.plants = { 2 | [0] = { -- default 3 | name = '???', 4 | growingTime = 0, 5 | stages = {'16bf63634a0.png'}, 6 | quantyOfSeeds = 0, 7 | }, 8 | [1] = { -- tomato 9 | name = 'tomato', 10 | growingTime = 60*3, 11 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16bf64806c6.png', '16bf64b8df5.png', '16c2544e15f.png', '16c2546d829.png'}, 12 | quantyOfSeeds = 5, 13 | pricePerSeed = 10, 14 | }, 15 | [2] = { -- oregano 16 | name = 'oregano', 17 | growingTime = 60*4, 18 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16bf64806c6.png', "16c2ad0f76a.png", "16c2acd5534.png"}, 19 | quantyOfSeeds = 5, 20 | pricePerSeed = 30, 21 | }, 22 | [3] = { -- lemon 23 | name = 'lemon', 24 | growingTime = 60*6, 25 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16bf64806c6.png', "16bfca9b802.png", "16bfcaa09ed.png", '16bfca975e5.png'}, 26 | quantyOfSeeds = 3, 27 | pricePerSeed = 120, 28 | }, 29 | [4] = { -- pepper 30 | name = 'pepper', 31 | growingTime = 60*3, 32 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16bf64806c6.png', '16c25569bf0.png', '16c2556b669.png', '16c2556cfb9.png'}, 33 | quantyOfSeeds = 5, 34 | pricePerSeed = 70, 35 | }, 36 | [5] = { -- luckyFlower 37 | name = 'luckyFlower', 38 | growingTime = 60*15, 39 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16c2580e482.png', '16c258100b7.png', '16c25811d3b.png', '16c25813c4c.png', '16c258182a0.png'}, 40 | quantyOfSeeds = 1, 41 | pricePerSeed = 10000, 42 | }, 43 | [6] = { -- wheat 44 | name = 'wheat', 45 | growingTime = 60*7, 46 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16c2ad99a4a.png', "16c2adf9395.png", "16d9c73c301.png"}, 47 | quantyOfSeeds = 5, 48 | pricePerSeed = 40, 49 | }, 50 | [7] = { -- pumpkin 51 | name = 'pumpkin', 52 | growingTime = 60*5, 53 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16da90fd0ad.png', '16da90fe81f.png', "16da905bd71.png"}, 54 | quantyOfSeeds = 1, 55 | pricePerSeed = 500, 56 | }, 57 | [8] = { -- blueberries 58 | name = 'blueberries', 59 | growingTime = 60*7, 60 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16bf64806c6.png', '16f1e9f4d55.png', '16f1e9fc472.png', "16f1ea01892.png"}, 61 | quantyOfSeeds = 2, 62 | pricePerSeed = 400, 63 | }, 64 | [9] = { -- banana 65 | name = 'banana', 66 | growingTime = 60*12.5, 67 | stages = {'16bf63634a0.png', '16bf64806c6.png', '17276940ecb.png', '1727693f16f.png', '1727693d907.png', "1727693bc5b.png"}, 68 | quantyOfSeeds = 2, 69 | pricePerSeed = 800, 70 | }, 71 | [10] = { -- luckyFlower - Cyan 72 | name = 'cyan_luckyFlower', 73 | growingTime = 60*15, 74 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '174ae579dd0.png', '174ae577cbb.png', '17498099287.png', '174980a3dae.png', '174980a9917.png'}, 75 | quantyOfSeeds = 1, 76 | pricePerSeed = 10000, 77 | }, 78 | [11] = { -- luckyFlower - Orange 79 | name = 'orange_luckyFlower', 80 | growingTime = 60*15, 81 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '174ae5a6858.png', '174ae5a9cdb.png', '174980cf5b5.png', '174980d12c7.png', '174980d3513.png'}, 82 | quantyOfSeeds = 1, 83 | pricePerSeed = 10000, 84 | }, 85 | [12] = { -- luckyFlower - Red 86 | name = 'red_luckyFlower', 87 | growingTime = 60*15, 88 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '174ae624905.png', '174ae627aa2.png', '174980fdfd2.png', '174980ffc6e.png', '174981023d8.png'}, 89 | quantyOfSeeds = 1, 90 | pricePerSeed = 10000, 91 | }, 92 | [13] = { -- luckyFlower - Purple 93 | name = 'purple_luckyFlower', 94 | growingTime = 60*15, 95 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '174ae5d3846.png', '174ae5d79d3.png', '17498129a80.png', '1749812bbd2.png', '1749812dbd1.png'}, 96 | quantyOfSeeds = 1, 97 | pricePerSeed = 10000, 98 | }, 99 | [14] = { -- luckyFlower - Green 100 | name = 'green_luckyFlower', 101 | growingTime = 60*15, 102 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '174ae7aea00.png', '174ae7b0f48.png', '174ae7b30ba.png', '174ae7b4aed.png', '174ae7b70ee.png'}, 103 | quantyOfSeeds = 1, 104 | pricePerSeed = 10000, 105 | }, 106 | [15] = { -- luckyFlower - Black 107 | name = 'black_luckyFlower', 108 | growingTime = 60*15, 109 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '174ae734bda.png', '174ae736b60.png', '174ae70674d.png', '174ae707fed.png', '174ae709bc6.png'}, 110 | quantyOfSeeds = 1, 111 | pricePerSeed = 10000, 112 | }, 113 | [16] = { -- strange pumpkin 114 | name = 'strangePumpkin', 115 | growingTime = 60*7, 116 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '16da90fd0ad.png', '1750fd174d4.png', "1750fd1904b.png", '1750fd156cf.png', '1750fd1ad00.png'}, 117 | quantyOfSeeds = 1, 118 | pricePerSeed = 1000, 119 | }, 120 | [17] = { -- raspberry 121 | name = 'raspberry', 122 | growingTime = 60*11, 123 | stages = {'16bf63634a0.png', '16bf63b93cf.png', '176886c0fef.png', '176886d0954.png', "176886c472a.png", '176886ccf32.png', '176886cecab.png'}, 124 | quantyOfSeeds = 2, 125 | pricePerSeed = 1300, 126 | }, 127 | } -------------------------------------------------------------------------------- /source/houseSystem/_terrainsPositions.lua: -------------------------------------------------------------------------------- 1 | mainAssets.__terrainsPositions = { 2 | {0100, 1596+room.y-12}, 3 | {0265, 1596+room.y-12}, 4 | {0660, 1596+room.y-12}, 5 | {0825, 1596+room.y-12}, 6 | {1400, 1596+room.y-12}, 7 | {2330, 1796+room.y-12}, 8 | {2330+165, 1796+room.y-12}, 9 | {2900, 1796+room.y-12}, 10 | {3065, 1796+room.y-12}, 11 | {3065+165, 1796+room.y-12}, 12 | {113000, 1796+room.y-12}, -- REMI 13 | {113000, 1796+room.y-12}, -- OLIVER 14 | {12100, 1796+room.y-12}, 15 | {12265, 1796+room.y-12}, 16 | {12265+165, 1796+room.y-12}, 17 | {12595, 1796+room.y-12}, 18 | } -------------------------------------------------------------------------------- /source/houseSystem/gardening.lua: -------------------------------------------------------------------------------- 1 | HouseSystem.gardening = function() 2 | for i, v in ipairs(room.gardens) do 3 | if players[v.owner].houseTerrainAdd[v.terrain] < #HouseSystem.plants[players[v.owner].houseTerrainPlants[v.terrain]].stages then 4 | local growingTime = HouseSystem.plants[players[v.owner].houseTerrainPlants[v.terrain]].growingTime*1000 5 | if os_time() - v.timer >= growingTime then 6 | players[v.owner].houseTerrainAdd[v.terrain] = players[v.owner].houseTerrainAdd[v.terrain]+1 7 | v.timer = os_time() 8 | HouseSystem.new(v.owner):genHouseGrounds() 9 | savedata(v.owner) 10 | end 11 | else 12 | local y = 1590 13 | if v.owner ~= 'Oliver' then 14 | showTextArea('-730'..(tonumber(v.terrain)..tonumber(players[v.owner].houseData.houseid)*10), '

'..translate('harvest', v.owner)..'

', v.owner, ((tonumber(v.idx)-1)%tonumber(v.idx))*1500+738-(175/2)-2 + (tonumber(v.terrain)-1)*175, y+150, 175, 150, 0xff0000, 0xff0000, 0) 15 | else 16 | for ii, vv in next, ROOM.playerList do 17 | if players[ii].job == 'farmer' then 18 | showTextArea('-730'..(tonumber(v.terrain)..tonumber(players[v.owner].houseData.houseid)*10), '

'..translate('harvest', ii)..'

', ii, ((tonumber(v.idx)-1)%tonumber(v.idx))*1500+738-(175/2)-2 + (tonumber(v.terrain)-1)*175, y+150, 175, 150, 0xff0000, 0xff0000, 0) 19 | end 20 | end 21 | end 22 | savedata(v.owner) 23 | table_remove(room.gardens, i) 24 | end 25 | end 26 | end 27 | 28 | HouseSystem.fertilize = function(player, speed) 29 | if not players[player].place:find('house_') then return end 30 | local house = tonumber(players[player].place:sub(7)) 31 | local owner = player 32 | 33 | if house == 12 then 34 | owner = 'Oliver' 35 | if players[player].job ~= 'farmer' then 36 | return 37 | end 38 | end 39 | 40 | if table_find(players[owner].houseTerrain, 2) then 41 | local x = ROOM.playerList[player].x 42 | local y = ROOM.playerList[player].y 43 | local idx = tonumber(players[owner].houseData.houseid) 44 | local yy = 1590 45 | for i, v in next, players[owner].houseTerrain do 46 | if v == 2 then 47 | if math_hypo(((idx-1)%idx)*1500+737 + (i-1)*175, yy+170, x, y) <= 90 then 48 | if players[owner].houseTerrainAdd[i] > 1 then 49 | for ii, vv in next, room.gardens do 50 | if vv.owner == owner then 51 | if vv.terrain == i then 52 | vv.timer = vv.timer - (speed * 60000) 53 | local sidequest = sideQuests[players[player].sideQuests[1]].type 54 | if string_find(sidequest, 'type:fertilize') then 55 | if (sidequest:find('oliver') and owner == 'Oliver') or not string_find(sidequest, 'oliver') then 56 | sideQuest_update(player, 1) 57 | end 58 | end 59 | return true 60 | end 61 | end 62 | end 63 | end 64 | end 65 | end 66 | end 67 | end 68 | 69 | return false 70 | end 71 | 72 | HouseSystem.removeCrop = function(player) 73 | if not players[player].place:find('house_') then return end 74 | local house = tonumber(players[player].place:sub(7)) 75 | local owner = player 76 | if house == 12 then return end 77 | if table_find(players[owner].houseTerrain, 2) then 78 | local x = ROOM.playerList[player].x 79 | local y = ROOM.playerList[player].y 80 | local idx = tonumber(players[owner].houseData.houseid) 81 | local yy = 1590 82 | for i, v in next, players[owner].houseTerrain do 83 | if v == 2 then 84 | if math_hypo(((idx-1)%idx)*1500+737 + (i-1)*175, yy+170, x, y) <= 90 then 85 | if players[owner].houseTerrainAdd[i] > 1 then 86 | for ii, vv in next, room.gardens do 87 | if vv.owner == owner then 88 | if vv.terrain == i then 89 | removeTextArea('-730'..(i..(house*10))) 90 | players[owner].houseTerrainAdd[i] = 1 91 | players[owner].houseTerrainPlants[i] = 0 92 | HouseSystem.new(owner):genHouseGrounds() 93 | savedata(owner) 94 | table_remove(room.gardens, ii) 95 | return true 96 | end 97 | end 98 | end 99 | end 100 | end 101 | end 102 | end 103 | end 104 | end -------------------------------------------------------------------------------- /source/houseSystem/genHouseFace.lua: -------------------------------------------------------------------------------- 1 | HouseSystem.genHouseFace = function(self, guest) 2 | local ownerData = players[self.houseOwner] 3 | local terrainID = ownerData.houseData.houseid 4 | local houseType = ownerData.houseData.currentHouse 5 | local complement = self.houseOwner:match('#0000') and self.houseOwner:gmatch('(.-)#[0-9]+$')() or self.houseOwner:gsub('#', '#') 6 | 7 | local y = self.y 8 | if not guest then 9 | removeGroupImages(room.houseImgs[terrainID].img) 10 | end 11 | room.houseImgs[terrainID].img[#room.houseImgs[terrainID].img+1] = addImage(mainAssets.__houses[houseType].outside.icon, "?100"..terrainID, mainAssets.__terrainsPositions[terrainID][1] + mainAssets.__houses[houseType].outside.axis[1], mainAssets.__terrainsPositions[terrainID][2]+60 + mainAssets.__houses[houseType].outside.axis[2], guest) 12 | room.houseImgs[terrainID].img[#room.houseImgs[terrainID].img+1] = addImage('17272033fc9.png', "_600"..terrainID, mainAssets.__terrainsPositions[terrainID][1], mainAssets.__terrainsPositions[terrainID][2]+176, guest) 13 | 14 | showTextArea(44 + terrainID, '

'..complement..'\n', guest, mainAssets.__terrainsPositions[terrainID][1], mainAssets.__terrainsPositions[terrainID][2]+176+23, 150, nil, 0x1, 0x1, 0) 15 | showTextArea(terrainID, '

' .. terrainID, guest, mainAssets.__terrainsPositions[terrainID][1], mainAssets.__terrainsPositions[terrainID][2]+176+11, 150, nil, 0, 0) 16 | room.houseImgs[terrainID].img[#room.houseImgs[terrainID].img+1] = addImage(mainAssets.__houses[houseType].inside.image, "?100", (terrainID-1)*1500 + 60, 847, guest) 17 | room.houseImgs[terrainID].img[#room.houseImgs[terrainID].img+1] = addImage('17256286356.jpg', '?901', (terrainID-1)*1500 + 317, 1616, guest) -- door 18 | room.houseImgs[terrainID].img[#room.houseImgs[terrainID].img+1] = addImage('1725d43cb08.png', '_9020', (terrainID-1)*1500 + 317, 1616, guest) -- handle 19 | 20 | if mainAssets.__houses[houseType].inside.foreground then 21 | room.houseImgs[terrainID].img[#room.houseImgs[terrainID].img+1] = addImage(mainAssets.__houses[houseType].inside.foreground, "!10000", (terrainID-1)*1500 + 60, 847, guest) 22 | end 23 | 24 | for i, v in next, ownerData.houseData.furnitures.placed[ownerData.houseData.currentSaveSlot] do 25 | local x = v.x + (terrainID-1)*1500 26 | local y = v.y + 1000 27 | room.houseImgs[terrainID].furnitures[#room.houseImgs[terrainID].furnitures+1] = addImage(mainAssets.__furnitures[v.type].image, '?1000'..i, x, y, guest) 28 | local furniture = mainAssets.__furnitures[v.type] 29 | if furniture.grounds then 30 | furniture.grounds(x, y, - 7000 - (terrainID-1)*200 - i) 31 | end 32 | if furniture.usable then 33 | if not guest then 34 | showTextArea(- 85000 - (terrainID*200 + i), "" .. string.rep('\n', mainAssets.__furnitures[v.type].area[2]/8), self.houseOwner, x, y, mainAssets.__furnitures[v.type].area[1], mainAssets.__furnitures[v.type].area[2], 1, 0xfff000, 0, false, 35 | function(player) 36 | furniture.usable(player) 37 | end) 38 | if furniture.name == 'chest' or furniture.name == 'freezer' then 39 | players[self.houseOwner].houseData.chests.position[furniture.uniqueID] = {x = x, y = y} 40 | end 41 | end 42 | end 43 | end 44 | for i, v in next, ownerData.houseTerrain do 45 | if v == 2 then 46 | if ownerData.houseTerrainAdd[i] > 1 then 47 | room.gardens[#room.gardens+1] = {owner = self.houseOwner, timer = os_time(), terrain = i, idx = terrainID, plant = ownerData.houseTerrainPlants[i]} 48 | end 49 | end 50 | end 51 | 52 | if mainAssets.__houses[houseType].inside.grounds then 53 | mainAssets.__houses[houseType].inside.grounds(terrainID) 54 | end 55 | return setmetatable(self, HouseSystem) 56 | end -------------------------------------------------------------------------------- /source/houseSystem/genHouseGrounds.lua: -------------------------------------------------------------------------------- 1 | HouseSystem.genHouseGrounds = function(self, guest) 2 | local ownerData = players[self.houseOwner] 3 | local houseType = ownerData.houseData.currentHouse 4 | local terrainID = ownerData.houseData.houseid 5 | local y = self.y 6 | if not guest then 7 | removeGroupImages(room.houseImgs[terrainID].expansions) 8 | end 9 | for i = 1, 5 do 10 | if not ownerData.houseTerrain[i] then 11 | ownerData.houseTerrain[i] = 0 12 | ownerData.houseTerrainAdd[i] = 1 13 | ownerData.houseTerrainPlants[i] = 0 14 | end 15 | if HouseSystem.expansions[ownerData.houseTerrain[i]].add then 16 | HouseSystem.expansions[ownerData.houseTerrain[i]].add(self.houseOwner, 1590, terrainID, i, guest) 17 | end 18 | end 19 | return setmetatable(self, HouseSystem) 20 | end -------------------------------------------------------------------------------- /source/houseSystem/loadHouse.lua: -------------------------------------------------------------------------------- 1 | loadHouse = function(player, houseType, terrainID) 2 | if room.terrains[terrainID].owner then return alert_Error(player, 'error', 'alreadyLand') end 3 | 4 | if players[player].houseData.houseid > 0 then 5 | HouseSystem.new(player):removeHouse() 6 | end 7 | 8 | removeTextArea(24+terrainID) 9 | removeTextArea(44+terrainID) 10 | removeTextArea(terrainID) 11 | 12 | players[player].houseData.houseid = terrainID 13 | players[player].houseData.currentHouse = houseType 14 | 15 | room.terrains[terrainID].bought = true 16 | room.terrains[terrainID].owner = player 17 | room.terrains[terrainID].settings = {isClosed = false, permissions = {[player] = 4}} 18 | 19 | HouseSystem.new(player) 20 | :genHouseFace() 21 | :genHouseGrounds() 22 | end -------------------------------------------------------------------------------- /source/houseSystem/loadTerrains.lua: -------------------------------------------------------------------------------- 1 | HouseSystem.loadTerrains = function(self) 2 | local name = self.houseOwner 3 | local nameData = players[name] 4 | local forSaleSign = room.event ~= '' and room.specialBackgrounds[room.event].forSaleSign or '1708781ad73.png' 5 | if room.terrains[1] then 6 | for i = 1, #mainAssets.__terrainsPositions do 7 | if not room.terrains[i].bought then 8 | room.houseImgs[i].img[#room.houseImgs[i].img+1] = addImage(forSaleSign, "?"..i+100, mainAssets.__terrainsPositions[i][1], mainAssets.__terrainsPositions[i][2], name) 9 | showTextArea(44 + i, '' .. translate('sale', name), name, mainAssets.__terrainsPositions[i][1]+40, mainAssets.__terrainsPositions[i][2]+114, nil, nil, 0xFF0000, 0xFF0000, 0) 10 | else 11 | self.houseOwner = room.terrains[i].owner 12 | room.terrains[i].groundsLoadedTo[name] = false 13 | HouseSystem.genHouseFace(self, name) 14 | end 15 | end 16 | end 17 | return setmetatable(self, HouseSystem) 18 | end 19 | -------------------------------------------------------------------------------- /source/houseSystem/removeHouse.lua: -------------------------------------------------------------------------------- 1 | HouseSystem.removeHouse = function(self) 2 | local ownerData = players[self.houseOwner] 3 | if ownerData.houseData.houseid > 0 then 4 | local terrainID = ownerData.houseData.houseid 5 | for i = 1, 4 do 6 | removeTextArea('-730'..i..(ownerData.houseData.houseid*10)) 7 | removeGround(- 2000 - (terrainID-1)*30 - i) 8 | end 9 | ownerData.houseData.houseid = -10 10 | ownerData.houseData.currentHouse = nil 11 | removeGroupImages(room.houseImgs[terrainID].expansions) 12 | removeGroupImages(room.houseImgs[terrainID].furnitures) 13 | removeGroupImages(room.houseImgs[terrainID].img) 14 | for i = 0, 15 do 15 | removeGround(-6500+terrainID*20-i) 16 | end 17 | for i, v in next, ownerData.houseData.furnitures.placed[ownerData.houseData.currentSaveSlot] do 18 | local furniture = mainAssets.__furnitures[v.type] 19 | if furniture.grounds then 20 | removeGround(- 7000 - (terrainID-1)*200 - i) 21 | end 22 | end 23 | local forSaleSign = room.event ~= '' and room.specialBackgrounds[room.event].forSaleSign or '1708781ad73.png' 24 | room.houseImgs[terrainID].img[#room.houseImgs[terrainID].img+1] = addImage(forSaleSign, "?" .. terrainID + 100, mainAssets.__terrainsPositions[terrainID][1], mainAssets.__terrainsPositions[terrainID][2]) 25 | for name in next, ROOM.playerList do 26 | showTextArea(terrainID + 44, "" .. translate("sale", name), name, mainAssets.__terrainsPositions[terrainID][1]+40, mainAssets.__terrainsPositions[terrainID][2]+114, nil, nil, 0xFF0000, 0xFF0000, 0) 27 | end 28 | for guest in next, room.terrains[terrainID].guests do 29 | if room.terrains[terrainID].guests[guest] then 30 | leaveHouse(guest, terrainID) 31 | end 32 | end 33 | removeTextArea(terrainID) 34 | room.terrains[terrainID] = {img = {}, bought = false, owner = nil, settings = {}, groundsLoadedTo = {}, guests = {}} 35 | end 36 | return setmetatable(self, HouseSystem) 37 | end -------------------------------------------------------------------------------- /source/init.lua: -------------------------------------------------------------------------------- 1 | startRoom = function() 2 | players = {} 3 | 4 | for name in next, ROOM.playerList do 5 | eventNewPlayer(name) 6 | end 7 | 8 | if not room.isInLobby then 9 | room.terrains = {} 10 | room.houseImgs = {} 11 | room.gameLoadedTimes = room.gameLoadedTimes + 1 12 | 13 | for i = 1, #mainAssets.__terrainsPositions do 14 | room.terrains[i] = {img = {}, bought = false, owner = nil, settings = {}, groundsLoadedTo = {}, guests = {}} 15 | room.houseImgs[i] = {img = {}, furnitures = {}, expansions = {}} 16 | end 17 | room.started = true 18 | 19 | eventNewPlayer('Oliver') 20 | eventNewPlayer('Remi') 21 | 22 | removeTimer(room.temporaryTimer) 23 | if room.gameLoadedTimes == 1 then 24 | for i = 1, 2 do 25 | gameNpcs.setOrder(table_randomKey(gameNpcs.orders.canOrder)) 26 | end 27 | 28 | addTimer(function() 29 | for player in next, ROOM.playerList do 30 | players[player].timePlayed = players[player].timePlayed + 1 31 | updateLifeBar(player) 32 | end 33 | end, 60000, 0) 34 | end 35 | end 36 | end 37 | 38 | for resource, callback in next, initialization do 39 | callback() 40 | end 41 | 42 | initializingModule = false -------------------------------------------------------------------------------- /source/initialization/configCrops.lua: -------------------------------------------------------------------------------- 1 | initialization.Crops = function() 2 | for i, v in next, HouseSystem.plants do 3 | if bagItems[v.name] then 4 | bagItems[v.name].sellingPrice = bagItems[v.name].sellingPrice or v.pricePerSeed/10 5 | bagItems[v.name].isFruit = true 6 | end 7 | end 8 | end -------------------------------------------------------------------------------- /source/initialization/configDaveOffers.lua: -------------------------------------------------------------------------------- 1 | initialization.DaveOffers = function() 2 | daveOffers = {} 3 | local i = 1 4 | while #daveOffers < 5 do 5 | randomseed(room.mathSeed * i^2) 6 | local offerID = random(1, #mainAssets.__farmOffers) 7 | local nextItem = mainAssets.__farmOffers[offerID].item[1] 8 | local alreadySelling = false 9 | for id, offer in next, daveOffers do 10 | local item = mainAssets.__farmOffers[offer].item[1] 11 | if item == nextItem then 12 | alreadySelling = true 13 | end 14 | end 15 | if not alreadySelling then 16 | daveOffers[#daveOffers+1] = offerID 17 | end 18 | i = i + 1 19 | end 20 | end -------------------------------------------------------------------------------- /source/initialization/configFiles.lua: -------------------------------------------------------------------------------- 1 | initialization.Files = function() 2 | loadFile(1) 3 | if not mainAssets.isRankingActive then 4 | addTimer(function() 5 | if room.fileUpdated then 6 | syncFiles() 7 | room.fileUpdated = false 8 | else 9 | loadFile(1) 10 | end 11 | end, 15000, 0) 12 | else 13 | local lastFile = 30 14 | addTimer(function() 15 | if lastFile == 30 then 16 | if room.fileUpdated then 17 | syncFiles() 18 | room.fileUpdated = false 19 | else 20 | loadFile(1) 21 | end 22 | lastFile = 1 23 | elseif lastFile == 1 then 24 | loadFile(30) 25 | lastFile = 30 26 | end 27 | end, 15000, 0) 28 | end 29 | end -------------------------------------------------------------------------------- /source/initialization/configMine.lua: -------------------------------------------------------------------------------- 1 | initialization.Mine = function() 2 | for item, data in next, Mine.ores do 3 | bagItems['crystal_'..item].price = floor(200*(12/data.rarity)) 4 | bagItems['crystal_'..item].sellingPrice = floor(200*(12/data.rarity)) 5 | end 6 | 7 | mine_generate() 8 | end -------------------------------------------------------------------------------- /source/initialization/configPlaces.lua: -------------------------------------------------------------------------------- 1 | initialization.Places = function() 2 | for place, data in next, places do 3 | local placeToGo 4 | local placeToGoPosition 5 | for property, v in next, data do 6 | if property:find('tp_') then 7 | placeToGo = property:gsub('tp_', '') 8 | placeToGoPosition = v 9 | break 10 | end 11 | end 12 | 13 | if data.exitSensor then 14 | TouchSensor.add( 15 | 0, 16 | data.exitSensor[1], 17 | data.exitSensor[2], 18 | data.id, 19 | 0, 20 | false, 21 | 0, 22 | function(player) 23 | if players[player].place == placeToGo then return end 24 | movePlayer(player, placeToGoPosition[1], placeToGoPosition[2], false) 25 | players[player].place = placeToGo 26 | 27 | checkIfPlayerIsDriving(player) 28 | if placeToGo == 'mine' or placeToGo == 'mine_excavation' then 29 | setNightMode(player, false) 30 | else 31 | setNightMode(player, true) 32 | end 33 | 34 | for i, v in next, players[player].questLocalData.other do 35 | if i:lower():find(players[player].place:lower()) and i:find('goTo') then 36 | quest_updateStep(player) 37 | end 38 | end 39 | if data.afterExit then 40 | data.afterExit(player) 41 | end 42 | end, 43 | true 44 | ) 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /source/initialization/configRecipes.lua: -------------------------------------------------------------------------------- 1 | initialization.Recipes = function() 2 | for i, v in next, recipes do 3 | if v.require then 4 | newFoodValue(i) 5 | newEnergyValue(i) 6 | newDishPrice(i) 7 | end 8 | end 9 | end -------------------------------------------------------------------------------- /source/initialization/configRoom.lua: -------------------------------------------------------------------------------- 1 | initialization.Room = function() 2 | if ROOM.name == "*#mytest" or ROOM.isTribeHouse then 3 | room.requiredPlayers = 0 4 | elseif ROOM.name:find("@") then 5 | TFM.setRoomPassword('') 6 | room.requiredPlayers = 4 7 | else 8 | TFM.setRoomPassword('') 9 | if string.match(ROOM.name, "^*#mycity[1-9]$") then 10 | room.requiredPlayers = 2 11 | room.maxPlayers = 10 12 | end 13 | end 14 | 15 | if ROOM.uniquePlayers >= room.requiredPlayers then 16 | genMap() 17 | else 18 | genLobby() 19 | end 20 | 21 | setPlayerLimit(room.maxPlayers) 22 | end -------------------------------------------------------------------------------- /source/initialization/configShops.lua: -------------------------------------------------------------------------------- 1 | initialization.Shops = function() 2 | npcsStores.items = mergeItemsWithFurnitures(mainAssets.__furnitures, bagIds) 3 | buildNpcsShopItems() 4 | end -------------------------------------------------------------------------------- /source/initialization/configTimers.lua: -------------------------------------------------------------------------------- 1 | initialization.Timers = function() 2 | system.looping(function() 3 | if GAME_PAUSED then return end 4 | updateDialogs(4) 5 | timersLoop(250) 6 | end, 4) 7 | 8 | system.newTimer(function() 9 | if tonumber(os_date('%S'))%10 == 0 then 10 | loadPlayerData('Sharpiebot#0000') 11 | end 12 | end, 1000, true) 13 | end -------------------------------------------------------------------------------- /source/initialization/configVehicles.lua: -------------------------------------------------------------------------------- 1 | initialization.Vehicles = function() 2 | for id, data in next, mainAssets.__cars do 3 | if data.type == 'car' then 4 | local width = data.size[1] 5 | local leftWheel = width - data.wheels[2][1] - data.wheelsSize[2] 6 | local rightWheel = width - data.wheels[1][1] - data.wheelsSize[1] 7 | data.wheels = {data.wheels, {{leftWheel, data.wheels[2][2]}, {rightWheel, data.wheels[1][2]}}} 8 | end 9 | end 10 | end -------------------------------------------------------------------------------- /source/interfaces/errorAlert.lua: -------------------------------------------------------------------------------- 1 | alert_Error = function(player, title, text, ...) 2 | local title = lang.en[title] and translate(title, player) or title 3 | local text = lang.en[text] and translate(text, player) or text 4 | modernUI.new(player, 240, 120, title, text:format(...), 'errorUI') 5 | :build() 6 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showATM_Machine.lua: -------------------------------------------------------------------------------- 1 | modernUI.showATM_Machine = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = 290 7 | local y = (200 - height/2) + 28 8 | 9 | local writtenCode = {} 10 | 11 | showTextArea(id..(900), '

'..translate('code', player), player, 300, y+20, 200, 20, 0x314e57, 0x314e57, 0.8, true) 12 | 13 | local keys = {'QWERTYUIOP', 'ASDFGHJKL', 'ZXCVBNM'} 14 | for index, v in next, {{6, 56}, {17, 79}, {42, 102}} do 15 | for i = 1, #keys[index] do 16 | local letter = keys[index]:sub(i, i) 17 | showTextArea(id..(900+i+(13*(index-1))), "

"..letter, player, x + (i-1)*22 + v[1], y + v[2], nil, 15, 0, 0, 0, true, 18 | function() 19 | if #writtenCode < 15 then 20 | writtenCode[#writtenCode+1] = letter 21 | ui.updateTextArea(id..(900), '

'..table_concat(writtenCode, ''), player) 22 | end 23 | end) 24 | end 25 | end 26 | 27 | greenButton(id, 1, translate('submit', player), player, 28 | function() 29 | local code = table_concat(writtenCode, '') 30 | writtenCode = {} 31 | if codes[code] then 32 | for i, v in next, players[player].receivedCodes do 33 | if v == codes[code].id then 34 | ui.updateTextArea(id..(900), '

'..translate('codeAlreadyReceived', player), player) 35 | return 36 | end 37 | end 38 | if codes[code].available then 39 | if codes[code].level then 40 | if codes[code].level > players[player].level[1] then 41 | return alert_Error(player, 'error', 'codeLevelError', codes[code].level) 42 | end 43 | end 44 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 45 | players[player].receivedCodes[#players[player].receivedCodes+1] = codes[code].id 46 | codes[code].reward(player) 47 | return 48 | else 49 | ui.updateTextArea(id..(900), '

'..translate('codeNotAvailable', player), player) 50 | return 51 | end 52 | else 53 | ui.updateTextArea(id..(900), '

'..translate('incorrect', player), player) 54 | end 55 | end, 56 | 300, y + 160, 200, 12) 57 | 58 | return setmetatable(self, modernUI) 59 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showAvailableTradingPlayers.lua: -------------------------------------------------------------------------------- 1 | modernUI.showAvailableTradingPlayers = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) + 20 7 | local y = (200 - height/2) + 70 8 | local playerList = {} 9 | local i = 1 10 | 11 | for user in next, ROOM.playerList do 12 | if user ~= player and players[user] and players[user].dataLoaded and players[user].inRoom then 13 | showTextArea(id..(896+i), user, player, x+4 + (i-1)%2*173, y + floor((i-1)/2)*15, nil, nil, -1, 0xff0000, 0, true, 14 | function(player, i) 15 | showTextArea(id..'930', '

'..user..'', player, x+4 + (i-1)%2*173, y + floor((i-1)/2)*15, 150, 70, 0x432c04, 0x7a5817, 1, true) 16 | showTextArea(id..'931', translate('txt_openProfile', player), player, x+4 + (i-1)%2*173, y + 25 + floor((i-1)/2)*15, nil, nil, 0x432c04, 0x7a5817, 0, true, 17 | function() 18 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 19 | openProfile(player, user) 20 | end) 21 | showTextArea(id..'932', translate('trade_invitePlayer', player), player, x+4 + (i-1)%2*173, y + 25 + floor((i-1)/2)*15 + 15, nil, nil, 0x432c04, 0x7a5817, 0, true, 22 | function() 23 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 24 | if players[user].questStep[1] <= 4 then return alert_Error(player, 'error', 'trade_error_quest2', user, ''..translate('req_4', player)..'') end 25 | if players[player].questStep[1] <= 4 then return alert_Error(player, 'error', 'trade_error_quest', ''..translate('req_4', player)..'') end 26 | tradeSystem.invite(player, user) 27 | end) 28 | end, i) 29 | i = i + 1 30 | end 31 | end 32 | return setmetatable(self, modernUI) 33 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showBadgeInterface.lua: -------------------------------------------------------------------------------- 1 | modernUI.badgeInterface = function(self, badge) 2 | local id = self.id 3 | local player = self.player 4 | local x = (400 - 220/2) 5 | local y = (200 - 90/2) - 30 6 | 7 | local desc = badges[badge].season and translate('badgeDesc_season', player):format(badges[badge].season) or translate('badgeDesc_'..badge, player) 8 | 9 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(badges[badge] and badges[badge].png, "~70", 385, 180, player) 10 | showTextArea(id..'890', '

'..desc, player, x+10, y+100, 200, nil, 0, 0x24474, 0, true) 11 | 12 | return setmetatable(self, modernUI) 13 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showBagIcons.lua: -------------------------------------------------------------------------------- 1 | modernUI.showBagIcons = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) + 12 7 | local y = (200 - height/2) + 40 8 | local i = 0 9 | 10 | for index, v in next, bagIcons do 11 | local isCurrentIcon = index == players[player].currentBagIcon 12 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(v, "~20", x + (i%5)*45, y + floor(i/5)*45, player, nil, nil, nil, isCurrentIcon and 1 or .3) 13 | if not isCurrentIcon then 14 | showTextArea(id..(900+i*5), string.rep('\n', 5), player, x + (i%5)*45, y + floor(i/5)*45, 40, 29, 0, 1, 0, true, 15 | function() 16 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 17 | players[player].currentBagIcon = index 18 | savedata(player) 19 | loadBackpackIcon(player) 20 | end) 21 | end 22 | i = i + 1 23 | end 24 | return setmetatable(self, modernUI) 25 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showDaveOffers.lua: -------------------------------------------------------------------------------- 1 | modernUI.showDaveOffers = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) - 12 7 | local y = (200 - height/2) - 20 8 | 9 | for i, offerID in next, daveOffers do 10 | local offer = mainAssets.__farmOffers[offerID] 11 | 12 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage("1717eaef706.png", "~20", 288, y+65 + (i-1)*45, player) -- Background 13 | 14 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('1717f0a6947.png', "~21", 315, y+66 + (i-1)*45, player) -- Item background1 15 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(bagItems[offer.requires[1]].png, "~22", 310, y+60 + (i-1)*45, player) -- Required Item Image 16 | 17 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('171830fd281.png', "~25", 377, y+70 + (i-1)*45, player) -- Arrow 18 | 19 | showTextArea(id..(900+(i-1)*3), '

x'..offer.item[2], player, 447, y+86 + (i-1)*45, 30, nil, 0xff0000, 0xff0000, 0, true) 20 | 21 | if checkItemAmount(offer.requires[1], offer.requires[2], player) then 22 | showTextArea(id..(901+(i-1)*3), '

x'..offer.requires[2], player, 322, y+86 + (i-1)*45, 30, nil, 0xff0000, 0xff0000, 0, true) 23 | showTextArea(id..(902+(i-1)*3), "" .. string.rep('\n', 5), player, 320, y+65 + (i-1)*45, 155, 40, 0xff0000, 0xff0000, 0, true, 24 | function() 25 | if not checkItemAmount(offer.requires[1], offer.requires[2], player) then return end 26 | removeBagItem(offer.requires[1], offer.requires[2], player) 27 | addItem(offer.item[1], offer.item[2], player) 28 | sideQuest_sendTrigger(player, "trade_with_dave", 1) 29 | chatMessage(''..translate('transferedItem', player):format(''..translate('item_'..offer.item[1], player)..' ('..offer.item[2]..')'), player) 30 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 31 | end) 32 | else 33 | showTextArea(id..(901+(i-1)*3), '

x'..offer.requires[2], player, 322, y+86 + (i-1)*45, 30, nil, 0xff0000, 0xff0000, 0, true) 34 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage("1717eaef706.png", "~30", 288, y+65 + (i-1)*45, player) 35 | end 36 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('1717f0a6947.png', "~23", 440, y+66 + (i-1)*45, player) -- Item background1 37 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(bagItems[offer.item[1]].png, "~24", 435, y+60 + (i-1)*45, player) -- Final Item Image 38 | end 39 | return setmetatable(self, modernUI) 40 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showHousePermissions.lua: -------------------------------------------------------------------------------- 1 | modernUI.showHousePermissions = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) + 20 7 | local y = (200 - height/2) + 70 8 | local playerList = {} 9 | local i = 1 10 | local terrainID = players[player].houseData.houseid 11 | local function button(i, text, callback, x, y) 12 | local width = 150 13 | local height = 15 14 | showTextArea(id..(930+i*5), '', player, x-1, y-1, width, height, 0x95d44d, 0x95d44d, 1, true) 15 | showTextArea(id..(931+i*5), '', player, x+1, y+1, width, height, 0x1, 0x1, 1, true) 16 | showTextArea(id..(932+i*5), '', player, x, y, width, height, 0x44662c, 0x44662c, 1, true) 17 | showTextArea(id..(933+i*5), '

'..text..'\n', player, x-4, y-4, width+8, height+8, 0xff0000, 0xff0000, 0, true, callback) 18 | end 19 | for user in next, ROOM.playerList do 20 | if user ~= player and players[user] and players[user].inRoom then 21 | showTextArea(id..(896+i), user, player, x+4 + (i-1)%2*173, y + floor((i-1)/2)*15, nil, nil, -1, 0xff0000, 0, true, 22 | function(player, i) 23 | if not room.terrains[terrainID].settings.permissions[user] then room.terrains[terrainID].settings.permissions[user] = 0 end 24 | local userPermission = room.terrains[terrainID].settings.permissions[user] 25 | showTextArea(id..'930', '

'..user..'\n«'..translate("permissions_"..mainAssets.housePermissions[userPermission], player)..'»', player, x+4 + (i-1)%2*173, y + floor((i-1)/2)*15, 150, 70, 0x432c04, 0x7a5817, 1, true) 26 | local counter = 0 27 | for _ = -1, 1 do 28 | if _ ~= room.terrains[terrainID].settings.permissions[user] then 29 | showTextArea(id..(931+counter), translate('setPermission', player):format(translate('permissions_'..mainAssets.housePermissions[_], player)), player, x+4 + (i-1)%2*173, y + 25 + floor((i-1)/2)*15 + counter*15, nil, nil, 0x432c04, 0x7a5817, 0, true, 30 | function() 31 | if room.terrains[terrainID].settings.permissions[user] == _ then return end 32 | room.terrains[terrainID].settings.permissions[user] = _ 33 | for i = 930, 934 do 34 | removeTextArea(id..i, player) 35 | end 36 | if _ == -1 then 37 | if room.terrains[terrainID].guests[user] then 38 | leaveHouse(user, terrainID) 39 | alert_Error(user, 'error', 'error_blockedFromHouse', player) 40 | end 41 | end 42 | end) 43 | counter = counter + 1 44 | end 45 | end 46 | end, i) 47 | i = i + 1 48 | end 49 | end 50 | local function buttonAction(option) 51 | if option == 1 then 52 | if not room.terrains[terrainID].settings.isClosed then 53 | for guest in next, room.terrains[terrainID].guests do 54 | if room.terrains[terrainID].guests[guest] then 55 | if not room.terrains[terrainID].settings.permissions[guest] then room.terrains[terrainID].settings.permissions[guest] = 0 end 56 | if room.terrains[terrainID].settings.permissions[guest] < 1 then 57 | leaveHouse(guest, terrainID) 58 | alert_Error(guest, 'error', 'error_houseClosed', player) 59 | end 60 | end 61 | end 62 | end 63 | room.terrains[terrainID].settings.isClosed = not room.terrains[terrainID].settings.isClosed 64 | elseif option == 2 then 65 | room.terrains[terrainID].settings.permissions = {[player] = 4} 66 | end 67 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 68 | end 69 | for i, v in next, {room.terrains[terrainID].settings.isClosed and translate('houseSettings_unlockHouse', player) or translate('houseSettings_lockHouse', player), translate('houseSettings_reset', player)} do 70 | button(i, v, function() 71 | buttonAction(i) 72 | end, x + 12 + (i-1)*166, y + 175) 73 | end 74 | return setmetatable(self, modernUI) 75 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showHouseSlotsToChoose.lua: -------------------------------------------------------------------------------- 1 | modernUI.showHouseSlotsToChoose = function(self, houseId, terrainId) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) - 12 7 | local y = (200 - height/2) - 20 8 | 9 | for saveSlot = 1, 2 do 10 | local totalOfPlacedFurnitures = table_getLength(players[player].houseData.furnitures.placed[saveSlot]) 11 | 12 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage("1717eaef706.png", "~20", 288, y+65 + (saveSlot-1)*45, player) 13 | showTextArea(id..(900+(saveSlot-1)*3), '

'..translate('placedFurnitures', player):format(''..totalOfPlacedFurnitures..'/'..maxPlacedFurnitures..''), player, 320, y+88 + (saveSlot-1)*45, 155, nil, 0xff0000, 0xff0000, 0, true) 14 | showTextArea(id..(901+(saveSlot-1)*3), ''..translate("slot", player):format(saveSlot), player, 320, y+65 + (saveSlot-1)*45, 155, 40, 0xff0000, 0xff0000, 0, true) 15 | 16 | showTextArea(id..(902+(saveSlot-1)*3), "" .. string.rep('\n', 5), player, 320, y+65 + (saveSlot-1)*45, 155, 40, 0xff0000, 0xff0000, 0, true, 17 | function() 18 | players[player].houseData.currentSaveSlot = saveSlot 19 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 20 | loadHouse(player, houseId, terrainId) 21 | end) 22 | end 23 | 24 | return setmetatable(self, modernUI) 25 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showJobInterface.lua: -------------------------------------------------------------------------------- 1 | modernUI.jobInterface = function(self, job) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - 161/2) 7 | local y = (200 - 161/2) + 40 8 | local color = '#'..jobs[job].color 9 | local jobImage = jobs[job].icon 10 | 11 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('171d2f983ba.png', "~26", x+30, y-19, player) 12 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(jobImage, "~27", x, y-20, player) 13 | 14 | showTextArea(id..'884', '

'..translate(job, player), player, x+38, y-10, 110, 30, 0xff0000, 0xff0000, 0, true) 15 | 16 | return setmetatable(self, modernUI) 17 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showLevelOrb.lua: -------------------------------------------------------------------------------- 1 | modernUI.showLevelOrb = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) + 12 7 | local y = (200 - height/2) + 40 8 | local i = 0 9 | 10 | for _, v in next, players[player].starIcons.owned do 11 | local isCurrentOrb = v == players[player].starIcons.selected 12 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(mainAssets.levelIcons.star[v], "~20", x + (i%5)*57, y + floor(i/5)*57, player, nil, nil, nil, isCurrentOrb and 1 or .3) 13 | if not isCurrentOrb then 14 | showTextArea(id..(900+i*5), string.rep('\n', 5), player, x + (i%5)*57, y + floor(i/5)*40, 57, 57, 0, 0, 0, true, 15 | function() 16 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 17 | players[player].starIcons.selected = v 18 | savedata(player) 19 | local level = players[player].level[1] 20 | for i, v in next, ROOM.playerList do 21 | generateLevelImage(player, level, i) 22 | end 23 | end) 24 | end 25 | i = i + 1 26 | end 27 | return setmetatable(self, modernUI) 28 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showMill.lua: -------------------------------------------------------------------------------- 1 | modernUI.showMill = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) - 12 7 | local y = (200 - height/2) 8 | 9 | for i = 1, 3 do 10 | local amount = i > 1 and i*i or i 11 | local amount2 = amount*5 12 | 13 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage("1717eaef706.png", "~20", 288, y+65 + (i-1)*45, player) -- Background 14 | 15 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('1717f0a6947.png', "~21", 315, y+66 + (i-1)*45, player) -- Item background1 16 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(bagItems.wheat.png, "~22", 310, y+60 + (i-1)*45, player) -- Required Item Image 17 | 18 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('171830fd281.png', "~25", 377, y+70 + (i-1)*45, player) -- Arrow 19 | 20 | showTextArea(id..(900+(i-1)*3), '

x'..amount, player, 447, y+86 + (i-1)*45, 30, nil, 0xff0000, 0xff0000, 0, true) 21 | 22 | if checkItemAmount('wheat', amount2, player) then 23 | showTextArea(id..(901+(i-1)*3), '

x'..amount2, player, 322, y+86 + (i-1)*45, 30, nil, 0xff0000, 0xff0000, 0, true) 24 | showTextArea(id..(902+(i-1)*3), "" .. string.rep('\n', 5), player, 320, y+65 + (i-1)*45, 155, 40, 0xff0000, 0xff0000, 0, true, 25 | function() 26 | if not checkItemAmount('wheat', amount2, player) then return end 27 | removeBagItem('wheat', amount2, player) 28 | addItem('wheatFlour', amount, player) 29 | chatMessage(''..translate('transferedItem', player):format(''..translate('item_wheatFlour', player)..' ('..amount..')'), player) 30 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 31 | end) 32 | else 33 | showTextArea(id..(901+(i-1)*3), '

x'..amount2, player, 322, y+86 + (i-1)*45, 30, nil, 0xff0000, 0xff0000, 0, true) 34 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage("1717eaef706.png", "~30", 288, y+65 + (i-1)*45, player) 35 | end 36 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('1717f0a6947.png', "~23", 440, y+66 + (i-1)*45, player) -- Item background1 37 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(bagItems.wheatFlour.png, "~24", 435, y+60 + (i-1)*45, player) -- Final Item Image 38 | end 39 | return setmetatable(self, modernUI) 40 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showNewLevelOrb.lua: -------------------------------------------------------------------------------- 1 | modernUI.showNewLevelOrb = function(self, orb) 2 | local id = self.id 3 | local player = self.player 4 | local x = (400 - 220/2) 5 | local y = (200 - 90/2) - 30 6 | 7 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(mainAssets.levelIcons.star[orb], "~70", 370, 145, player) 8 | showTextArea(id..'890', '

'..translate('newLevelOrb_info', player), player, x+10, y+90, 200, nil, 0, 0x24474, 0, true) 9 | 10 | return setmetatable(self, modernUI) 11 | end 12 | -------------------------------------------------------------------------------- /source/interfaces/modernUI/showPlayerVehicles.lua: -------------------------------------------------------------------------------- 1 | modernUI.showPlayerVehicles = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - width/2) + 45 7 | local y = (200 - height/2) + 70 8 | local currentPage = 1 9 | local filter = {'car', 'boat', 'air'} 10 | local pages = {'land', 'water', 'air'} 11 | local favorites = players[player].favoriteCars 12 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('17238027fa4.jpg', "~26", x, y-16, player) 13 | 14 | local function showItems() 15 | showTextArea(id..'890', '

'..translate(pages[currentPage]..'Vehicles', player), player, 350, y-25, 100, nil, 0x152d30, 0x152d30, 0, true) 16 | local i = 1 17 | for _ = 1, #players[player].cars do 18 | local v = mainAssets.__cars[players[player].cars[_]] 19 | if v.type == filter[currentPage] then 20 | players[player]._modernUISelectedItemImages[3][#players[player]._modernUISelectedItemImages[3]+1] = addImage('17237e4b350.jpg', "~26", x + ((i-1)%4)*107, y + floor((i-1)/4)*65, player) 21 | players[player]._modernUISelectedItemImages[3][#players[player]._modernUISelectedItemImages[3]+1] = addImage(v.icon, "~26", x + ((i-1)%4)*107, y + floor((i-1)/4)*65, player) 22 | players[player]._modernUISelectedItemImages[3][#players[player]._modernUISelectedItemImages[3]+1] = addImage('17958659424.png', "~27", x + ((i-1)%4)*107, y + floor((i-1)/4)*65, player) 23 | 24 | local isFavorite = favorites[currentPage] == players[player].cars[_] and '17238fea420.png' or '17238fe6532.png' 25 | players[player]._modernUISelectedItemImages[1][#players[player]._modernUISelectedItemImages[1]+1] = addImage(isFavorite, "~27", x+82 + ((i-1)%4)*107, y +42 + floor((i-1)/4)*65, player) 26 | 27 | local vehicleName = lang.en['vehicle_'..players[player].cars[_]] and translate('vehicle_'..players[player].cars[_], player) or v.name 28 | showTextArea(id..(895+i*4), '

'..vehicleName, player, x + ((i-1)%4)*107, y-2 + floor((i-1)/4)*65, 104, nil, 0xff0000, 0xff0000, 0, true) 29 | showTextArea(id..(896+i*4), ''..v.speed..' '..(v.type == 'boat' and translate('speed_knots', player) or translate('speed_km', player)), player, x + ((i-1)%4)*107, y+54 + floor((i-1)/4)*65, 104, nil, 0xff0000, 0xff0000, 0, true) 30 | showTextArea(id..(897+i*4), '\n\n\n\n', player, x + 3 + ((i-1)%4)*107, y + 3 + floor((i-1)/4)*65, 104, 62, 0xff0000, 0xff0000, 0, true, 31 | function(player) 32 | local car = players[player].cars[_] 33 | if currentPage ~= 2 and (ROOM.playerList[player].y < 7000 or ROOM.playerList[player].y > 7800 or players[player].place ~= 'town' and players[player].place ~= 'island') and not players[player].canDrive then return alert_Error(player, 'error', 'vehicleError') end 34 | drive(player, car) 35 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 36 | if v.type == 'air' then 37 | modernUI.new(player, 240, 120, translate('confirmButton_tip', player), translate('tip_airVehicle', player), 'errorUI') 38 | :build() 39 | end 40 | end) 41 | showTextArea(id..(898+i*4), "\n\n\n\n", player, x + 82 + ((i-1)%4)*107, y + 42 + floor((i-1)/4)*65, 20, 20, 0xff0000, 0xff0000, 0, true, 42 | function(player) 43 | favorites[currentPage] = players[player].cars[_] 44 | players[player].favoriteCars[currentPage] = players[player].cars[_] 45 | showItems() 46 | savedata(player) 47 | end) 48 | i = i + 1 49 | end 50 | end 51 | end 52 | local function updateScrollbar() 53 | local function updatePage(count) 54 | if currentPage + count > 3 or currentPage + count < 1 then return end 55 | currentPage = currentPage + count 56 | removeGroupImages(players[player]._modernUISelectedItemImages[1]) 57 | removeGroupImages(players[player]._modernUISelectedItemImages[3]) 58 | for i = 899, 950 do 59 | removeTextArea(id..i, player) 60 | end 61 | updateScrollbar() 62 | showItems() 63 | end 64 | showTextArea(id..'888', string.rep('\n', 10), player, x, y+202, 212, 10, 0x24474D, 0xff0000, 0, true, 65 | function() 66 | updatePage(-1) 67 | end) 68 | showTextArea(id..'889', string.rep('\n', 10), player, x+213, y+202, 212, 10, 0x24474D, 0xff0000, 0, true, 69 | function() 70 | updatePage(1) 71 | end) 72 | 73 | removeGroupImages(players[player]._modernUISelectedItemImages[2]) 74 | players[player]._modernUISelectedItemImages[2][#players[player]._modernUISelectedItemImages[2]+1] = addImage('172380798d8.jpg', "~26", x, y+205, player) 75 | for i = 1, 3 do 76 | players[player]._modernUISelectedItemImages[2][#players[player]._modernUISelectedItemImages[2]+1] = addImage('172383aa660.jpg', "~27", x + (i-1)*85 + (currentPage-1)*85, y+205, player) 77 | end 78 | end 79 | 80 | updateScrollbar() 81 | showItems() 82 | return setmetatable(self, modernUI) 83 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showQuestInterface.lua: -------------------------------------------------------------------------------- 1 | modernUI.questInterface = function(self) 2 | local id = self.id 3 | local player = self.player 4 | local width = self.width 5 | local height = self.height 6 | local x = (400 - 270/2) 7 | local y = (200 - 90/2) - 30 8 | 9 | local images = {'174070bd0ec.png', '174070e21a1.png'} -- available, unavailaible 10 | 11 | local playerData = players[player] 12 | local getLang = playerData.lang 13 | 14 | for i = 1, 2 do 15 | local icon = 1 16 | local title, min, max, goal = '', 0, 100, '

'..translate('newQuestSoon', player):format(questsAvailable+1, ''..syncData.quests.newQuestDevelopmentStage) 17 | if i == 1 then 18 | if playerData.questStep[1] > questsAvailable then 19 | icon = 2 20 | else 21 | title = lang[getLang].quests[playerData.questStep[1]].name 22 | min = playerData.questStep[2] 23 | max = #lang['en'].quests[playerData.questStep[1]] 24 | goal = string.format(lang[getLang].quests[playerData.questStep[1]][playerData.questStep[2]]._add, quest_formatText(player, playerData.questStep[1], playerData.questStep[2])) 25 | end 26 | else 27 | local sideQuestID = sideQuests[playerData.sideQuests[1]].alias or playerData.sideQuests[1] 28 | local currentAmount = playerData.sideQuests[2] 29 | local requiredAmount = playerData.sideQuests[7] or sideQuests[playerData.sideQuests[1]].amount 30 | 31 | if type(requiredAmount) == "table" then 32 | requiredAmount = requiredAmount[1] 33 | end 34 | 35 | local description = sideQuests[sideQuestID].formatDescription and sideQuests[sideQuestID].formatDescription(player) or {""..currentAmount .. '/' .. requiredAmount..""} 36 | title = '['..translate('_2ndquest', player)..']' 37 | min = currentAmount 38 | max = requiredAmount 39 | 40 | goal = lang[getLang].sideQuests[sideQuestID]:format(table.unpack(description)) 41 | end 42 | 43 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(images[icon], "~26", x - 5, y + (i-1)*100, player) 44 | 45 | local progress = floor(min / max * 100) 46 | local progress2 = floor(min / max * 250/11.5) 47 | showTextArea(id..(890+i), ''..title, player, x+2, y+5 + (i-1)*100, 270, nil, 1, 0x24474, 0, true) 48 | showTextArea(id..(892+i), ''..goal, player, x+2, y+30 + (i-1)*100, 270, 40, 0x1, 0x1, 0, true) 49 | 50 | for ii = 1, progress2 do 51 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('171d74086d8.png', "~25", x+17 + (ii-1)*11, y+77 + (i-1)*100, player) 52 | end 53 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('171d736325c.png', "~27", x + 10, y + 70 + (i-1)*100, player) 54 | 55 | showTextArea(id..(900+i), '

'..translate('percentageFormat', player):format(progress), player, x+11, y+73 + (i-1)*100, 250, nil, 0, 0x24474, 0, true) 56 | showTextArea(id..(902+i), '

'..translate('percentageFormat', player):format(progress), player, x+10, y+72 + (i-1)*100, 250, nil, 0, 0x24474, 0, true) 57 | 58 | if i == 2 then -- Skip Side Quest 59 | -- If the player already skipped a quest today, end the function 60 | if players[player].sideQuests[5] == floor(os_time() / (24*60*60*1000)) then return end 61 | local mirrorButton = players[player].settings.mirroredMode == 1 and 10 or 246 62 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage('174077c73af.png', "~28", x + mirrorButton, y + 8 + (i-1)*100, player) 63 | showTextArea(id..(905), "" .. string.rep('\n', 4), player, x + mirrorButton, y + 8 + (i-1)*100, 20, 20, 0, 0x24474, 0, true, 64 | function() 65 | -- If the player already skipped a quest today, end the function to avoid double click 66 | if players[player].sideQuests[5] == floor(os_time() / (24*60*60*1000)) then return end 67 | 68 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 69 | modernUI.new(player, 240, 170, translate('skipQuest', player), translate('skipQuestTxt', player), 0) 70 | :build() 71 | :addConfirmButton(function() 72 | players[player].sideQuests[5] = floor(os_time() / (24*60*60*1000)) 73 | players[player].sideQuests[6] = sideQuests[players[player].sideQuests[1]].alias or players[player].sideQuests[1] 74 | sideQuest_new(player) 75 | end, translate('confirmButton_skipQuest', player)) 76 | end) 77 | end 78 | end 79 | 80 | return setmetatable(self, modernUI) 81 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showRewardInterface.lua: -------------------------------------------------------------------------------- 1 | modernUI.rewardInterface = function(self, rewards, title, text) 2 | local player = self.player 3 | if not title then title = translate('reward', player) end 4 | if not text then text = translate('rewardText', player) end 5 | text = text..'\n' 6 | for i, v in next, rewards do 7 | if v.currency then 8 | text = text..'\n+'..mainAssets.currencies[v.currency].color..v.quanty..'' 9 | else 10 | text = text..'\n'..v.text..' ('..v.format..v.quanty..')' 11 | end 12 | end 13 | self.title = title 14 | self.text = text 15 | return setmetatable(self, modernUI) 16 | end -------------------------------------------------------------------------------- /source/interfaces/modernUI/showUpdateLog.lua: -------------------------------------------------------------------------------- 1 | modernUI.showUpdateLog = function(self, badge) 2 | local id = self.id 3 | local player = self.player 4 | local x = self.width/2 + 30 5 | local y = 70 6 | 7 | local version = 'v'..table_concat(version, '.') 8 | local width = 520 9 | local height = 300 10 | showTextArea(id..'876', '', player, 5 - width/2, 0, 400, 400, 0x152d30, 0x152d30, 0, true) showTextArea(id..'877', '', player, 395 + width/2, 0, 400, 400, 0x152d30, 0x152d30, 0, true) showTextArea(id..'878', '', player, 0, 6 - height/2, 800, 200, 0x152d30, 0x152d30, 0, true) showTextArea(id..'879', '', player, 0, 194 + height/2, 800, 200, 0x152d30, 0x152d30, 0, true) 11 | 12 | players[player]._modernUIImages[id][#players[player]._modernUIImages[id]+1] = addImage(versionLogs[version].banner, "~100", 155, 90, player) 13 | showTextArea(id..'891', ''..version, player, 610, 63, nil, nil, 0, 0, 0, true) 14 | showTextArea(id..'892', '

'..translate('$VersionName', player), player, 0, 63, 800, nil, 0, 0, 0, true) 15 | 16 | addTimer(function() 17 | greenButton(200, 0, translate('confirmButton_Play', player), player, 18 | function() 19 | for i = 800, 999 do 20 | removeTextArea((200)..i, player) 21 | end 22 | eventTextAreaCallback(0, player, 'modernUI_Close_'..id, true) 23 | if players[player].dataLoaded then return end 24 | loadPlayerData(player) 25 | 26 | showDishOrders(player) 27 | mine_drawGrid(mine_optimizeGrid(grid, grid_width, grid_height), 60, Mine.position[1], Mine.position[2]) 28 | showTextArea(999997, "" .. string.rep('\n', 4), player, 660, 365, 35, 35, 0x324650, 0x000000, 0, true, function(player) openProfile(player) end) 29 | showTextArea(999999, "" .. string.rep('\n', 4), player, 750, 365, 35, 35, 0x324650, 0x000000, 0, true, function(player) openSettings(player) end) 30 | showTextArea(999996, "" .. string.rep('\n', 4), player, 750, 330, 35, 35, 0x324650, 0x000000, 0, true, function(player) modernUI.new(player, 520, 300):build():showSettingsMenu(true) end) 31 | showTextArea(999995, "" .. string.rep('\n', 4), player, 705, 365, 35, 35, 0x324650, 0x000000, 0, true, function(player) modernUI.new(player, 380, 280, translate('tradeSystem_title', player)):build():showAvailableTradingPlayers() end) 32 | 33 | addImage("170fef3117d.png", "~1", 660, 365, player) 34 | addImage("170f8ccde22.png", "~3", 750, 365, player) 35 | addImage("1744cc60c32.png", "~4", 750, 330, player) 36 | addImage("1744cf82bac.png", "~5", 705, 365, player) 37 | end, 38 | 350, 310, 100, 15) 39 | end, 4000, 1) 40 | return setmetatable(self, modernUI) 41 | end 42 | -------------------------------------------------------------------------------- /source/items/bag.lua: -------------------------------------------------------------------------------- 1 | addItem = function(item, amount, player, coin, notify) 2 | local id = bagItems[item].id 3 | if not coin then coin = 0 end 4 | if players[player].coins < coin then return end 5 | 6 | for id, properties in next, players[player].questLocalData.other do 7 | if id:find('ItemAmount_') then 8 | if id:lower():find(item:lower()) then 9 | if type(properties) == 'boolean' then 10 | quest_updateStep(player) 11 | else 12 | players[player].questLocalData.other[id] = properties - 1 13 | if players[player].questLocalData.other[id] <= 0 then 14 | quest_updateStep(player) 15 | end 16 | end 17 | break 18 | end 19 | end 20 | end 21 | local canAdd = false 22 | for i, v in next, players[player].bag do 23 | if v.name == item then 24 | canAdd = i 25 | end 26 | end 27 | 28 | if notify then 29 | modernUI.new(player, 120, 120) 30 | :build() 31 | players[player]._modernUISelectedItemImages[1][#players[player]._modernUISelectedItemImages[1]+1] = addImage(bagItems[item].png, ":70", 400 - 50 * 0.5, 180, player) 32 | end 33 | 34 | if (players[player].totalOfStoredItems.bag + amount > players[player].bagLimit) and not players[player].trading then 35 | alert_Error(player, 'error', 'bagError') 36 | if coin == 0 then 37 | item_drop(item, player, amount) 38 | end 39 | return 40 | else 41 | players[player].totalOfStoredItems.bag = players[player].totalOfStoredItems.bag + amount 42 | if (players[player].totalOfStoredItems.bag + amount > players[player].bagLimit) and players[player].trading then 43 | modernUI.new(player, 240, 220, translate('warning', player), translate('bagTemporaryLimit', player):format(players[player].bagLimit), 'errorUI') 44 | :build() 45 | end 46 | end 47 | 48 | if canAdd then 49 | players[player].bag[canAdd].qt = players[player].bag[canAdd].qt + amount 50 | giveCoin(-coin, player) 51 | return 52 | end 53 | 54 | players[player].bag[#players[player].bag+1] = {name = item, qt = amount} 55 | giveCoin(-coin, player) 56 | end 57 | 58 | removeBagItem = function(item, amount, player) 59 | amount = abs(amount) 60 | local hasItem = false 61 | for i, v in next, players[player].bag do 62 | if v.name == item then 63 | if amount > v.qt then 64 | amount = v.qt 65 | end 66 | v.qt = v.qt - amount 67 | if v.qt <= 0 then 68 | table_remove(players[player].bag, i) 69 | end 70 | hasItem = true 71 | break 72 | end 73 | end 74 | if not hasItem then return false end 75 | 76 | players[player].totalOfStoredItems.bag = players[player].totalOfStoredItems.bag - amount 77 | savedata(player) 78 | 79 | return true 80 | end -------------------------------------------------------------------------------- /source/items/checkAmount.lua: -------------------------------------------------------------------------------- 1 | checkItemAmount = function(item, quant, player) 2 | if not players[player].bag then return end 3 | if #players[player].bag == 0 then return false end 4 | for i, v in next, players[player].bag do 5 | if v.name == item then 6 | if v.qt >= quant then 7 | return v.qt 8 | end 9 | end 10 | end 11 | return false 12 | end 13 | 14 | checkItemInChest = function(item, quant, player) 15 | local playerChests = players[player].houseData.chests.storage 16 | local amount = 0 17 | for chest = 1, #playerChests do 18 | for i, v in next, playerChests[chest] do 19 | if v.name == item then 20 | amount = amount + v.qt 21 | end 22 | end 23 | end 24 | if amount >= quant then 25 | return amount 26 | end 27 | return false 28 | end -------------------------------------------------------------------------------- /source/items/chest.lua: -------------------------------------------------------------------------------- 1 | item_addToChest = function(item, amount, player, chest) 2 | if not chest then chest = 1 end 3 | players[player].totalOfStoredItems.chest[chest] = players[player].totalOfStoredItems.chest[chest] + amount 4 | for i, v in next, players[player].houseData.chests.storage[chest] do 5 | if v.name == item then 6 | v.qt = v.qt + amount 7 | return 8 | end 9 | end 10 | players[player].houseData.chests.storage[chest][#players[player].houseData.chests.storage[chest]+1] = {name = item, qt = amount} 11 | end 12 | 13 | item_removeFromChest = function(item, amount, player, chest) 14 | amount = abs(amount) 15 | if chest then 16 | for i, v in next, players[player].houseData.chests.storage[chest] do 17 | if v.name == item then 18 | v.qt = v.qt - amount 19 | if v.qt <= 0 then 20 | table_remove(players[player].houseData.chests.storage[chest], i) 21 | end 22 | break 23 | end 24 | end 25 | players[player].totalOfStoredItems.chest[chest] = players[player].totalOfStoredItems.chest[chest] - amount 26 | else 27 | local playerChests = players[player].houseData.chests.storage 28 | for chest = 1, #playerChests do 29 | local _amount = 0 30 | for i, v in next, playerChests[chest] do 31 | if v.name == item then 32 | _amount = _amount + v.qt 33 | table_remove(players[player].houseData.chests.storage[chest], i) 34 | break 35 | end 36 | end 37 | players[player].totalOfStoredItems.chest[chest] = players[player].totalOfStoredItems.chest[chest] - _amount 38 | end 39 | end 40 | savedata(player) 41 | end -------------------------------------------------------------------------------- /source/items/itemInfo.lua: -------------------------------------------------------------------------------- 1 | item_getDescription = function(item, player, isFurniture) 2 | local itemData = isFurniture and mainAssets.__furnitures[item] or bagItems[item] 3 | local description = lang.en['itemDesc_'..item] and '

"'..translate('itemDesc_'..item, player)..'"

\n' or '' 4 | local isLimitedTime = itemData.limitedTime 5 | local isOutOfSale = isLimitedTime and formatDaysRemaining(isLimitedTime, true) 6 | 7 | if not isFurniture then 8 | local itemType = itemData.type 9 | local power = itemData.power or 0 10 | local hunger = itemData.hunger or 0 11 | if itemType == 'complementItem' then 12 | description = '

"'..translate('itemDesc_'..item, player):format(itemData.complement)..'"

\n' 13 | end 14 | if itemType == 'food' then 15 | description = description ..string.format(translate('energyInfo', player) ..'\n'.. translate('hungerInfo', player)..'\n', ''..power..'', ''..hunger..'') 16 | elseif itemData.miningPower then 17 | description = description .. translate('itemInfo_miningPower', player):format('0') 18 | elseif item:find("prop_") then 19 | description = '

"'..translate('itemDesc_prop', player)..'"

\n' 20 | elseif item:find('Seed') and not isFurniture then 21 | local txt = translate('itemInfo_Seed', player) 22 | for i, v in next, HouseSystem.plants do 23 | if v.name:find(item:gsub('Seed', '')) then 24 | txt = txt:format((v.growingTime * (#v.stages-2)/60), v.pricePerSeed)..'\n' 25 | break 26 | end 27 | end 28 | description = description .. txt 29 | end 30 | if itemData.sellingPrice then 31 | description = description .. translate('itemInfo_sellingPrice', player):format('$'..itemData.sellingPrice..'')..'\n' 32 | end 33 | end 34 | if itemData.credits then 35 | description = description ..translate('createdBy', player):format(''..itemData.credits..'')..'\n' 36 | end 37 | 38 | if isLimitedTime then 39 | description = description ..'\n

'..translate('collectorItem', player) 40 | end 41 | 42 | return description 43 | end -------------------------------------------------------------------------------- /source/items/itemList/recipes.lua: -------------------------------------------------------------------------------- 1 | recipes = { 2 | sauce = { 3 | require = { 4 | tomato = 3, 5 | water = 1, 6 | salt = 1, 7 | }, 8 | }, 9 | hotsauce = { 10 | require = { 11 | tomato = 3, 12 | pepper = 2, 13 | water = 1, 14 | salt = 1, 15 | }, 16 | }, 17 | pizza = { 18 | require = { 19 | wheatFlour = 1, 20 | tomato = 2, 21 | sauce = 1, 22 | oregano = 2, 23 | milk = 2, 24 | cheese = 1, 25 | }, 26 | }, 27 | cookies = { 28 | require = { 29 | wheatFlour = 1, 30 | milk = 1, 31 | sugar = 1, 32 | chocolate = 1, 33 | }, 34 | }, 35 | hotChocolate = { 36 | require = { 37 | milk = 1, 38 | chocolate = 2, 39 | }, 40 | }, 41 | milkShake = { 42 | require = { 43 | blueberries = 1, 44 | milk = 1, 45 | sugar = 1, 46 | }, 47 | }, 48 | lemonade = { 49 | require = { 50 | lemon = 2, 51 | water = 1, 52 | sugar = 1, 53 | }, 54 | }, 55 | lobsterBisque = { 56 | require = { 57 | fish_Lobster = 1, 58 | milk = 1, 59 | salt = 1, 60 | }, 61 | }, 62 | bread = { 63 | require = { 64 | water = 1, 65 | wheatFlour = 1, 66 | salt = 1, 67 | sugar = 1, 68 | }, 69 | }, 70 | bruschetta = { 71 | require = { 72 | bread = 1, 73 | tomato = 1, 74 | oregano = 1, 75 | }, 76 | }, 77 | waffles = { 78 | require = { 79 | sugar = 1, 80 | salt = 1, 81 | egg = 1, 82 | wheatFlour = 3, 83 | milk = 1, 84 | honey = 1, 85 | }, 86 | }, 87 | grilledLobster = { 88 | require = { 89 | fish_Lobster = 1, 90 | salt = 2, 91 | lemon = 3, 92 | }, 93 | }, 94 | frogSandwich = { 95 | require = { 96 | fish_Frog = 1, 97 | bread = 1, 98 | tomato = 1, 99 | }, 100 | }, 101 | chocolateCake = { 102 | require = { 103 | chocolate = 2, 104 | milk = 1, 105 | egg = 3, 106 | sugar = 1, 107 | wheatFlour = 3, 108 | }, 109 | }, 110 | salad = { 111 | require = { 112 | tomato = 2, 113 | egg = 1, 114 | cheese = 1, 115 | lettuce = 2, 116 | }, 117 | }, 118 | pierogies = { 119 | require = { 120 | cheese = 1, 121 | wheatFlour = 2, 122 | egg = 2, 123 | salt = 1, 124 | potato = 2, 125 | }, 126 | }, 127 | frenchFries = { 128 | require = { 129 | potato = 2, 130 | salt = 1, 131 | }, 132 | }, 133 | pudding = { 134 | require = { 135 | milk = 2, 136 | sugar = 1, 137 | egg = 3 138 | }, 139 | }, 140 | garlicBread = { 141 | require = { 142 | bread = 1, 143 | garlic = 1, 144 | cheese = 1, 145 | oregano = 1, 146 | salt = 1, 147 | }, 148 | }, 149 | moqueca = { 150 | require = { 151 | tomato = 2, 152 | garlic = 1, 153 | salt = 1, 154 | pepper = 1, 155 | milk = 1, 156 | fish_Lionfish = 1, 157 | }, 158 | }, 159 | grilledCheese = { 160 | require = { 161 | cheese = 1, 162 | bread = 1, 163 | }, 164 | }, 165 | fishBurger = { 166 | require = { 167 | bread = 1, 168 | fish_Dogfish = 1, 169 | lemon = 1, 170 | }, 171 | }, 172 | sushi = { 173 | require = { 174 | fish_Goldenmare = 1, 175 | lemon = 2, 176 | }, 177 | }, 178 | bananaCake = { 179 | require = { 180 | banana = 2, 181 | milk = 1, 182 | egg = 2, 183 | sugar = 2, 184 | wheatFlour = 3, 185 | }, 186 | }, 187 | croquettes = { 188 | require = { 189 | potato = 3, 190 | milk = 1, 191 | egg = 2, 192 | salt = 1, 193 | wheatFlour = 2, 194 | cheese = 1, 195 | }, 196 | }, 197 | cheeseburger = { 198 | require = { 199 | bread = 1, 200 | cheese = 1, 201 | meat = 2, 202 | }, 203 | }, 204 | lasagna = { 205 | require = { 206 | cheese = 2, 207 | meat = 2, 208 | sauce = 1, 209 | water = 1, 210 | wheatFlour = 1, 211 | salt = 1, 212 | }, 213 | }, 214 | meatballs = { 215 | require = { 216 | meat = 3, 217 | salt = 1, 218 | hotsauce = 1, 219 | }, 220 | }, 221 | garlicMashedPotatoes = { 222 | require = { 223 | garlic = 2, 224 | salt = 1, 225 | milk = 1, 226 | potato = 2, 227 | }, 228 | }, 229 | mushroomBurger = { 230 | require = { 231 | bread = 1, 232 | garlic = 1, 233 | mushroom = 2, 234 | } 235 | }, 236 | creamOfMushroom = { 237 | require = { 238 | salt = 1, 239 | milk = 1, 240 | mushroom = 2, 241 | } 242 | }, 243 | pumpkinPie = { 244 | require = { 245 | pumpkin = 1, 246 | egg = 2, 247 | sugar = 1, 248 | honey = 1, 249 | wheatFlour = 2, 250 | } 251 | }, 252 | steakFrites = { 253 | require = { 254 | meat = 2, 255 | frenchFries = 1, 256 | salt = 1, 257 | } 258 | }, 259 | breadedCutlet = { 260 | require = { 261 | meat = 2, 262 | salt = 1, 263 | egg = 2, 264 | wheatFlour = 1, 265 | garlic = 1, 266 | pepper = 1, 267 | } 268 | }, 269 | fishAndChips = { 270 | require = { 271 | fish_Catfish = 1, 272 | frenchFries = 1, 273 | wheatFlour = 1, 274 | } 275 | }, 276 | raspberryCake = { 277 | require = { 278 | raspberry = 2, 279 | milk = 1, 280 | egg = 2, 281 | sugar = 1, 282 | wheatFlour = 3, 283 | }, 284 | }, 285 | } -------------------------------------------------------------------------------- /source/jobs/cop/arrest.lua: -------------------------------------------------------------------------------- 1 | arrestPlayer = function(thief, cop, command) 2 | local i = thief 3 | local player = cop 4 | local thiefData = players[thief] 5 | local copData = players[cop] 6 | if not copData then 7 | eventNewPlayer(cop) 8 | return arrestPlayer(thief, cop, command) 9 | elseif not thiefData then 10 | eventNewPlayer(thief) 11 | return arrestPlayer(thief, cop, command) 12 | end 13 | 14 | checkIfPlayerIsDriving(thief) 15 | removeGroupImages(players[thief].images) 16 | removeTextArea(1012, thief) 17 | removeTextArea(5001, thief) 18 | closeMenu(920, thief) 19 | removeTimer(thiefData.timer) 20 | job_fire(thief) 21 | eventTextAreaCallback(1, thief, 'closeVaultPassword', true) 22 | 23 | players[thief].place = 'police' 24 | players[thief].blockScreen = true 25 | players[thief].robbery.arrested = true 26 | players[thief].robbery.robbing = false 27 | players[thief].robbery.usingShield = false 28 | players[thief].robbery.whenWasArrested = os_time() 29 | players[thief].robbery.escaped = false 30 | players[thief].timer = {} 31 | players[thief].bankPassword = nil 32 | 33 | if thief == 'Robber' then 34 | quest_updateStep(cop) 35 | return 36 | else 37 | players[thief].timer = addTimer(function(j) 38 | local time = room.robbing.prisonTimer - j 39 | local thiefPosition = ROOM.playerList[thief] 40 | 41 | showTextArea(98900000000, string.format("

"..translate('looseMgs', thief), time), thief, 253, 345, 290, nil, 1, 1, 0, true) 42 | if j == room.robbing.prisonTimer then 43 | removeTimer(thiefData.timer) 44 | removeTextArea(98900000000, thief) 45 | players[thief].robbery.arrested = false 46 | players[thief].blockScreen = false 47 | players[thief].timer = {} 48 | movePlayer(thief, 8020, 6400, false) 49 | end 50 | 51 | if not (thiefPosition.x > 8040 and thiefPosition.y > 6260 and thiefPosition.x < 8500 and thiefPosition.y < 6420) then 52 | movePlayer(thief, random(8055, 8330), 6400, false) 53 | end 54 | end, 1000, command and 30 or room.robbing.prisonTimer) 55 | end 56 | 57 | setNightMode(thief, true) 58 | giveExperiencePoints(thief, 10) 59 | giveExperiencePoints(cop, 30) 60 | local complement = i:gmatch('(.-)#[0-9]+$')() 61 | if not i:match('#0000') then 62 | complement = i:gsub('#', '#') 63 | end 64 | for name in next, ROOM.playerList do 65 | if name ~= cop then 66 | chatMessage(string.format(translate('captured', name), complement), name) 67 | end 68 | end 69 | chatMessage(string.format(translate('arrestedPlayer', cop), complement), cop) 70 | 71 | sideQuest_sendTrigger(cop, 'arrest', 1) 72 | giveCoin(jobs['police'].coins, cop, true) 73 | job_updatePlayerStats(cop, 1) 74 | players[cop].time = os_time() + 10000 75 | end -------------------------------------------------------------------------------- /source/jobs/fisher/_biomes.lua: -------------------------------------------------------------------------------- 1 | room.fishing = { 2 | biomes = { 3 | sea = { 4 | canUseBoat = true, 5 | between = {'town', 'island'}, 6 | location = { 7 | {x = 6400-70, y = 7775-70}, {x = 6400-70, y = 8000}, {x = 9160+70, y = 7775-70}, {x = 9160+70, y = 8000}, 8 | }, 9 | fishes = { 10 | normal = {'fish_Smolty', 'cheese', 'wheatSeed', 'fish_Guppy'}, 11 | rare = {'fish_Lionfish', 'fish_Dogfish', 'fish_Catfish'}, 12 | mythical = {'fish_Lobster',}, 13 | legendary = {'fish_Goldenmare',}, 14 | }, 15 | }, 16 | bridge = { 17 | location = { 18 | {x = 10760, y = 7775-70}, {x = 10915, y = 7775-70}, {x = 10915, y = 7828}, {x = 10760, y = 7828}, 19 | }, 20 | fishes = { 21 | normal = {'fish_Frog', 'fish_Guppy', 'fish_Bittyfish'}, 22 | rare = {'fish_Dogfish'}, 23 | mythical = {'fish_Lobster',}, 24 | legendary = {'fish_Goldenmare',}, 25 | }, 26 | }, 27 | sewer = { 28 | canUseBoat = true, 29 | between = {'mine', 'mine_excavation'}, 30 | location = { 31 | {x = 2837-70, y = 8662-70}, {x = 2837-70, y = 8800}, {x = 4325+70, y = 8662-70}, {x = 4325+70, y = 8800}, 32 | }, 33 | fishes = { 34 | normal = {'fish_Mudfish', 'fish_Sinkfish'}, 35 | rare = {'fish_Dogfish', 'fish_Catfish'}, 36 | mythical = {'fish_Lobster',}, 37 | legendary = {'fish_Goldenmare',}, 38 | }, 39 | }, 40 | }, 41 | } -------------------------------------------------------------------------------- /source/jobs/fisher/fish.lua: -------------------------------------------------------------------------------- 1 | playerFishing = function(name, x, y, biome) 2 | local player = players[name] 3 | local playerStatus = ROOM.playerList[name] 4 | 5 | randomseed(os_time()) 6 | local chances = random(1, 10000) 7 | local rarityFished = 'normal' 8 | 9 | for rarity, percentage in next, player.lucky[1] do 10 | if (percentage * 100) >= chances then 11 | rarityFished = rarity 12 | break 13 | end 14 | end 15 | 16 | player.fishing[1] = true 17 | TFM.playEmote(name, 26) 18 | player.fishing[3][#player.fishing[3]+1] = addImage(playerStatus.isFacingRight and '170b1daa3ed.png' or '170b1daccfb.png', '$'..name, playerStatus.isFacingRight and 0 or -40, -42) 19 | 20 | player.fishing[2] = addTimer(function(j) 21 | if j == 2 then 22 | playerStatus = ROOM.playerList[name] 23 | if not players[name].canDrive and biome == 'sea' then 24 | checkIfPlayerIsDriving(name) 25 | movePlayer(name, playerStatus.x, playerStatus.y, false) 26 | addGround(77777 + playerStatus.id, playerStatus.x + (playerStatus.isFacingRight and 40 or -40), playerStatus.y - 40, {type = 14, miceCollision = false, groundCollision = false}) 27 | addGround(77777 + playerStatus.id+1, playerStatus.x + (playerStatus.isFacingRight and 70 or -70), playerStatus.y - 30, {type = 14, dynamic = true, miceCollision = false}) 28 | 29 | TFM.addJoint(77777 + playerStatus.id, 77777 + playerStatus.id, 77777 + playerStatus.id+1, {type = 0, color = 0xc1c1c1, line = 1, frequency = 0.2}) 30 | for i = 1, #player.fishing[3] do 31 | removeImage(player.fishing[3][i]) 32 | end 33 | player.fishing[3] = {} 34 | player.fishing[3][#player.fishing[3]+1] = addImage(playerStatus.isFacingRight and '170b1daa3ed.png' or '170b1daccfb.png', '$'..name, playerStatus.isFacingRight and 0 or -40, -42) 35 | else 36 | player.fishing[3][#player.fishing[3]+1] = addImage('170b66954aa.png', '$'..name, playerStatus.isFacingRight and 35 or -40, -35) 37 | end 38 | 39 | elseif j == 28 then 40 | player.fishing[1] = false 41 | TFM.playEmote(name, 9) 42 | job_updatePlayerStats(name, 3) 43 | 44 | local align = playerStatus.isFacingRight and 20 or -90 45 | for particles = 1, 10 do 46 | TFM.displayParticle(14, particles * 3 + x + align, y + 50, random(-5, 5), random(-2, 0.5), random(-0.7, 0.1)) 47 | end 48 | 49 | randomseed(os_time()) 50 | local willFish = room.fishing.biomes[biome].fishes[rarityFished][random(#room.fishing.biomes[biome].fishes[rarityFished])] 51 | local willFishInfo = bagItems[willFish] 52 | 53 | addItem(willFish, 1, name, nil, true) 54 | 55 | if rarityFished == 'normal' then 56 | players[name].lucky[1]['normal'] = player.lucky[1]['normal'] - .5 57 | players[name].lucky[1]['rare'] = player.lucky[1]['rare'] + .5 58 | giveExperiencePoints(name, 10) 59 | elseif rarityFished == 'rare' then 60 | players[name].lucky[1]['rare'] = player.lucky[1]['rare'] - .25 61 | players[name].lucky[1]['mythical'] = player.lucky[1]['mythical'] + .25 62 | giveExperiencePoints(name, 100) 63 | elseif rarityFished == 'mythical' then 64 | players[name].lucky[1]['normal'] = player.lucky[1]['normal'] + player.lucky[1]['mythical']/2 65 | players[name].lucky[1]['legendary'] = player.lucky[1]['legendary'] + player.lucky[1]['mythical']/2 66 | players[name].lucky[1]['mythical'] = 0 67 | giveExperiencePoints(name, 500) 68 | else 69 | players[name].lucky[1] = {normal = 100, rare = 0, mythical = 0, legendary = 0} 70 | giveExperiencePoints(name, 1000) 71 | translatedMessage('caught_goldenmare', name) 72 | end 73 | 74 | local sidequest = sideQuests[player.sideQuests[1]].type 75 | if sidequest == 'type:fish' or string_find(sidequest, willFish) then 76 | sideQuest_update(name, 1) 77 | end 78 | for id, properties in next, player.questLocalData.other do 79 | if id:find('fish_') then 80 | if type(properties) == 'boolean' then 81 | quest_updateStep(name) 82 | else 83 | player.questLocalData.other[id] = properties - 1 84 | if player.questLocalData.other[id] == 0 then 85 | quest_updateStep(name) 86 | end 87 | end 88 | break 89 | end 90 | end 91 | for i = 1, #player.fishing[3] do 92 | removeImage(player.fishing[3][i]) 93 | end 94 | players[name].fishing[3] = {} 95 | for i = 77777 + playerStatus.id, 77777 + playerStatus.id+2 do 96 | removeGround(i) 97 | end 98 | setLifeStat(name, 1, random(-11, -8)) 99 | end 100 | end, 1000, 28) 101 | end 102 | 103 | stopFishing = function(player) 104 | local playerStatus = ROOM.playerList[player] 105 | if not playerStatus then return end 106 | players[player].fishing[1] = false 107 | removeTimer(players[player].fishing[2]) 108 | chatMessage(''..translate('fishingError', player), player) 109 | for i = 1, #players[player].fishing[3] do 110 | removeImage(players[player].fishing[3][i]) 111 | end 112 | players[player].fishing[3] = {} 113 | for i = 77777 + playerStatus.id, 77777 + playerStatus.id+2 do 114 | removeGround(i) 115 | end 116 | end -------------------------------------------------------------------------------- /source/jobs/jobData.lua: -------------------------------------------------------------------------------- 1 | jobs = { 2 | fisher = { 3 | color = '32CD32', 4 | coins = '15 - $10.000', 5 | working = {}, 6 | players = 0, 7 | icon = '171d2134def.png', 8 | }, 9 | police = { 10 | color = '4169E1', 11 | coins = 150, 12 | working = {}, 13 | players = 10, 14 | icon = '171d1f8d911.png', 15 | }, 16 | thief = { 17 | color = 'CB546B', 18 | coins = 250, 19 | bankRobCoins = 1100, 20 | working = {}, 21 | players = 0, 22 | icon = '171d20cca72.png', 23 | }, 24 | miner = { 25 | color = 'B8860B', 26 | coins = 0, 27 | working = {}, 28 | players = 0, 29 | icon = '171d21cd12d.png', 30 | }, 31 | farmer = { 32 | color = '9ACD32', 33 | coins = '10 - $10.000', 34 | working = {}, 35 | players = 0, 36 | icon = '171d1e559be.png', 37 | specialAssets = function(player) 38 | for i = 1, 5 do 39 | if players['Oliver'].houseTerrainAdd[i] >= #HouseSystem.plants[players['Oliver'].houseTerrainPlants[i]].stages then 40 | local y = 1500 + 90 41 | showTextArea('-730'..(tonumber(i)..tonumber(players['Oliver'].houseData.houseid)*10), '

'..translate('harvest', player)..'

', player, (11%12)*1500+738-(175/2)-2 + (tonumber(i)-1)*175, y+150, 175, 150, 0xff0000, 0xff0000, 0) 42 | end 43 | end 44 | end, 45 | }, 46 | chef = { 47 | color = '00CED1', 48 | coins = '10 - $10.000', 49 | working = {}, 50 | players = 0, 51 | icon = '171d20548bd.png', 52 | }, 53 | ghostbuster = { 54 | color = 'FFE4B5', 55 | coins = 300, 56 | working = {}, 57 | players = 0, 58 | icon = '', 59 | }, 60 | ghost = { 61 | color = 'A020F0', 62 | coins = 100, 63 | players = 0, 64 | }, 65 | } -------------------------------------------------------------------------------- /source/jobs/jobState.lua: -------------------------------------------------------------------------------- 1 | job_fire = function(i) 2 | if not players[i] then return end 3 | if not ROOM.playerList[i] then return end 4 | removeGroupImages(players[i].images) 5 | TFM.setNameColor(i, 0) 6 | 7 | local job = players[i].job 8 | if not job then return end 9 | jobs[job].working[i] = nil 10 | for index, player in next, jobs[job].working do 11 | if player == i then 12 | table_remove(jobs[job].working, index) 13 | break 14 | end 15 | end 16 | players[i].job = nil 17 | local images = players[i].temporaryImages.jobDisplay 18 | if images[1] then 19 | for i = 1, #images do 20 | removeImage(images[i]) 21 | end 22 | players[i].temporaryImages.jobDisplay = {} 23 | removeTextArea(1012, i) 24 | end 25 | if job == 'farmer' then 26 | for i = 1, 4 do 27 | removeTextArea('-730'..(i..tonumber(players['Oliver'].houseData.houseid)*10), i) 28 | end 29 | end 30 | end 31 | 32 | job_invite = function(job, player) 33 | local playerData = players[player] 34 | if not jobs[job] or not playerData then return end 35 | if playerData.job == job then return end 36 | modernUI.new(player, 240, 220) 37 | :build() 38 | :jobInterface(job) 39 | :addConfirmButton(function(player, job) job_hire(job, player) end, translate('confirmButton_Work', player), job) 40 | end 41 | 42 | job_hire = function(job, player) 43 | local playerData = players[player] 44 | if not playerData or playerData.robbery.robbing then return end 45 | if job == 'police' and playerData.place ~= 'police' then 46 | return alert_Error(player, 'error', 'error') 47 | end 48 | 49 | if playerData.job then 50 | job_fire(player) 51 | end 52 | players[player].temporaryImages.jobDisplay[#players[player].temporaryImages.jobDisplay+1] = addImage("171d301df6c.png", ":1", 0, 22, player) 53 | players[player].temporaryImages.jobDisplay[#players[player].temporaryImages.jobDisplay+1] = addImage(jobs[job].icon, ":2", 107, 22, player) 54 | showTextArea(1012, '

'..translate(job, player), player, 0, 29, 110, 30, 0x1, 0x1, 0, true) 55 | 56 | if job ~= 'thief' then 57 | TFM.setNameColor(player, '0x'..jobs[job].color) 58 | if jobs[job].specialAssets then 59 | jobs[job].specialAssets(player) 60 | end 61 | else 62 | TFM.setNameColor(player, 0) 63 | end 64 | 65 | local image = playerData.callbackImages 66 | if image[1] then 67 | for i = 1, #image do 68 | removeImage(image[i]) 69 | end 70 | players[player].callbackImages = {} 71 | end 72 | 73 | players[player].job = job 74 | jobs[job].working[#jobs[job].working+1] = player 75 | end 76 | 77 | job_updatePlayerStats = function(player, id, amount) 78 | amount = amount or 1 79 | players[player].jobs[id] = players[player].jobs[id] or 0 80 | players[player].jobs[id] = players[player].jobs[id] + amount 81 | 82 | if jobRewards[id] and players[player].jobs[id] >= jobRewards[id].requires then 83 | jobRewards[id].callback(player) 84 | end 85 | end -------------------------------------------------------------------------------- /source/jobs/thief/rob.lua: -------------------------------------------------------------------------------- 1 | startRobbery = function(player, character) 2 | local npcTimer = gameNpcs.robbing[character].cooldown 3 | addTimer(function(j) 4 | gameNpcs.hideNPC(character) 5 | if j == npcTimer then 6 | gameNpcs.showNPC(character) 7 | end 8 | end, 1000, npcTimer) 9 | 10 | local shield = addImage('1566af4f852.png', '$'..player, -45, -45) 11 | players[player].robbery.usingShield = true 12 | players[player].robbery.robbing = true 13 | players[player].timer = addTimer(function(j) 14 | local time = room.robbing.robbingTimer - j 15 | showTextArea(98900000000, "

"..translate('runAway', player):format(time)..'\n'..translate('runAwayCoinInfo', player):format('$'..jobs['thief'].coins), player, 253, 345, 290, nil, 1, 1, 0, true) 16 | if j == 10 then 17 | removeImage(shield) 18 | players[player].robbery.usingShield = false 19 | 20 | elseif j == room.robbing.robbingTimer then 21 | sideQuest_sendTrigger(player, 'rob', 1) 22 | sideQuest_sendTrigger(player, 'rob_npc', 1, character) 23 | 24 | players[player].robbery.robbing = false 25 | removeTimer(players[player].timer) 26 | players[player].timer = {} 27 | removeTextArea(98900000000, player) 28 | giveExperiencePoints(player, 100) 29 | job_updatePlayerStats(player, 2) 30 | giveCoin(jobs['thief'].coins, player, true) 31 | TFM.setNameColor(player, 0) 32 | end 33 | end, 1000, room.robbing.robbingTimer) 34 | 35 | chatMessage(''..translate('copAlerted', player), player) 36 | TFM.setNameColor(player, 0xFF0000) 37 | 38 | for _, cop in next, jobs['police'].working do 39 | chatMessage('['..translate('alert', cop)..'] '.. player, cop) 40 | end 41 | end -------------------------------------------------------------------------------- /source/lifeStats.lua: -------------------------------------------------------------------------------- 1 | local lifeStatsIcons = { 2 | {'171653c0aa6.png', '17174d72c5e.png', '17174d81707.png'}, 3 | {'170f8acc9f4.png', '170f8ac976f.png', '170f8acf954.png'} 4 | } 5 | 6 | showLifeStats = function(player, lifeStat) 7 | local playerInfos = players[player] 8 | if playerInfos.editingHouse then return end 9 | 10 | for i = 1, #playerInfos.lifeStatsImages[lifeStat].images do 11 | removeImage(playerInfos.lifeStatsImages[lifeStat].images[i]) 12 | end 13 | playerInfos.lifeStatsImages[lifeStat].images = {} 14 | local selectedImage = playerInfos.lifeStats[lifeStat] > 80 and 1 or playerInfos.lifeStats[lifeStat] > 40 and 2 or 3 15 | 16 | playerInfos.lifeStatsImages[lifeStat].images[#playerInfos.lifeStatsImages[lifeStat].images+1] = addImage(lifeStatsIcons[lifeStat][selectedImage], ":2", (lifeStat-1)*45, 365, player) 17 | if playerInfos.lifeStats[lifeStat] <= 0 then 18 | playerInfos.hospital.diseases[#playerInfos.hospital.diseases+1] = lifeStat 19 | loadHospital(player) 20 | checkIfPlayerIsDriving(player) 21 | hospitalize(player) 22 | loadHospitalFloor(player) 23 | players[player].lifeStats[lifeStat] = 0 24 | end 25 | showTextArea(999995-lifeStat*2, "

"..playerInfos.lifeStats[lifeStat], player, 11 + (lifeStat-1)*45, 386, 50, nil, 0x324650, 0x000000, 0, true) 26 | showTextArea(999994-lifeStat*2, "

"..playerInfos.lifeStats[lifeStat], player, 10 + (lifeStat-1)*45, 385, 50, nil, 0x324650, 0x000000, 0, true) 27 | end 28 | 29 | setLifeStat = function(player, lifeStat, quant) 30 | quant = quant or 0 31 | if not players[player].dataLoaded then return end 32 | players[player].lifeStats[lifeStat] = players[player].lifeStats[lifeStat] + quant 33 | 34 | if quant > 0 then 35 | if lifeStat == 2 then 36 | sideQuest_sendTrigger(player, 'recoveHunger', quant) 37 | else 38 | sideQuest_sendTrigger(player, 'recoveEnergy', quant) 39 | end 40 | else 41 | if lifeStat == 2 then 42 | sideQuest_sendTrigger(player, 'loseHunger', -quant) 43 | else 44 | sideQuest_sendTrigger(player, 'loseEnergy', -quant) 45 | end 46 | end 47 | 48 | if players[player].lifeStats[lifeStat] > 100 then 49 | players[player].lifeStats[lifeStat] = 100 50 | end 51 | showLifeStats(player, lifeStat) 52 | end 53 | 54 | updateLifeBar = function(player) 55 | local playerInfos = players[player] 56 | if not playerInfos then return end 57 | if playerInfos.hospital.hospitalized then return end 58 | if playerInfos.lifeStats[1] <= 94 and not playerInfos.robbery.robbing then 59 | setLifeStat(player, 1, playerInfos.place == 'cafe' and 3 or 2) 60 | if string_find(playerInfos.place, 'house_') then 61 | local house_ = playerInfos.place:sub(7) 62 | if playerInfos.houseData.houseid == house_ then 63 | setLifeStat(player, 1, 1) 64 | end 65 | end 66 | end 67 | setLifeStat(player, 2, -1) 68 | end -------------------------------------------------------------------------------- /source/map/loadMap.lua: -------------------------------------------------------------------------------- 1 | loadMap = function(name) -- TO REWRITE 2 | if room.bankBeingRobbed and players[name].driving then return end 3 | showTextArea(1028, '

' .. translate('goTo', name) .. '\n', name, 440, 1600+room.y, 200, 30, 0x122528, 0x122528, 0.7) 4 | showTextArea(1021, '

' .. translate('goTo', name) .. '\n', name, 990, 1600+room.y, 200, 30, 0x122528, 0x122528, 0.7) 5 | showTextArea(1022, '

' .. translate('goTo', name) .. '\n', name, 3445, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 6 | showTextArea(1025, '

' .. translate('goTo', name) .. '\n', name, 4675, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 7 | showTextArea(1027, '

' .. translate('goTo', name) .. '\n', name, 4960, 1775+room.y+11, 310, 40, 0x122528, 0x122528, 0.7) 8 | showTextArea(459, '

' .. translate('goTo', name) .. '\n', name, 11177, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 9 | showTextArea(458, '

' .. translate('goTo', name) .. '\n', name, 10027, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 10 | 11 | showTextArea(1051, '

' .. translate('goTo', name) .. '\n', name, 5868, 7615, 200, 30, 0x122528, 0x122528, 0.7) 12 | 13 | if room.bankBeingRobbed then 14 | showTextArea(1029, '

' .. translate('robberyInProgress', name) .. '\n', name, 2670, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 15 | else 16 | showTextArea(1029, '

' .. translate('goTo', name) .. '\n', name, 2670, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 17 | end 18 | 19 | showTextArea(1026, '

' .. translate('goTo', name) .. '\n', name, 10950+300, 8750, 200, 30, 0x122528, 0x122528, 0.7) 20 | if players[name].questStep[1] > 1 then 21 | showTextArea(1036, '

' .. translate('goTo', name) .. '\n', name, 5622, 7615, 200, 30, 0x122528, 0x122528, 0.7) 22 | else 23 | showTextArea(1036, '' .. translate('enterQuestPlace', name):format(translate('req_1', name)), name, 5622, 7615, 200, 30, 0x122528, 0x122528, 0.7) 24 | end 25 | if players[name].questStep[1] > 2 then 26 | showTextArea(1031, '

' .. translate('goTo', name) .. '\n', name, 9730, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 27 | else 28 | showTextArea(1031, '' .. translate('enterQuestPlace', name):format(translate('req_2', name)), name, 9730, 1800+room.y, 200, nil, 0x122528, 0x122528, 0.7) 29 | end 30 | if players[name].questStep[1] > 3 then 31 | showTextArea(1026, '

' .. translate('goTo', name) .. '\n', name, 10300, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 32 | else 33 | showTextArea(1026, '' .. translate('enterQuestPlace', name):format(translate('req_3', name)), name, 10300, 1800+room.y, 200, nil, 0x122528, 0x122528, 0.7) 34 | end 35 | if players[name].questStep[1] > 4 then 36 | showTextArea(1032, '

' .. translate('goTo', name) .. '\n', name, 4310, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 37 | else 38 | showTextArea(1032, ''.. translate('enterQuestPlace', name):format(translate('req_4', name)), name, 4310, 1800+room.y, 200, nil, 0x122528, 0x122528, 0.7) 39 | end 40 | showTextArea(1034, '

' .. translate('goTo', name), name, 11858, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.7) 41 | end -------------------------------------------------------------------------------- /source/map/lobby.lua: -------------------------------------------------------------------------------- 1 | genLobby = function() 2 | room.isInLobby = true 3 | TFM.newGame('

') 4 | room.started = false 5 | startRoom() 6 | removeTimer(room.temporaryTimer) 7 | room.temporaryTimer = addTimer(function(j) 8 | for i in next, ROOM.playerList do 9 | showTextArea(0, "

".. translate('waitingForPlayers', i) .."
"..ROOM.uniquePlayers.."/"..room.requiredPlayers.."

", i, 0, 35, 800, nil, 1, 1, 0.3) 10 | local lang = players[i].lang 11 | local tip = tips[lang] and tips[lang][random(1, #tips[lang])] or tips['en'][random(1, #tips['en'])] 12 | showTextArea(1, "

"..tip.."

", i, 0, 105, 800, nil, 1, 1, 0.3) 13 | end 14 | end, 5000, 0) 15 | end -------------------------------------------------------------------------------- /source/misc/badges.lua: -------------------------------------------------------------------------------- 1 | local badgesPriority = { 2 | 10, 5, 2, 3, 15, 16, 17, 18, 19, 4, 8, 25, 9, 14, 0, 6, 7, 20, 24, 26, 1, 11, 12, 13, 21, 22, 23, 27 3 | } 4 | 5 | badges = { 6 | [0] = { -- Halloween2019 7 | png = '1769050490e.png', 8 | }, 9 | [1] = { -- meet Fofinhoppp 10 | png = '171e0f4e290.png', 11 | }, 12 | [2] = { -- fish 500 times 13 | png = '171dba5770c.png', 14 | }, 15 | [3] = { -- mine 1000 gold nuggets 16 | png = '171e1010745.png', 17 | }, 18 | [4] = { -- harvested 500 plants 19 | png = '171e0f9de0e.png', 20 | }, 21 | [5] = { -- Rob 500 times 22 | png = '16f1a7af2f0.png', 23 | }, 24 | [6] = { -- Christmas2019 25 | png = '16f23df7a05.png', 26 | }, 27 | [7] = { -- Buy the sleigh 28 | png = '16f1fe3812d.png', 29 | }, 30 | [8] = { -- Sell 500 seeds 31 | png = '171db390cbe.png', 32 | }, 33 | [9] = { -- Fulfill 500 orders 34 | png = '174b20f6c7d.png', 35 | }, 36 | [10] = { -- Arrest 500 players 37 | png = '171db99a9e3.png', 38 | }, 39 | [11] = { -- Season 1 reward 40 | png = '1733ad217ba.png', 41 | season = 1, 42 | }, 43 | [12] = { -- Season 2 reward 44 | png = '17479ba02f4.png', 45 | season = 2, 46 | }, 47 | [13] = { -- Season 3 reward 48 | png = '17479ba7052.png', 49 | season = 3, 50 | }, 51 | [14] = { -- Cook 500 dishes 52 | png = '1769050831b.png', 53 | }, 54 | [15] = { -- Sold 300 yellow crystals 55 | png = '174b2214c49.png', 56 | }, 57 | [16] = { -- Sold 150 blue crystals 58 | png = '174b2221bf9.png', 59 | }, 60 | [17] = { -- Sold 75 purple crystals 61 | png = '174b2224164.png', 62 | }, 63 | [18] = { -- Sold 30 green crystals 64 | png = '174b2226e7d.png', 65 | }, 66 | [19] = { -- Sold 10 red crystals 67 | png = '174b22294f7.png', 68 | }, 69 | [20] = { -- Halloween2020 70 | png = '17537f7806f.png', 71 | }, 72 | [21] = { -- Season 4 reward 73 | png = '17529b1df9b.png', 74 | season = 4, 75 | }, 76 | [22] = { -- Season 5 reward 77 | png = '175d2a8ae26.png', 78 | season = 5, 79 | }, 80 | [23] = { -- Season 6 reward 81 | png = '17690581d74.png', 82 | season = 6, 83 | }, 84 | [24] = { -- Christmas2020 85 | png = '176905067bc.png', 86 | }, 87 | [25] = { -- Sell 500 fruits 88 | png = '17dd4a42ccb.png', 89 | }, 90 | [26] = { -- Christmas2021 91 | png = '17dd4a374e9.png', 92 | }, 93 | [27] = { -- Christmas2021 (Season 7) reward 94 | png = '17e582cb13e.png', 95 | season = 7, 96 | }, 97 | } -------------------------------------------------------------------------------- /source/misc/bagIcons.lua: -------------------------------------------------------------------------------- 1 | bagIcons = { 2 | '170fa52959e.png', 3 | '170fa52b3f4.png', 4 | '170fa52d22d.png', 5 | '170fa52ed70.png', 6 | '1710c4d7d09.png', 7 | '172af53daad.png', 8 | '17725835470.png', 9 | '17725832d18.png', 10 | } -------------------------------------------------------------------------------- /source/misc/bankCodes.lua: -------------------------------------------------------------------------------- 1 | codesIds = { 2 | [0] = {n = 'WELCOME'}, 3 | [1] = {n = 'BOOM'}, 4 | [2] = {n = 'OFFICIAL'}, 5 | [3] = {n = 'GOLD'}, 6 | [4] = {n = 'MYCITY'}, 7 | [5] = {n = 'WINTER'}, 8 | [6] = {n = 'XMAS'}, 9 | [7] = {n = 'BLUEBERRY'}, 10 | [8] = {n = 'COINS'}, 11 | [9] = {n = 'GARDENING'}, 12 | [10] = {n = 'XP'}, 13 | [11] = {n = 'FLOUR'}, 14 | } 15 | 16 | codes = { 17 | ['WELCOME'] = { 18 | id = 0, 19 | uses = 1, 20 | available = false, 21 | }, 22 | ['BOOM'] = { 23 | id = 1, 24 | uses = 1, 25 | available = false, 26 | }, 27 | ['OFFICIAL'] = { 28 | id = 2, 29 | uses = 1, 30 | available = false, 31 | }, 32 | ['GOLD'] = { 33 | id = 3, 34 | uses = 1, 35 | available = false, 36 | }, 37 | ['MYCITY'] = { 38 | id = 4, 39 | uses = 1, 40 | available = false, 41 | }, 42 | ['WINTER'] = { 43 | id = 5, 44 | uses = 1, 45 | available = false, 46 | level = 3, 47 | }, 48 | ['XMAS'] = { 49 | id = 6, 50 | uses = 1, 51 | available = false, 52 | level = 4, 53 | }, 54 | ['BLUEBERRY'] = { 55 | id = 7, 56 | uses = 1, 57 | available = false, 58 | level = 3, 59 | }, 60 | ['COINS'] = { 61 | id = 8, 62 | uses = 1, 63 | available = false, 64 | level = 2, 65 | }, 66 | ['GARDENING'] = { 67 | id = 9, 68 | uses = 1, 69 | available = false, 70 | level = 3, 71 | }, 72 | ['XP'] = { 73 | id = 10, 74 | uses = 1, 75 | available = true, 76 | reward = function(player) 77 | giveExperiencePoints(player, 500) 78 | alert_Error(player, 'atmMachine', 'codeReceived', translate('experiencePoints', player)..': 500') 79 | end, 80 | }, 81 | ['FLOUR'] = { 82 | id = 11, 83 | uses = 1, 84 | available = true, 85 | level = 3, 86 | reward = function(player) 87 | addItem('wheatFlour', 8, player) 88 | alert_Error(player, 'atmMachine', 'codeReceived', translate('item_wheatFlour', player)..': 8') 89 | end, 90 | }, 91 | } -------------------------------------------------------------------------------- /source/misc/communityFlag.lua: -------------------------------------------------------------------------------- 1 | community = { 2 | ['af'] = "1749dbddd5c.png", 3 | ['az'] = "1749d8b3308.png", 4 | ['id'] = "1749d9ac80b.png", 5 | ['ms'] = "1749da2fc01.png", 6 | ['bi'] = "1749dbd6826.png", 7 | ['bs'] = "1749d8b4a7a.png", 8 | ['ca'] = "1749da13e9a.png", 9 | ['ny'] = "", 10 | ['da'] = "", 11 | ['de'] = "1749d96d7f6.png", 12 | ['et'] = "1749d977c12.png", 13 | ['na'] = "", 14 | ['en'] = "1749d98c447.png", 15 | ['es'] = "1749d97d9d5.png", 16 | ['to'] = "1749dbbd1c9.png", 17 | ['mg'] = "1749da184ee.png", 18 | ['fr'] = "1749d989562.png", 19 | ['sm'] = "", 20 | ['hr'] = "1749d9a6a44.png", 21 | ['it'] = "1749d9e8716.png", 22 | ['mh'] = "1749da19c5f.png", 23 | ['kl'] = "", 24 | ['rn'] = "", 25 | ['rw'] = "1749da7bb63.png", 26 | ['sw'] = "", 27 | ['ht'] = "1749d9a81b6.png", 28 | ['lv'] = "1749da0e0d0.png", 29 | ['lt'] = "1749da0b1ed.png", 30 | ['lb'] = "", 31 | ['he'] = "1749d9af6ef.png", 32 | ['hu'] = "1749d9a9927.png", 33 | ['mt'] = "1749da286cb.png", 34 | ['nl'] = "1749da588c7.png", 35 | ['no'] = "1749da5a039.png", 36 | ['uz'] = "1749dbcc40a.png", 37 | ['pl'] = "1749da6b98b.png", 38 | ['pt'] = "1749da7174a.png", 39 | ['br'] = "1749d8c7b3c.png", 40 | ['ro'] = "1749da77511.png", 41 | ['qu'] = "", 42 | ['st'] = "", 43 | ['tn'] = "", 44 | ['sq'] = "", 45 | ['ss'] = "", 46 | ['sk'] = "1749da88e5a.png", 47 | ['sl'] = "", 48 | ['so'] = "1749dba339d.png", 49 | ['fi'] = "1749d982028.png", 50 | ['sv'] = "", 51 | ['tl'] = "", 52 | ['vi'] = "", 53 | ['tk'] = "", 54 | ['tr'] = "1749dbbe93a.png", 55 | ['fj'] = "1749d98379a.png", 56 | ['wo'] = "", 57 | ['yo'] = "", 58 | ['is'] = "1749d9e6fa5.png", 59 | ['cs'] = "", 60 | ['el'] = "", 61 | ['be'] = "", 62 | ['ky'] = "", 63 | ['mn'] = "1749da1fa24.png", 64 | ['ru'] = "1749da7a3f2.png", 65 | ['sr'] = "", 66 | ['tg'] = "", 67 | ['uk'] = "", 68 | ['bg'] = "1749d8bbfb0.png", 69 | ['kk'] = "", 70 | ['hy'] = "", 71 | ['ur'] = "", 72 | ['ar'] = "1749d979383.png", 73 | ['fa'] = "", 74 | ['dv'] = "", 75 | ['ne'] = "1749da5b7aa.png", 76 | ['hi'] = "", 77 | ['bn'] = "", 78 | ['ta'] = "1749da06b98.png", 79 | ['th'] = "1749dbb4520.png", 80 | ['lo'] = "", 81 | ['dz'] = "", 82 | ['my'] = "", 83 | ['ka'] = "", 84 | ['ti'] = "", 85 | ['am'] = "", 86 | ['km'] = "", 87 | ['cn'] = "1749d8df255.png", 88 | ['zh'] = "", 89 | ['ja'] = "1749d9ef47d.png", 90 | ['ko'] = "", 91 | ['xx'] = "174971ff384.png", 92 | ['int'] = "174971ff384.png", 93 | } -------------------------------------------------------------------------------- /source/misc/jobRewards.lua: -------------------------------------------------------------------------------- 1 | jobRewards = { 2 | [1] = { -- Arrest 500 times 3 | requires = 500, 4 | callback = function(player) 5 | giveBadge(player, 10) 6 | end 7 | }, 8 | [2] = { -- Rob 500 times 9 | requires = 500, 10 | callback = function(player) 11 | giveBadge(player, 5) 12 | end 13 | }, 14 | [3] = { -- Fish 500 times 15 | requires = 500, 16 | callback = function(player) 17 | giveBadge(player, 2) 18 | end 19 | }, 20 | [4] = { -- Mine 1000 gold nuggets 21 | requires = 1000, 22 | callback = function(player) 23 | giveBadge(player, 3) 24 | end 25 | }, 26 | [5] = { -- Harvest 500 times 27 | requires = 500, 28 | callback = function(player) 29 | giveBadge(player, 4) 30 | end 31 | }, 32 | [6] = { -- Sell 500 seeds 33 | requires = 500, 34 | callback = function(player) 35 | giveBadge(player, 8) 36 | end 37 | }, 38 | [9] = { -- Deliver 500 orders 39 | requires = 500, 40 | callback = function(player) 41 | giveBadge(player, 9) 42 | end 43 | }, 44 | [10] = { -- Cook 500 dishes 45 | requires = 500, 46 | callback = function(player) 47 | giveBadge(player, 14) 48 | end 49 | }, 50 | [11] = { -- Sell 500 fruits 51 | requires = 500, 52 | callback = function(player) 53 | giveBadge(player, 25) 54 | end 55 | }, 56 | [12] = { -- Sold 300 yellow crystals 57 | requires = 300, 58 | callback = function(player) 59 | giveBadge(player, 15) 60 | end 61 | }, 62 | [13] = { -- Sold 150 blue crystals 63 | requires = 150, 64 | callback = function(player) 65 | giveBadge(player, 16) 66 | end 67 | }, 68 | [14] = { -- Sold 75 purple crystals 69 | requires = 75, 70 | callback = function(player) 71 | giveBadge(player, 17) 72 | end 73 | }, 74 | [15] = { -- Sold 30 green crystals 75 | requires = 30, 76 | callback = function(player) 77 | giveBadge(player, 18) 78 | end 79 | }, 80 | [16] = { -- Sold 10 red crystals 81 | requires = 10, 82 | callback = function(player) 83 | giveBadge(player, 19) 84 | end 85 | } 86 | --17: Halloween 2019 87 | --24: Christmas 2020 88 | --26: Christmas 2021 89 | } -------------------------------------------------------------------------------- /source/npcs/gameNpcs/addCharacter.lua: -------------------------------------------------------------------------------- 1 | gameNpcs.addCharacter = function(name, image, player, x, y, properties, ...) 2 | if not properties then properties = {} end 3 | local playerData = players[player] 4 | local hideName = properties.hideName 5 | 6 | if properties.questNPC and playerData._npcsCallbacks.questNPCS[name] then return end 7 | local type = properties.type and properties.type or '!' 8 | local canClick = true 9 | local canOrder = true 10 | local imageFixAlign = {0, 0} 11 | if not image[2] then 12 | image[2] = image[1] 13 | imageFixAlign = {0, -23} 14 | end 15 | local npcID = playerData._npcsAdded 16 | 17 | local color = '6c99d6' 18 | if properties.job then 19 | color = jobs[properties.job].color 20 | if properties.jobConfirm then 21 | if not properties.endEvent then 22 | properties.callback = function(player) job_invite(properties.job, player) end 23 | end 24 | addImage('17408124c64.png', "!30", x+38, y+20, player) 25 | end 26 | elseif properties.color then 27 | color = properties.color 28 | elseif properties.canRob then 29 | color = 'FF69B4' 30 | canOrder = false 31 | elseif properties.questNPC then 32 | color = 'b69efd' 33 | canOrder = false 34 | playerData._npcsCallbacks.questNPCS[name] = {id = npcID} 35 | local newName = name:gsub('%$', '') 36 | canClick = quest_checkIfCanTalk(playerData.questStep[1], playerData.questStep[2], newName) 37 | if gameNpcs.characters[newName] and not image[1] then 38 | local v = gameNpcs.characters[newName] 39 | x = v.x 40 | y = v.y 41 | image[1] = '171a497f4e2.png' 42 | image[2] = v.image2 43 | imageFixAlign = {0, 0} 44 | for id, obj in next, playerData._npcsCallbacks.starting do 45 | if obj.name == newName then 46 | playerData._npcsCallbacks.ending[npcID] = {callback = playerData._npcsCallbacks.starting[id].callback, name = name} 47 | break 48 | end 49 | end 50 | end 51 | end 52 | if properties.formatDialog then 53 | playerData._npcsCallbacks.formatDialog[name] = properties.formatDialog 54 | end 55 | 56 | local callback = 'npcDialog_talkWith_'..npcID..'_'..name..'_'..image[2] 57 | if properties.callback then 58 | callback = 'npcDialog_talkWith_'..npcID..'_otherCallback' 59 | playerData._npcsCallbacks.starting[npcID] = {callback = properties.callback, name = name} 60 | elseif properties.endEvent then 61 | playerData._npcsCallbacks.ending[npcID] = {callback = properties.endEvent, name = name} 62 | elseif properties.sellingItems then 63 | callback = 'npcDialog_talkWith_'..npcID..'_otherCallback' 64 | playerData._npcsCallbacks.starting[npcID] = {callback = function(player) showNPCShop(player, name) end, name = name} 65 | addImage('174080a7702.png', "!30", x+38, y+20, player) 66 | elseif properties.questNPC then 67 | callback = callback .. '_questDialog' 68 | end 69 | 70 | if not gameNpcs.characters[name] then 71 | if canOrder then 72 | gameNpcs.orders.canOrder[name] = properties.place or 'town' 73 | end 74 | 75 | gameNpcs.characters[name] = {visible = true, x = x, y = y, type = type, players = {}, runningImages = nil, image = image[1], image2 = image[2], callback = callback, color = color, fixAlign = imageFixAlign, place = properties.place} 76 | if properties.canRob then 77 | gameNpcs.robbing[name] = {x = x+50, y = y+80, cooldown = properties.canRob.cooldown} 78 | end 79 | if properties.sellingItems then 80 | gameNpcs.selling[name] = true 81 | end 82 | 83 | imgsToLoad[#imgsToLoad+1] = image[1] 84 | imgsToLoad[#imgsToLoad+1] = image[2] 85 | end 86 | 87 | playerData._npcsCallbacks.clickArea[npcID] = {x + 50, y + 80, name} 88 | 89 | gameNpcs.characters[name].players[player] = {id = npcID} 90 | if gameNpcs.characters[name].visible and players[player] then 91 | gameNpcs.characters[name].players[player] = {id = npcID, image = addImage(image[1], type.."1000", x, y, player, ...), properties = (...)} 92 | 93 | local id = -89000+(npcID*6) 94 | gameNpcs.setNPCName(id, name:gsub('%$', ''), callback, player, x, y, color, canClick, hideName) 95 | end 96 | players[player]._npcsAdded = npcID + 1 97 | end -------------------------------------------------------------------------------- /source/npcs/gameNpcs/daveOffers.lua: -------------------------------------------------------------------------------- 1 | mainAssets.__farmOffers = { 2 | [1] = { 3 | item = {'bananaSeed', 1}, 4 | requires = {'grilledLobster', 3}, 5 | }, 6 | [2] = { 7 | item = {'lettuce', 5}, 8 | requires = {'tomato', 10}, 9 | }, 10 | [3] = { 11 | item = {'egg', 2}, 12 | requires = {'wheat', 15}, 13 | }, 14 | [4] = { 15 | item = {'honey', 2}, 16 | requires = {'bread', 3}, 17 | }, 18 | [5] = { 19 | item = {'honey', 2}, 20 | requires = {'lemon', 5}, 21 | }, 22 | [6] = { 23 | item = {'garlic', 3}, 24 | requires = {'wheat', 15}, 25 | }, 26 | [7] = { 27 | item = {'potato', 5}, 28 | requires = {'tomato', 10}, 29 | }, 30 | [8] = { 31 | item = {'pumpkin', 1}, 32 | requires = {'chocolateCake', 2}, 33 | }, 34 | [9] = { 35 | item = {'egg', 1}, 36 | requires = {'lemon', 2}, 37 | }, 38 | [10] = { 39 | item = {'potato', 1}, 40 | requires = {'pepper', 2}, 41 | }, 42 | [11] = { 43 | item = {'lettuce', 5}, 44 | requires = {'oregano', 10}, 45 | }, 46 | [12] = { 47 | item = {'banana', 5}, 48 | requires = {'lemon', 3}, 49 | }, 50 | [13] = { 51 | item = {'bananaSeed', 1}, 52 | requires = {'chocolateCake', 5}, 53 | }, 54 | [14] = { 55 | item = {'meat', 1}, 56 | requires = {'cheese', 3}, 57 | }, 58 | [15] = { 59 | item = {'garlic', 3}, 60 | requires = {'banana', 3}, 61 | }, 62 | [16] = { 63 | item = {'mushroom', 3}, 64 | requires = {'fish_Frog', 2}, 65 | }, 66 | [17] = { 67 | item = {'garlic', 5}, 68 | requires = {'frenchFries', 3}, 69 | }, 70 | [18] = { 71 | item = {'meat', 1}, 72 | requires = {'fish_Smolty', 3}, 73 | }, 74 | } -------------------------------------------------------------------------------- /source/npcs/gameNpcs/setOrder.lua: -------------------------------------------------------------------------------- 1 | local circleSlices = { 2 | [ 1] = '174558f6393.png', 3 | [ 2] = '1745588b429.png', 4 | [ 3] = '17455904362.png', 5 | [ 4] = '17455876d27.png', 6 | [ 5] = '1745590f162.png', 7 | [ 6] = '17455847e27.png', 8 | [ 7] = '1745591a12a.png', 9 | [ 8] = '1745581e99b.png', 10 | [ 9] = '174559244ca.png', 11 | [10] = '1745572fc55.png', 12 | [11] = '1745592d979.png', 13 | [12] = '174557c2791.png', 14 | [13] = '17455936450.png', 15 | [14] = '174557f051a.png', 16 | } 17 | 18 | local currentOrders = { 19 | images = {}, 20 | orders = {}, 21 | index = {}, 22 | } 23 | 24 | showDishOrders = function(target) 25 | if not target then 26 | removeGroupImages(currentOrders.images) 27 | end 28 | 29 | local counter = 0 30 | for npc, order in next, currentOrders.orders do 31 | currentOrders.images[#currentOrders.images+1] = addImage(bagItems[order].png, "_1000", 15900, 1560+counter*40, target) 32 | showTextArea(4444441+counter, npc, target, 15940, 1575+counter*40, nil, nil, 1, 1, 0) 33 | currentOrders.index[npc] = counter 34 | counter = counter + 1 35 | end 36 | end 37 | 38 | gameNpcs.setOrder = function(npcName) 39 | local npc = gameNpcs.characters[npcName] 40 | local image = npc.image 41 | local type = npc.type 42 | local x = npc.x 43 | local y = npc.y 44 | local character = gameNpcs.orders 45 | local order = table_randomKey(recipes) 46 | local place = character.canOrder[npcName] 47 | local orderTime = random(60*2, 60*3) 48 | 49 | character.orderList[npcName] = {order = order, fulfilled = {}} 50 | character.canOrder[npcName] = nil 51 | removeGroupImages(character.trashImages) 52 | currentOrders.orders[npcName] = order 53 | 54 | showDishOrders() 55 | 56 | local images = character.orderList[npcName].fulfilled 57 | local function addDataToPlayer(player) 58 | images[player] = { 59 | icons = { 60 | addImage('171c7ac4232.png', type.."1000", x, y-20, player), 61 | addImage(bagItems[order].png, type.."1000", x+25, y-20, player), 62 | }, 63 | completed = false, 64 | } 65 | end 66 | for _, player in next, jobs['chef'].working do 67 | addDataToPlayer(player) 68 | end 69 | 70 | local currentSlice = 14 71 | local sliceDuration = math.ceil(orderTime/14) 72 | local stopwatch = addImage('174082ea765.png', "_1001", 16020, 1577 + currentOrders.index[npcName]*40) 73 | local stopwatchTimer 74 | 75 | stopwatchTimer = addTimer(function(time) 76 | currentSlice = currentSlice - 1 77 | removeImage(stopwatch) 78 | stopwatch = addImage(circleSlices[currentSlice], "_1001", 16020, 1577 + currentOrders.index[npcName]*40) 79 | end, sliceDuration * 1000, 0) 80 | 81 | addTimer(function(time) 82 | local images = character.orderList[npcName].fulfilled 83 | for player, k in next, images do 84 | if not k.completed then 85 | removeGroupImages(k.icons) 86 | end 87 | end 88 | character.orderList[npcName] = nil 89 | character.canOrder[npcName] = place 90 | local nextOrder 91 | while true do 92 | nextOrder = table_randomKey(character.canOrder) 93 | --chatMessage('Trying to choose '..nextOrder) 94 | local isOpened = places[character.canOrder[nextOrder]].opened 95 | if checkGameHour(isOpened) or isOpened == '-' then 96 | --chatMessage(''..character.canOrder[nextOrder]..' is opened!') 97 | break 98 | end 99 | --chatMessage(''..character.canOrder[nextOrder]..' is closed!') 100 | end 101 | --chatMessage(''..nextOrder..' was chosen!') 102 | removeImage(stopwatch) 103 | removeTimer(stopwatchTimer) 104 | currentOrders.index[npcName] = nil 105 | currentOrders.orders[npcName] = nil 106 | 107 | gameNpcs.setOrder(nextOrder) 108 | end, orderTime * 1000, 1) 109 | end -------------------------------------------------------------------------------- /source/npcs/gameNpcs/talk.lua: -------------------------------------------------------------------------------- 1 | gameNpcs.talk = function(npc, player) 2 | local playerData = players[player] 3 | local lang = playerData.lang 4 | local npcText = npcDialogs.normal[lang][npc.name] and npcDialogs.normal[lang][npc.name] or (npc.name:find('Souris') and {' '} or npcDialogs.normal[lang]['Natasha']) 5 | if npc.questDialog then 6 | npcText = npcDialogs 7 | .quests 8 | [lang] 9 | [playerData.questStep[1]] 10 | [playerData.questStep[2]] 11 | end 12 | local dialog = npc.text or npcText 13 | dialog = table_copy(dialog) 14 | local formatText = playerData._npcsCallbacks.formatDialog[npc.name] 15 | 16 | if formatText == 'fishingLuckiness' then 17 | local lucky = playerData.lucky[1] 18 | dialog[3] = dialog[3]:format(lucky.normal..'%', lucky.rare..'%', lucky.mythical..'%') 19 | dialog[4] = dialog[4]:format(lucky.legendary..'%') 20 | elseif formatText == 'christmasEventEnds' then 21 | dialog[7] = dialog[7]:format(formatDaysRemaining(os_time{day=15, year=2022, month=1})) 22 | end 23 | 24 | dialogs[player] = {name = npc.name, text = dialog, length = 0, currentPage = 1, running = true, npcID = npc.npcID, isQuest = npc.questDialog} 25 | local tbl = players[player]._npcDialogImages 26 | 27 | local alignFix = gameNpcs.characters[npc.name].fixAlign 28 | if not npcDialogs.normal[lang][npc.name] and npc.image ~= gameNpcs.characters[npc.name].image2 then 29 | alignFix = {0, -23} 30 | end 31 | tbl[#tbl+1] = addImage('17184484e6b.png', ":0", 0, 0, player) 32 | tbl[#tbl+1] = addImage('1718435fa5c.png', ":1", 300, 250, player) 33 | tbl[#tbl+1] = addImage(npc.image, ":2", 270+alignFix[1], 260+alignFix[2], player) 34 | tbl[#tbl+1] = addImage('171843a9f21.png', ":3", 270, 330, player) 35 | --npc.name = npc.name:gsub('$', '') 36 | local font = 15 37 | if #npc.name > 8 then 38 | font = 12 39 | elseif #npc.name > 13 then 40 | font = 10 41 | end 42 | showTextArea(-88000, '

' .. translate('robberyInProgress', name) .. '', name, 2670, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.3) 16 | end 17 | if players[name].place == 'bank' then 18 | if players[name].job ~= 'police' then 19 | job_hire('thief', name) 20 | chatMessage(''..translate('copAlerted', name), name) 21 | end 22 | end 23 | if players[name].job == 'police' then 24 | chatMessage(''..translate('bankRobAlert', name)..'', name) 25 | end 26 | if players[name].questLocalData.other.goToBankRob then 27 | quest_updateStep(name) 28 | end 29 | end 30 | local lightImage = nil 31 | removeImage(room.bankDoors[1]) 32 | removeImage(room.bankDoors[2]) 33 | removeImage(room.bankDoors[3]) 34 | removeImage(room.bankDoors[4]) 35 | removeImage(room.bankDoors[5]) 36 | room.bankDoors[1] = addImage("16baf05e96a.png", "!36", 5787, 4596) 37 | room.bankDoors[2] = addImage("16bb46e2a7c.png", "!36", 5243, 4718) 38 | room.bankDoors[3] = addImage("16bb46e2a7c.png", "!37", 5792, 4926) 39 | room.bankDoors[4] = addImage("16bb98e5d8f.png", "!38", 5988, 4930) -- lever 40 | room.bankDoors[5] = addImage("16bb493c28e.png", "!36", 5275, 4812) -- lasers 41 | 42 | 43 | addGround(9999, 7+5791, 66+30+4596, {type = 14, width = 12, height = 190}) 44 | addGround(9997, 260+5000, 135+4555, {type = 14, width = 25, height = 200}) 45 | addGround(9996, 88+5275, 80+4812, {type = 14, width = 200, angle = 45, restitution = 999}) -- laser 46 | addGround(9995, 232+5275, 80+4812, {type = 14, width = 200, angle = -45, restitution = 999}) -- laser 47 | addGround(9994, 809+5000, 338+4555, {type = 14, width = 25, height = 200}) 48 | 49 | showTextArea(-5950, ''..string.rep('\n', 5), nil, 5990, 4935, 25, 25, 0x324650, 0x0, 0) 50 | 51 | addTimer(function(time) 52 | if room.bankRobStep == 'vault' then 53 | for player, v in next, ROOM.playerList do 54 | if players[player].place == 'bank' then 55 | if not players[player].robbery.robbing then 56 | if v.x > 5791 and v.x < 6014 and v.y > 4596 and v.y < 4785 then 57 | if players[player].job == 'thief' then 58 | players[player].timer = addTimer(function(j) 59 | local time = room.robbing.bankRobbingTimer - j 60 | showTextArea(98900000001, "

"..translate('runAway', player):format(time)..'\n'..translate('runAwayCoinInfo', player):format('$'..jobs['thief'].bankRobCoins), player, 250, 370, 250, nil, 0x1, 0x1, 0, true) 61 | if j == room.robbing.bankRobbingTimer then 62 | players[player].robbery.robbing = false 63 | removeTimer(players[player].timer) 64 | players[player].timer = {} 65 | removeTextArea(98900000001, player) 66 | giveCoin(jobs['thief'].bankRobCoins, player, true) 67 | TFM.setNameColor(player, 0) 68 | giveExperiencePoints(player, 250) 69 | job_updatePlayerStats(player, 2) 70 | sideQuest_sendTrigger(player, 'bank', 1) 71 | end 72 | end, 1000, room.robbing.bankRobbingTimer) 73 | 74 | players[player].robbery.robbing = true 75 | TFM.setNameColor(player, 0xFF0000) 76 | end 77 | end 78 | end 79 | end 80 | end 81 | end 82 | if time%2 == 0 then 83 | if lightImage then 84 | removeImage(lightImage) 85 | end 86 | else 87 | lightImage = addImage('16b9521a7ac.png', '!999999', 5000+66, 4545) 88 | end 89 | if time == room.bankRobbingTime then 90 | room.bankBeingRobbed = false 91 | removeTextArea(-510, nil) 92 | removeImage(room.bankDoors[1]) 93 | for i = 1, #room.bankTrashImages do 94 | removeImage(room.bankTrashImages[i]) 95 | end 96 | room.bankTrashImages = {} 97 | for i in next, ROOM.playerList do 98 | showTextArea(1029, '

' .. translate('goTo', i) .. '', i, 2670, 1800+room.y, 200, 30, 0x122528, 0x122528, 0.3) 99 | if players[i].place == 'bank' then 100 | if players[i].job == 'thief' then 101 | if players[i].inRoom then 102 | arrestPlayer(i, 'Colt') 103 | end 104 | end 105 | end 106 | eventTextAreaCallback(1, i, 'closeVaultPassword', true) 107 | end 108 | reloadBankAssets() 109 | elseif time == room.bankRobbingTime - 5 then 110 | gameNpcs.showNPC('Colt') 111 | end 112 | end, 1000, room.bankRobbingTime) 113 | end -------------------------------------------------------------------------------- /source/places/events.lua: -------------------------------------------------------------------------------- 1 | closePlaces = function() 2 | for place, v in next, places do 3 | if not checkGameHour(v.opened) and v.opened ~= '-' then 4 | kickPlayersFromPlace(place) 5 | end 6 | end 7 | end 8 | 9 | kickPlayersFromPlace = function(place) 10 | for name in next, ROOM.playerList do 11 | local playerData = players[name] 12 | if playerData.place == place then 13 | if places[place].tp_town then 14 | movePlayer(name, places[place].tp_town[1], places[place].tp_town[2], false) 15 | playerData.place = 'town' 16 | else 17 | movePlayer(name, places[place].tp_island[1], places[place].tp_island[2], false) 18 | playerData.place = 'island' 19 | end 20 | alert_Error(name, 'timeOut', 'closed_'..place) 21 | end 22 | end 23 | end 24 | 25 | goToHouse = function(player, terrainID) 26 | players[player].place = 'house_'..terrainID 27 | loadFound(player, terrainID) 28 | movePlayer(player, ((terrainID-1)%terrainID)*1500+400, 1690, false) 29 | checkIfPlayerIsDriving(player) 30 | showTextArea(400, string.rep('\n', 3), player, ((terrainID-1)%terrainID)*1500 + 317, 1616 + 45, 25, 25, 0, 0, 0, false, 31 | function() 32 | leaveHouse(player, terrainID) 33 | end) 34 | if room.terrains[terrainID].owner ~= player then 35 | room.terrains[terrainID].guests[player] = true 36 | end 37 | if players[player].questLocalData.other.goToHouse or (terrainID == 12 and players[player].questLocalData.other.goToOliver) or (terrainID == 11 and players[player].questLocalData.other.goToRestaurant) then 38 | quest_updateStep(player) 39 | end 40 | 41 | if not room.terrains[terrainID].groundsLoadedTo[player] then 42 | HouseSystem.new(room.terrains[terrainID].owner):genHouseGrounds(player) 43 | room.terrains[terrainID].groundsLoadedTo[player] = true 44 | end 45 | end 46 | 47 | leaveHouse = function(player, terrainID) 48 | if not string_find(players[player].place, 'house_') or players[player].editingHouse then return end 49 | if terrainID == 12 then -- Oliver's Farm 50 | movePlayer(player, 11275, 7770, false) 51 | elseif terrainID == 11 then -- Remi's Restaurant 52 | movePlayer(player, 10200, 7770, false) 53 | else 54 | movePlayer(player, mainAssets.__terrainsPositions[terrainID][1], mainAssets.__terrainsPositions[terrainID][2]+184, false) 55 | end 56 | if terrainID > 10 then 57 | players[player].place = 'island' 58 | else 59 | players[player].place = 'town' 60 | end 61 | room.terrains[terrainID].guests[player] = false 62 | end -------------------------------------------------------------------------------- /source/places/hospital/_properties.lua: -------------------------------------------------------------------------------- 1 | room.hospital = {} 2 | 3 | for floor = 1, 9 do 4 | room.hospital[floor] = {} 5 | for bed = 1, 2 do 6 | room.hospital[floor][bed] = {name = nil} 7 | end 8 | end -------------------------------------------------------------------------------- /source/places/hospital/hospitalize.lua: -------------------------------------------------------------------------------- 1 | hospitalize = function(player) 2 | setNightMode(player, true) 3 | giveCoin(-600 * #players[player].hospital.diseases, player) 4 | if players[player].hospital.hospitalized then return end 5 | for i = 1, 4 do 6 | for x = 1, 2 do 7 | if not room.hospital[i][x].name then 8 | local pos = {100, 700} 9 | room.hospital[i][x].name = player 10 | players[player].hospital.hospitalized = true 11 | players[player].hospital.currentFloor = i 12 | freezePlayer(player, true, false) 13 | movePlayer(player, ((i-1)%i)*900+4000+pos[x], 3200, false) 14 | players[player].timer = addTimer(function(j) local time = 60 - j 15 | if time > 0 then 16 | showTextArea(98900000000, "

"..translate('healing', player):format(time), player, 250, 345, 290, 20, 0x1, 0x1, 0, true) 17 | else 18 | for i, v in next, players[player].hospital.diseases do 19 | setLifeStat(player, v, 60) 20 | end 21 | players[player].hospital.diseases = {} 22 | players[player].hospital.hospitalized = false 23 | freezePlayer(player, false) 24 | savedata(player) 25 | room.hospital[i][x].name = nil 26 | 27 | removeTextArea(98900000000, player) 28 | 29 | if x == 1 then 30 | showTextArea(8888805, '', nil, ((i-1)%i)*900+3+4000, 4+3000, 287, 249, 0x1, 0x1, 0.5) 31 | else 32 | showTextArea(8888806, '', nil, ((i-1)%i)*900+510+4000, 4+3000, 287, 249, 0x1, 0x1, 0.5) 33 | end 34 | end 35 | end, 1000, 60) 36 | removeTextArea(8888804+x) 37 | return 38 | end 39 | end 40 | end 41 | end -------------------------------------------------------------------------------- /source/places/hospital/loadFloor.lua: -------------------------------------------------------------------------------- 1 | loadHospitalFloor = function(player) 2 | local playerInfos = players[player] 3 | local currentFloor = playerInfos.hospital.currentFloor 4 | showTextArea(8888800, '

'..currentFloor, player, ((currentFloor-1)%currentFloor)*900+348+4000, 54+3000, 100, nil, 0x1, 0x1, 0) 5 | showTextArea(8888801, '', player, ((currentFloor-1)%currentFloor)*900+804+4000, -300+3000, 1000, 1000, 0x1, 0x1, 1) 6 | showTextArea(8888802, '', player, ((currentFloor-1)%currentFloor)*900-1004+4000, -300+3000, 1000, 1000, 0x1, 0x1, 1) 7 | 8 | showTextArea(8888803, '

01', player, ((currentFloor-1)%currentFloor)*900+325+4000, 102+3000, 53, nil, 0x1, 0x1, 0) 9 | showTextArea(8888804, '

01', player, ((currentFloor-1)%currentFloor)*900+415+4000, 102+3000, 53, nil, 0x1, 0x1, 0) 10 | showTextArea(8888808, "" .. string.rep('\n', 5), player, ((currentFloor-1)%currentFloor)*900+388+4000, 188+3000, 20, 30, 1, 1, 0) 11 | 12 | if not playerInfos.hospital.hospitalized then 13 | movePlayer(player, ((currentFloor-1)%currentFloor)*900+4400, 3240, false) 14 | end 15 | 16 | if not room.hospital[currentFloor][1].name then 17 | showTextArea(8888805, '', player, ((currentFloor-1)%currentFloor)*900+3+4000, 4+3000, 287, 249, 0x1, 0x1, 0.5) 18 | end 19 | if not room.hospital[currentFloor][2].name then 20 | showTextArea(8888806, '', player, ((currentFloor-1)%currentFloor)*900+510+4000, 4+3000, 287, 249, 0x1, 0x1, 0.5) 21 | end 22 | end 23 | 24 | loadHospital = function(player, elevador) 25 | players[player].place = 'hospital' 26 | 27 | local currentFloor = 1 28 | showTextArea(8888800, '

P', player, ((currentFloor-1)%currentFloor)*900+348+4000, 54+3400, 100, nil, 0x1, 0x1, 0) 29 | showTextArea(8888801, '', player, ((currentFloor-1)%currentFloor)*900+804+4000, -300+3400, 1000, 1000, 0x1, 0x1, 1) 30 | showTextArea(8888802, '', player, ((currentFloor-1)%currentFloor)*900-1004+4000, -300+3400, 1000, 1000, 0x1, 0x1, 1) 31 | 32 | showTextArea(8888803, '

01', player, ((currentFloor-1)%currentFloor)*900+325+4000, 102+3400, 53, nil, 0x1, 0x1, 0) 33 | showTextArea(8888804, '

01', player, ((currentFloor-1)%currentFloor)*900+415+4000, 102+3400, 53, nil, 0x1, 0x1, 0) 34 | showTextArea(8888807, "" .. string.rep('\n', 5), player, ((currentFloor-1)%currentFloor)*900+388+4000, 188+3400, 20, 30, 1, 1, 0) 35 | 36 | if not players[player].hospital.hospitalized and not elevador and not players[player].robbery.robbing then 37 | movePlayer(player, 4600, 3650, false) 38 | end 39 | if elevador then 40 | movePlayer(player, 4400, 3640, false) 41 | end 42 | end -------------------------------------------------------------------------------- /source/places/mine/_perlin.lua: -------------------------------------------------------------------------------- 1 | local perlin = {} 2 | do 3 | --[[ 4 | Implemented as described here: 5 | http://flafla2.github.io/2014/08/09/perlinnoise.html 6 | ]]-- 7 | perlin.p = {} 8 | 9 | -- Hash lookup table as defined by Ken Perlin 10 | -- This is a randomly arranged array of all numbers from 0-255 inclusive 11 | local permutation = {151,160,137,91,90,15, 12 | 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 13 | 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 14 | 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 15 | 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 16 | 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 17 | 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 18 | 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 19 | 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 20 | 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 21 | 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 22 | 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 23 | 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 24 | } 25 | 26 | -- p is used to hash unit cube coordinates to [0, 255] 27 | for i=0,255 do 28 | -- Convert to 0 based index table 29 | perlin.p[i] = permutation[i+1] 30 | -- Repeat the array to avoid buffer overflow in hash function 31 | perlin.p[i+256] = permutation[i+1] 32 | end 33 | 34 | -- Return range: [-1, 1] 35 | function perlin:noise(x, y, z) 36 | y = y or 0 37 | z = z or 0 38 | 39 | -- Calculate the "unit cube" that the point asked will be located in 40 | local xi = bit32.band(floor(x),255) 41 | local yi = bit32.band(floor(y),255) 42 | local zi = bit32.band(floor(z),255) 43 | 44 | -- Next we calculate the location (from 0 to 1) in that cube 45 | x = x - floor(x) 46 | y = y - floor(y) 47 | z = z - floor(z) 48 | 49 | -- We also fade the location to smooth the result 50 | local u = self.fade(x) 51 | local v = self.fade(y) 52 | local w = self.fade(z) 53 | 54 | -- Hash all 8 unit cube coordinates surrounding input coordinate 55 | local p = self.p 56 | local A, AA, AB, AAA, ABA, AAB, ABB, B, BA, BB, BAA, BBA, BAB, BBB 57 | A = p[xi ] + yi 58 | AA = p[A ] + zi 59 | AB = p[A+1 ] + zi 60 | AAA = p[ AA ] 61 | ABA = p[ AB ] 62 | AAB = p[ AA+1 ] 63 | ABB = p[ AB+1 ] 64 | 65 | B = p[xi+1] + yi 66 | BA = p[B ] + zi 67 | BB = p[B+1 ] + zi 68 | BAA = p[ BA ] 69 | BBA = p[ BB ] 70 | BAB = p[ BA+1 ] 71 | BBB = p[ BB+1 ] 72 | 73 | -- Take the weighted average between all 8 unit cube coordinates 74 | return self.lerp(w, 75 | self.lerp(v, 76 | self.lerp(u, 77 | self:grad(AAA,x,y,z), 78 | self:grad(BAA,x-1,y,z) 79 | ), 80 | self.lerp(u, 81 | self:grad(ABA,x,y-1,z), 82 | self:grad(BBA,x-1,y-1,z) 83 | ) 84 | ), 85 | self.lerp(v, 86 | self.lerp(u, 87 | self:grad(AAB,x,y,z-1), self:grad(BAB,x-1,y,z-1) 88 | ), 89 | self.lerp(u, 90 | self:grad(ABB,x,y-1,z-1), self:grad(BBB,x-1,y-1,z-1) 91 | ) 92 | ) 93 | ) 94 | end 95 | 96 | -- Gradient function finds dot product between pseudorandom gradient vector 97 | -- and the vector from input coordinate to a unit cube vertex 98 | perlin.dot_product = { 99 | [0x0]=function(x,y,z) return x + y end, 100 | [0x1]=function(x,y,z) return -x + y end, 101 | [0x2]=function(x,y,z) return x - y end, 102 | [0x3]=function(x,y,z) return -x - y end, 103 | [0x4]=function(x,y,z) return x + z end, 104 | [0x5]=function(x,y,z) return -x + z end, 105 | [0x6]=function(x,y,z) return x - z end, 106 | [0x7]=function(x,y,z) return -x - z end, 107 | [0x8]=function(x,y,z) return y + z end, 108 | [0x9]=function(x,y,z) return -y + z end, 109 | [0xA]=function(x,y,z) return y - z end, 110 | [0xB]=function(x,y,z) return -y - z end, 111 | [0xC]=function(x,y,z) return y + x end, 112 | [0xD]=function(x,y,z) return -y + z end, 113 | [0xE]=function(x,y,z) return y - x end, 114 | [0xF]=function(x,y,z) return -y - z end 115 | } 116 | function perlin:grad(hash, x, y, z) 117 | return self.dot_product[bit32.band(hash,0xF)](x,y,z) 118 | end 119 | 120 | -- Fade function is used to smooth final output 121 | function perlin.fade(t) 122 | return t * t * t * (t * (t * 6 - 15) + 10) 123 | end 124 | 125 | function perlin.lerp(t, a, b) 126 | return a + t * (b - a) 127 | end 128 | end -------------------------------------------------------------------------------- /source/places/mine/_properties.lua: -------------------------------------------------------------------------------- 1 | Mine = { 2 | position = {4536, 8643}, 3 | area = {10, 60}, 4 | availableRocks = {}, 5 | blocks = {}, 6 | blockLength = 60, 7 | ores = { 8 | yellow = { 9 | img = '1722e1e84dc.png', 10 | rarity = 12, 11 | }, 12 | blue = { 13 | img = '1722e1eccc0.png', 14 | rarity = 7, 15 | }, 16 | purple = { 17 | img = '1722e1e56b7.png', 18 | rarity = 4, 19 | }, 20 | green = { 21 | img = '1722e1eab1c.png', 22 | rarity = 3, 23 | }, 24 | red = { 25 | img = '1722e1e3389.png', 26 | rarity = 2, 27 | }, 28 | }, 29 | stones = { 30 | { 31 | name = 'sand', 32 | health = 2, 33 | ground = 7, 34 | image = '171fa7a17c1.png', 35 | }, 36 | { 37 | name = 'dirt', 38 | health = 5, 39 | ground = 5, 40 | image = '171fa80941f.jpg', 41 | }, 42 | { 43 | name = 'coal', 44 | health = 20, 45 | ground = 4, 46 | image = '1721aa68210.png', 47 | ores = {'yellow', 'blue'}, 48 | }, 49 | { 50 | name = 'stone', 51 | health = 50, 52 | ground = 10, 53 | image = '171fa7cdbc2.png', 54 | ores = {'yellow', 'blue', 'purple'}, 55 | }, 56 | { 57 | name = 'lava', 58 | health = 200, 59 | ground = 3, 60 | image = '171fa832ec8.png', 61 | ores = {'yellow', 'blue', 'purple', 'green'}, 62 | }, 63 | { 64 | name = 'diamont', 65 | health = 500, 66 | ground = 1, 67 | image = '171fa8b16dd.jpg', 68 | ores = {'yellow', 'blue', 'purple', 'green', 'red'}, 69 | }, 70 | { 71 | name = 'tiplonium', 72 | health = 1000, 73 | ground = 11, 74 | image = '1722e396406.png', 75 | ores = {'yellow', 'blue', 'purple', 'green', 'red'}, 76 | }, 77 | { 78 | name = 'chernobyl', 79 | health = 2000, 80 | ground = 11, 81 | image = '1722e4b0bfb.png', 82 | ores = {'yellow', 'blue', 'purple', 'green', 'red'}, 83 | }, 84 | { 85 | name = 'chernobyl2', 86 | health = 5000, 87 | ground = 15, 88 | image = '1722e5fe753.png', 89 | ores = {'yellow', 'blue', 'purple', 'green', 'red'}, 90 | }, 91 | }, 92 | } -------------------------------------------------------------------------------- /source/playerData/_dataStructure.lua: -------------------------------------------------------------------------------- 1 | local playerData = DataHandler.new('myc', { 2 | coins = { 3 | index = 1, 4 | type = 'number', 5 | default = function() 6 | return 0 7 | end 8 | }, 9 | lifeStats = { 10 | index = 2, 11 | type = 'table', 12 | default = function() 13 | return { 14 | 100, 15 | 100 16 | } 17 | end 18 | }, 19 | houses = { 20 | index = 3, 21 | type = 'table', 22 | default = function() 23 | return {} 24 | end 25 | }, 26 | cars = { 27 | index = 4, 28 | type = 'table', 29 | default = function() 30 | return {} 31 | end 32 | }, 33 | quests = { 34 | index = 5, 35 | type = 'table', 36 | default = function() 37 | return { 38 | 1, 39 | 0 40 | } 41 | end 42 | }, 43 | bagItem = { 44 | index = 6, 45 | type = 'table', 46 | default = function() 47 | return {} 48 | end 49 | }, 50 | bagQuant = { 51 | index = 7, 52 | type = 'table', 53 | default = function() 54 | return {} 55 | end 56 | }, 57 | spentCoins = { 58 | index = 8, 59 | type = 'number', 60 | default = function() 61 | return 0 62 | end 63 | }, 64 | codes = { 65 | index = 9, 66 | type = 'table', 67 | default = function() 68 | return {} 69 | end 70 | }, 71 | housesTerrains = { 72 | index = 10, 73 | type = 'table', 74 | default = function() 75 | return {0, 0, 0, 0, 0} 76 | end 77 | }, 78 | housesTerrainsAdd = { 79 | index = 11, 80 | type = 'table', 81 | default = function() 82 | return {1, 1, 1, 1, 1} 83 | end 84 | }, 85 | housesTerrainsPlants = { 86 | index = 12, 87 | type = 'table', 88 | default = function() 89 | return {0, 0, 0, 0, 0} 90 | end 91 | }, 92 | bagStorage = { 93 | index = 13, 94 | type = 'number', 95 | default = function() 96 | return 20 97 | end 98 | }, 99 | houseSaves = { 100 | index = 14, 101 | type = 'table', 102 | default = function() 103 | return {} 104 | end 105 | }, 106 | storedFurnitures = { 107 | index = 15, 108 | type = 'table', 109 | default = function() 110 | return {} 111 | end 112 | }, 113 | chestStorage = { 114 | index = 16, 115 | type = 'table', 116 | default = function() 117 | return {{}, {}, {}, {}} 118 | end 119 | }, 120 | chestStorageQuanty = { 121 | index = 17, 122 | type = 'table', 123 | default = function() 124 | return {{}, {}, {}, {}} 125 | end 126 | }, 127 | sideQuests = { 128 | index = 18, 129 | type = 'table', 130 | default = function() 131 | return {1, 0, 0, 0, 0, 0} 132 | end 133 | }, 134 | level = { 135 | index = 19, 136 | type = 'table', 137 | default = function() 138 | return {1, 0} 139 | end 140 | }, 141 | jobStats = { 142 | index = 20, 143 | type = 'table', 144 | default = function() 145 | return {} 146 | end 147 | }, 148 | badges = { 149 | index = 21, 150 | type = 'table', 151 | default = function() 152 | return {} 153 | end 154 | }, 155 | luckiness = { 156 | index = 22, 157 | type = 'table', 158 | default = function() 159 | return {{100, 0, 0, 0}, false} -- Fishing luckiness, isWhitelisted 160 | end 161 | }, 162 | playerLog = { 163 | index = 23, 164 | type = 'table', 165 | default = function() 166 | return {{mainAssets.season, 0}, {0, lang[ROOM.community] and langIDS[ROOM.community] or '0', 0, 0, 0, 0, 0}, {0, 0, 0}, {0, 0, 0}} -- Season Data| Player Settings| Current Version| Favorite Vehicles 167 | end 168 | }, 169 | starIcons = { 170 | index = 24, 171 | type = 'table', 172 | default = function() 173 | return { 174 | {1}, -- Star Icons 175 | 1, -- Selected Star Icon 176 | {1}, -- Level Icons 177 | 1 -- Selected Level Icon 178 | } 179 | end 180 | }, 181 | timePlayed = { 182 | index = 25, 183 | type = 'number', 184 | default = function() 185 | return 0 186 | end 187 | }, 188 | currentBagIcon = { 189 | index = 26, 190 | type = 'number', 191 | default = function() 192 | return 1 193 | end 194 | }, 195 | houseCopy = { 196 | index = 27, 197 | type = 'table', 198 | default = function() 199 | return {} 200 | end 201 | } 202 | }) 203 | 204 | local sharpieData = DataHandler.new('sync', { 205 | questDevelopmentStage = { 206 | index = 1, 207 | type = 'number', 208 | default = function() 209 | return 0 210 | end 211 | }, 212 | canUpdate = { 213 | index = 2, 214 | type = 'string', 215 | default = function() 216 | return '' 217 | end 218 | }, 219 | }) -------------------------------------------------------------------------------- /source/playerData/dataToLoad/storeFurniture.lua: -------------------------------------------------------------------------------- 1 | storeFurniture = function(name, furniture) 2 | local isTable = type(furniture) == 'table' 3 | if isTable then 4 | local furnitureID = furniture[1] 5 | local amount = furniture[2] 6 | players[name].houseData.furnitures.stored[furnitureID] = {quanty = amount, type = furnitureID} 7 | else 8 | if not players[name].houseData.furnitures.stored[furniture] then 9 | players[name].houseData.furnitures.stored[furniture] = {quanty = 1, type = furniture} 10 | else 11 | players[name].houseData.furnitures.stored[furniture].quanty = players[name].houseData.furnitures.stored[furniture].quanty + 1 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /source/quests/sidequest.lua: -------------------------------------------------------------------------------- 1 | sideQuest_update = function(player, value) 2 | players[player].sideQuests[2] = players[player].sideQuests[2] + value 3 | 4 | local currentAmount = players[player].sideQuests[2] 5 | local requiredAmount = players[player].sideQuests[7] or sideQuests[players[player].sideQuests[1]].amount 6 | 7 | if type(requiredAmount) == "table" then 8 | requiredAmount = requiredAmount[1] 9 | end 10 | 11 | if currentAmount >= requiredAmount then 12 | sideQuest_reward(player) 13 | end 14 | end 15 | 16 | sideQuest_sendTrigger = function(player, triggerName, value, extraData) 17 | local playerData = players[player] 18 | local sidequest = sideQuests[playerData.sideQuests[1]].type 19 | 20 | if string_find(sidequest, triggerName) then 21 | if playerData.sideQuests[8] then 22 | if not extraData then return end 23 | if extraData:lower() ~= playerData.sideQuests[8]:lower() then return end 24 | end 25 | sideQuest_update(player, value) 26 | end 27 | end 28 | 29 | sideQuest_reward = function(player) 30 | local currentSideQuest = players[player].sideQuests[1] 31 | local hasNewDataFormat = players[player].sideQuests[7] 32 | local diamonds = sideQuests[currentSideQuest].points 33 | 34 | if hasNewDataFormat then 35 | local id = table_find(sideQuests[currentSideQuest].amount, hasNewDataFormat) or 1 36 | diamonds = sideQuests[currentSideQuest].points[id] 37 | end 38 | 39 | if type(diamonds) == "table" then 40 | diamonds = 5 41 | end 42 | 43 | giveDiamond(diamonds, player) 44 | 45 | local newxp = diamonds * 100 46 | modernUI.new(player, 240, 220) 47 | :rewardInterface({ 48 | {text = translate('experiencePoints', player), quanty = newxp, format = '+'}, 49 | {currency = 'diamond', quanty = diamonds}, 50 | }, nil, translate('sidequestCompleted', player)) 51 | :build() 52 | :addConfirmButton(function() end, translate('confirmButton_Great', player)) 53 | 54 | sideQuest_new(player) 55 | players[player].sideQuests[3] = players[player].sideQuests[3] + 1 56 | giveExperiencePoints(player, newxp) 57 | end 58 | 59 | sideQuest_checkAlias = function(nextQuest, currentQuest) 60 | if nextQuest == currentQuest or nextQuest == 8 then 61 | return false 62 | elseif sideQuests[currentQuest].alias then 63 | if sideQuests[currentQuest].alias ~= nextQuest then 64 | if sideQuests[nextQuest].alias and sideQuests[nextQuest].alias == sideQuests[currentQuest].alias then 65 | return false 66 | else 67 | return true 68 | end 69 | end 70 | elseif sideQuests[nextQuest].alias then 71 | if sideQuests[nextQuest].alias ~= currentQuest then 72 | return true 73 | end 74 | else 75 | return true 76 | end 77 | return false 78 | end 79 | 80 | sideQuest_new = function(player, specificQuest) 81 | local nextQuest = specificQuest 82 | if not specificQuest then 83 | local currentQuestType = sideQuests[players[player].sideQuests[1]].alias or players[player].sideQuests[1] 84 | while true do 85 | nextQuest = random(#sideQuests) 86 | if players[player].sideQuests[5] == floor(os_time() / (24*60*60*1000)) then 87 | if nextQuest ~= currentQuestType then 88 | if sideQuest_checkAlias(nextQuest, players[player].sideQuests[6]) then 89 | break 90 | end 91 | end 92 | else 93 | if nextQuest ~= currentQuestType then 94 | if sideQuest_checkAlias(nextQuest, currentQuestType) then 95 | break 96 | end 97 | end 98 | end 99 | end 100 | end 101 | 102 | players[player].sideQuests[1] = nextQuest 103 | players[player].sideQuests[2] = 0 104 | players[player].sideQuests[7] = type(sideQuests[nextQuest].amount) == "table" and sideQuests[nextQuest].amount[random(#sideQuests[nextQuest].amount)] or nil 105 | players[player].sideQuests[8] = sideQuests[nextQuest].extraData and sideQuests[nextQuest].extraData() or nil 106 | 107 | savedata(player) 108 | end -------------------------------------------------------------------------------- /source/ranking/load.lua: -------------------------------------------------------------------------------- 1 | loadRanking = function(player) 2 | if not mainAssets.isRankingActive then return end 3 | 4 | local minn = 1 5 | local maxx = 10 6 | 7 | local playerList = {} 8 | local playerLevel = {{}, {}} 9 | local playerExperience = {{}, {}} 10 | 11 | local color = '' 12 | local xAlign = 3710 13 | local yAlign = 7480 14 | 15 | for i = minn, maxx do 16 | if not room.globalRanking[i] then break end 17 | local name = room.globalRanking[i].name 18 | local level = room.globalRanking[i].level 19 | local gifts = room.globalRanking[i].gifts 20 | local commu = room.globalRanking[i].commu 21 | if not room.globalRanking[i].commu then 22 | room.globalRanking[i].commu = 'xx' 23 | end 24 | if i == 1 then 25 | color = '#FFD700' 26 | elseif i == 2 then 27 | color = '#c9c9c9' 28 | elseif i == 3 then 29 | color = '#A0522D' 30 | else 31 | color = '#BEBEBE' 32 | end 33 | 34 | playerList[#playerList+1] = ''..i..'. ' .. name 35 | --playerLevel[2][#playerLevel[2]+1] = '

'.. level 36 | --playerLevel[1][#playerLevel[1]+1] = '

'.. level 37 | 38 | playerExperience[2][#playerExperience[2]+1] = '

'.. gifts 39 | playerExperience[1][#playerExperience[1]+1] = '

'.. gifts 40 | 41 | room.rankingImages[#room.rankingImages+1] = addImage('1711870c79c.jpg', '?1000', 95 + xAlign, (i-1)*12+102 + yAlign, player) 42 | room.rankingImages[#room.rankingImages+1] = addImage((community[commu] and community[commu] or community['xx']), '?1001', 109 + xAlign, (i-1)*12+101 + yAlign, player) 43 | room.rankingImages[#room.rankingImages+1] = addImage('173f47ce384.png', '?1002', 97 + xAlign, (i-1)*12+103 + yAlign, player) 44 | playerFinder.checkIfIsOnline(name, 45 | function() 46 | room.rankingImages[#room.rankingImages+1] = addImage('173f47cffe1.png', '?1002', 97 + xAlign, (i-1)*12+103 + yAlign, player) 47 | end 48 | ) 49 | end 50 | if not room.globalRanking[1] then 51 | playerList[#playerList+1] = '\n\nConnecting...' 52 | end 53 | 54 | showTextArea(5432, table_concat(playerList, '\n'), player, 128 + xAlign, 100 + yAlign, 180, 130, 0x324650, 0x0, 0) 55 | showTextArea(5433, table_concat(playerLevel[1], '\n'), player, 276+10+ xAlign, 101 + yAlign, 40, 130, 0x324650, 0x0, 0) 56 | showTextArea(5434, table_concat(playerLevel[2], '\n'), player, 275+10+ xAlign, 100 + yAlign, 40, 130, 0x324650, 0x0, 0) 57 | 58 | showTextArea(5435, table_concat(playerExperience[1], '\n'), player, 276+65+ xAlign, 101 + yAlign, 70, 130, 0x324650, 0x0, 0) 59 | showTextArea(5436, table_concat(playerExperience[2], '\n'), player, 275+65+ xAlign, 100 + yAlign, 70, 130, 0x324650, 0x0, 0) 60 | 61 | if player then 62 | showTextArea(5440, '

'..translate('ranking_Christmas2021', player), player, 94+ xAlign, 55+ yAlign, 400, nil, 0x324650, 0x0, 0) 63 | showTextArea(5441, '

'..translate('ranking_Christmas2021', player), player, 93+ xAlign, 54+ yAlign, 400, nil, 0x324650, 0x0, 0) 64 | 65 | showTextArea(5442, '

'..translate('daysLeft', player):format(formatDaysRemaining(os_time{day=14, year=2022, month=1})), player, 93+ xAlign, 84+ yAlign, 400, nil, 0x324650, 0x0, 0) 66 | end 67 | end -------------------------------------------------------------------------------- /source/ranking/save.lua: -------------------------------------------------------------------------------- 1 | saveRanking = function() 2 | if not mainAssets.isRankingActive then return end 3 | 4 | if ROOM.name:sub(1,2) == "*" then 5 | return 6 | elseif ROOM.uniquePlayers < room.requiredPlayers then 7 | return 8 | end 9 | local newRanking = {} 10 | local localRanking = table_copy(room.globalRanking) 11 | 12 | for i = #localRanking, 1, -1 do 13 | local name = localRanking[i].name 14 | if players[name] and players[name].inRoom and players[name].dataLoaded then 15 | table_remove(localRanking, i) 16 | end 17 | end 18 | 19 | for name in next, ROOM.playerList do 20 | local player = players[name] 21 | if player and player.inRoom and player.dataLoaded and player.level[1] >= 10 then 22 | if not table_find(room.unranked, name) then 23 | localRanking[#localRanking+1] = {name = name, level = player.level[1], gifts = player.jobs[21], commu = player.lang, id = ROOM.playerList[name].id} 24 | end 25 | end 26 | end 27 | table_sort(localRanking, function(a, b) return tonumber(a.gifts) > tonumber(b.gifts) end) 28 | 29 | if #localRanking > 20 then 30 | local len = #localRanking 31 | for i = len, 21, -1 do 32 | table_remove(localRanking, i) 33 | end 34 | end 35 | 36 | for _, player in next, localRanking do 37 | newRanking[#newRanking+1] = string.format('%s,%i,%i,%s,%i', player.name, player.level, player.gifts, player.commu, player.id) 38 | end 39 | 40 | saveFile(table_concat(newRanking, ';')..'|', 30) 41 | end -------------------------------------------------------------------------------- /source/recipeSystem.lua: -------------------------------------------------------------------------------- 1 | newFoodValue = function(recipe) 2 | local newValue = 0 3 | local ingredients = 0 4 | local spiceList = { 5 | pepper = 0.12, 6 | } 7 | 8 | for i, v in next, recipes[recipe].require do 9 | local item = bagItems[i] 10 | if not item.hunger then 11 | item.hunger = (not recipes[i] and 0.11 or floor(newFoodValue(i))) 12 | end 13 | newValue = newValue + (item.hunger >= 0 and item.hunger or ((i:find('fish') or i:find('meat')) and abs(item.hunger)/1.62 or spiceList[i] and spiceList[i] or 0.57)) * v 14 | ingredients = ingredients + 1 15 | end 16 | bagItems[recipe].hunger = floor((ingredients/1.025) * newValue) 17 | return bagItems[recipe].hunger 18 | end 19 | 20 | newEnergyValue = function(recipe) 21 | local recipeHunger = bagItems[recipe].hunger 22 | local newValue = 0 23 | local ingredients = 0 24 | local spiceList = { 25 | pepper = 1.49, 26 | oregano = 1.09, 27 | lemon = 1.11, 28 | salt = 1.32, 29 | tomato = 1.32, 30 | garlic = 1.42, 31 | } 32 | 33 | for i, v in next, recipes[recipe].require do 34 | local item = bagItems[i] 35 | if not item.power then 36 | item.power = (not recipes[i] and 1.03 or floor(newEnergyValue(i))) 37 | end 38 | newValue = newValue + ((item.power >= 0 and not spiceList[i]) and item.power*1.1 or ((i:find('fish') or i:find('meat')) and abs(item.power)/2.12 or spiceList[i] and spiceList[i] or 0.30)) * v 39 | ingredients = ingredients + 1 40 | end 41 | bagItems[recipe].power = floor((ingredients/0.971) * newValue/2) 42 | return bagItems[recipe].power 43 | end 44 | 45 | newDishPrice = function(recipe) 46 | local price = 100 47 | for i, v in next, recipes[recipe].require do 48 | local item = bagItems[i] 49 | if item.price then 50 | price = price + item.price 51 | else 52 | price = price + 10 53 | end 54 | end 55 | bagItems[recipe].sellingPrice = floor(price + price/4) 56 | return bagItems[recipe].sellingPrice 57 | end -------------------------------------------------------------------------------- /source/social/addLootDrop.lua: -------------------------------------------------------------------------------- 1 | addLootDrop = function(x, y, wind) 2 | for i = 1, 51 do 3 | TFM.removeObject(TFM.addShamanObject(1, -500, 2800)) 4 | end 5 | local fallingSpeed = 5 6 | local id = 1 7 | addGround(id..'44444444', x, y-14, {type = 14, width = 80, friction = 9999, dynamic = true, fixedRotation = true, miceCollision = false, linearDamping = fallingSpeed}) 8 | addGround(id..'44444445', x+29, y-50, {type = 14, height = 62, width = 25, dynamic = true, friction = 0.3, fixedRotation = true, linearDamping = fallingSpeed}) 9 | addGround(id..'44444446', x-29, y-50, {type = 14, height = 62, width = 25, dynamic = true, friction = 0.3, fixedRotation = true, linearDamping = fallingSpeed}) 10 | addGround(id..'44444447', x, y-69, {type = 14, height = 23, width = 32, dynamic = true, friction = 0.3, fixedRotation = true, linearDamping = fallingSpeed}) 11 | 12 | 13 | addGround(id..'44444450', x-40, y+40, {type = 14, width = 2000, restitution = 1, angle = 90- wind*.5, miceCollision = false}) 14 | addGround(id..'44444451', x-160, y+40, {type = 14, width = 2000, restitution = 1, angle = 90- wind*.5, miceCollision = false}) 15 | addGround(id..'44444452', x-120, y-14, {type = 14, width = 80, friction = 9999, dynamic = true, fixedRotation = true, miceCollision = false, linearDamping = fallingSpeed*1.35}) 16 | 17 | TFM.addJoint(id..'1', id..'44444444', id..'44444445', {type = 3}) 18 | TFM.addJoint(id..'2', id..'44444446', id..'44444447', {type = 3}) 19 | TFM.addJoint(id..'3', id..'44444444', id..'44444446', {type = 3}) 20 | 21 | id = id + 1 22 | local box = TFM.addShamanObject(6300, x, y-20) 23 | local lootImage = addImage('171ebdaa31b.png', '#'..box, -40 -110, -127 -145) 24 | 25 | local auxiliarBox = TFM.addShamanObject(6300, x-120, y-20) 26 | 27 | local lastPos = {} 28 | local checkExplosion 29 | checkExplosion = addTimer(function() 30 | for i, v in next, tfm.get.room.objectList do 31 | if i == auxiliarBox then 32 | if lastPos[1] == v.x and lastPos[2] == v.y and v.y > 7490 then 33 | for i = 1, 10 do 34 | TFM.displayParticle(10, v.x+50+random(0, 150), v.y-250+random(0, 170)) 35 | TFM.displayParticle(3, v.x+80+random(0, 75), v.y+23) 36 | end 37 | local objs = {} 38 | local images = {'171ec448e1c.png', '171ec446276.png', '171ec443e74.png', '171ec4424c1.png'} 39 | for i = 1, 15 do 40 | objs[#objs+1] = TFM.addShamanObject(95, v.x+20+random(0, 150), v.y-250+random(0, 80), random(0, 50), random(-10, 10)) 41 | addImage(images[random(#images)], '#'..objs[#objs], 0, 0) 42 | end 43 | addTimer(function() 44 | for i = 1, #objs do 45 | TFM.removeObject(objs[i]) 46 | end 47 | end, 1000, 1) 48 | removeImage(lootImage) 49 | lootImage = addImage('171eb5f183b.png', '#'..box, -45, -122) 50 | removeTimer(checkExplosion) 51 | end 52 | lastPos[1] = v.x 53 | lastPos[2] = v.y 54 | end 55 | end 56 | end, 500, 0) 57 | end -------------------------------------------------------------------------------- /source/social/freezePlayer.lua: -------------------------------------------------------------------------------- 1 | freezePlayer = function(player, freeze, displayIce) 2 | TFM.freezePlayer(player, freeze, displayIce) 3 | if not players[player] then return end 4 | players[player].isFrozen = freeze 5 | end -------------------------------------------------------------------------------- /source/social/setNightMode.lua: -------------------------------------------------------------------------------- 1 | setNightMode = function(name, remove) 2 | if not players[name].isBlind and remove then return end 3 | 4 | setPlayerNightMode(name, not remove) 5 | players[name].isBlind = not remove 6 | end -------------------------------------------------------------------------------- /source/social/showPlayerLevel.lua: -------------------------------------------------------------------------------- 1 | generateLevelImage = function(player, level, requested) 2 | if player == requested then 3 | setPlayerScore(player, level) 4 | end 5 | local level = tostring(level) 6 | local iconImage = mainAssets.levelIcons.lvl -- change to player current star icon 7 | local playerImage = players[requested].playerNameIcons.level 8 | if not playerImage[player] then 9 | playerImage[player] = {} 10 | else 11 | for i = 1, #playerImage[player] do 12 | removeImage(playerImage[player][i]) 13 | end 14 | playerImage[player] = {} 15 | end 16 | playerImage[player][#playerImage[player]+1] = addImage(mainAssets.levelIcons.star[players[player].starIcons.selected], "$"..player, -32, requested ~= player and -107 or -117, requested) 17 | for i = 1, #level do 18 | local id = tonumber(level:sub(i, i))+1 19 | playerImage[player][#playerImage[player]+1] = addImage(iconImage[id][1], "$"..player, (i-1)*8 - (#level*8)/2 -5, requested ~= player and -69 or -79, requested) 20 | end 21 | end -------------------------------------------------------------------------------- /source/sounds/soundList.lua: -------------------------------------------------------------------------------- 1 | sounds = { 2 | buttonClick = "cite18/bouton2.mp3" 3 | } -------------------------------------------------------------------------------- /source/specialBackgrounds.lua: -------------------------------------------------------------------------------- 1 | room.specialBackgrounds = { 2 | christmas2019 = { 3 | evening = '16ee11c6a13.jpg', 4 | dawn = '16ee11d3516.jpg', 5 | night = '16ee11b36c4.jpg', 6 | day = '16ee11b1f00.png', 7 | align = 1919, 8 | }, 9 | halloween2019 = { 10 | evening = '16dd5d7c4e1.jpg', 11 | dawn = '16dd5d78f0d.jpg', 12 | night = '16dd5d7ad6f.jpg', 13 | day = '16dd5d7738e.jpg', 14 | align = 1919, 15 | }, 16 | halloween2020 = { 17 | evening = '1752efbedd0.jpg', 18 | dawn = '174f9c1ecf5.jpg', 19 | night = '174f9c1ecf5.jpg', 20 | day = '1752efbedd0.jpg', 21 | align = 1373, 22 | }, 23 | christmas2020 = { 24 | evening = '17690bea277.jpg', 25 | dawn = '176708fb915.jpg', 26 | night = '1767090e36c.jpg', 27 | day = '1767089b19c.jpg', 28 | forSaleSign = '1767190d05d.png', 29 | align = 1919, 30 | }, 31 | christmas2021 = { 32 | evening = '17690bea277.jpg', 33 | dawn = '176708fb915.jpg', 34 | night = '1767090e36c.jpg', 35 | day = '1767089b19c.jpg', 36 | forSaleSign = '1767190d05d.png', 37 | uiBackground = { 38 | dawn = '#C2CDF2', 39 | day = '#95D2F4', 40 | evening = '#EEF8CC', 41 | night = '#889697', 42 | }, 43 | align = 1919, 44 | }, 45 | } -------------------------------------------------------------------------------- /source/tips.lua: -------------------------------------------------------------------------------- 1 | local tips = { 2 | br = {'Você consegue ir e voltar a pé pelo no mapa até 14 vezes em 1 hora!','O jogo começa quando estiverem presentes no mínimo 4 pessoas na sala com IPs diferentes.', 'A planta mais rara do jogo é a Flor-da-sorte!', 'Existem '..#bagIds..' itens no jogo!', 'Você pode plantar na horta de Oliver!', 'Digite !perfil [jogador] para ver perfis de diferentes jogadores!', 'Existem '..#sideQuests..' missões secundárias disponíveis!', 'Você sabia? #mycity foi criado em 2014!', 'Você sabia? A comunidade brasileira é a que mais joga #mycity!'}, 3 | en = {'There are '..#bagIds..' items in the game!', 'The rarest plant is the lucky flower!', 'You can plant in Oliver\'s house.', 'Type !profile [playerName] to see profiles from different players!', 'There are '..#sideQuests..' side quests available!'}, 4 | hu = {#bagIds..' tárgy van a játékban!', 'A legértékesebb növény a Szerencsevirág!', 'Tudsz ültetni Oliver házába.', 'Írd be a !profile [játékosNév] parancsot, hogy lásd mások profilját!', 'Jelenleg '..#sideQuests..' mellékküldetés érhető el!'}, 5 | } -------------------------------------------------------------------------------- /source/translations/_langIDS.lua: -------------------------------------------------------------------------------- 1 | local lang = {} 2 | local langIDS = { 3 | [0] = 'en', 4 | [1] = 'br', 5 | [2] = 'fr', 6 | [3] = 'es', 7 | [4] = 'hu', 8 | [5] = 'de', 9 | [6] = 'pl', 10 | [7] = 'ar', 11 | [8] = 'tr', 12 | [9] = 'ru', 13 | [10] = 'he', 14 | [11] = 'id', 15 | [12] = 'pt', 16 | } -------------------------------------------------------------------------------- /source/translations/_merge.lua: -------------------------------------------------------------------------------- 1 | for k, v in next, lang do 2 | if k ~= "en" then 3 | table_merge(v, lang.en) 4 | end 5 | end -------------------------------------------------------------------------------- /source/translations/_translationSystem.lua: -------------------------------------------------------------------------------- 1 | translate = function(message, name) 2 | if not players[name] then return '?' end 3 | local cmm = players[name].lang or 'en' 4 | if message:sub(1, 3) == 'req' then 5 | local quest = tonumber(message:sub(5)) 6 | return lang[cmm].quests[quest].name 7 | end 8 | if message == '$VersionName' then 9 | local playerVersion = 'v'..table_concat(version, '.') 10 | return versionLogs[playerVersion][cmm] or versionLogs[playerVersion].en 11 | end 12 | return lang[cmm][message] and lang[cmm][message] or '$txt_'..message 13 | end 14 | 15 | translatedMessage = function(msg, ...) 16 | for name in next, ROOM.playerList do 17 | chatMessage(string.format(translate(msg, name), ...), name) 18 | end 19 | end -------------------------------------------------------------------------------- /source/translations/de.lua: -------------------------------------------------------------------------------- 1 | lang.de = { 2 | police = 'Polizei', 3 | sale = 'Zu Verkaufen', 4 | close = 'Zu machen', 5 | soon = 'In kurzer Zeit', 6 | house = 'Haus', 7 | yes = 'Ja', 8 | no = 'Nein', 9 | thief = 'Dieb', 10 | House1 = 'Klassisches Haus', 11 | House2 = 'Familien Haus', 12 | goTo = 'Reingehen', 13 | fisher = 'Fischer', 14 | furniture = 'Möbel', 15 | hospital = 'Krankenhaus', 16 | open = 'Öffnen', 17 | } -------------------------------------------------------------------------------- /source/vehicles/giveCar.lua: -------------------------------------------------------------------------------- 1 | giveCar = function(player, car) 2 | if not mainAssets.__cars[car] then return alert_Error(player, 'error', 'Unknown Vehicle') end 3 | if table_find(players[player].cars, car) then return end 4 | players[player].cars[#players[player].cars+1] = car 5 | modernUI.new(player, 240, 220, translate('newCar', player), translate('unlockedCar', player)) 6 | :build() 7 | :addConfirmButton(function() end, translate('confirmButton_Great', player)) 8 | players[player]._modernUISelectedItemImages[1][#players[player]._modernUISelectedItemImages[1]+1] = addImage(mainAssets.__cars[car].icon, "&70", 349, 180, player) 9 | 10 | savedata(player) 11 | end --------------------------------------------------------------------------------

'..npc.name:gsub('%$', ''), player, 275, 335 + (15-font), 90, 30, 1, 1, 0, true) 43 | showTextArea(-88001, '', player, 380, 260, 210, 75, 1, 1, 0, true) 44 | showTextArea(-88002, "" .. string.rep('\n', 10), player, 300, 250, 300, 100, nil, 1, 0, true) 45 | end -------------------------------------------------------------------------------- /source/npcs/gameNpcs/updateDialogBox.lua: -------------------------------------------------------------------------------- 1 | gameNpcs.updateDialogBox = function(id) 2 | local index = dialogs[id] 3 | if not index.text[index.currentPage] then return end 4 | local t = string.sub(index.text[index.currentPage], 1, index.length) 5 | local text = index.text 6 | ui.updateTextArea(-88001, ''..t, id) 7 | ui.updateTextArea(-88002, "" .. string.rep('\n', 10), id) 8 | if #t >= #text[index.currentPage] then 9 | index.running = false 10 | index.currentPage = index.currentPage + 1 11 | index.length = 0 12 | isQuest = index.isQuest and index.isQuest or 'not' 13 | ui.updateTextArea(-88002, "" .. string.rep('\n', 10), id) 14 | end 15 | end -------------------------------------------------------------------------------- /source/npcs/gameNpcs/updateDialogs.lua: -------------------------------------------------------------------------------- 1 | updateDialogs = function(counter) 2 | for npc, v in next, dialogs do 3 | if v.running then 4 | v.length = v.length + counter 5 | gameNpcs.updateDialogBox(npc) 6 | end 7 | end 8 | end -------------------------------------------------------------------------------- /source/npcs/npcDialogs.lua: -------------------------------------------------------------------------------- 1 | for commu, v in next, lang do 2 | for id, message in next, v do 3 | if id:find('npcDialog_') then 4 | if not npcDialogs.normal[commu] then npcDialogs.normal[commu] = {} end 5 | local npc = id:sub(11) 6 | local message = message 7 | local dialog = {} 8 | for text in message:gmatch('[^\n]+') do 9 | dialog[#dialog+1] = text 10 | end 11 | npcDialogs.normal[commu][npc] = dialog 12 | end 13 | end 14 | for questID, properties in next, v.quests do 15 | for questStep, stepData in next, properties do 16 | if tonumber(questStep) then 17 | if not npcDialogs.quests[commu] then npcDialogs.quests[commu] = {} end 18 | if not npcDialogs.quests[commu][questID] then npcDialogs.quests[commu][questID] = {} end 19 | if not npcDialogs.quests[commu][questID][questStep] then npcDialogs.quests[commu][questID][questStep] = {} end 20 | local message = {} 21 | if stepData.dialog then 22 | for msg in stepData.dialog:gmatch('[^\n]+') do 23 | message[#message+1] = msg 24 | end 25 | end 26 | npcDialogs.quests[commu][questID][questStep] = message 27 | end 28 | end 29 | end 30 | end -------------------------------------------------------------------------------- /source/npcs/shops/loadShop.lua: -------------------------------------------------------------------------------- 1 | showNPCShop = function(player, npc) 2 | npc = npc:lower() 3 | if not npcsStores.shops[npc] then return alert_Error(player, 'error', 'nonexistentShop') end 4 | modernUI.new(player, 520, 300) 5 | :build() 6 | :showNPCShop(npcsStores.shops[npc], npc) 7 | end 8 | 9 | buildNpcsShopItems = function() 10 | for npc in next, npcsStores.shops do 11 | local newFormat = {} 12 | for i, k in next, npcsStores.items do 13 | local v = type(k) == 'table' and k or bagItems[k] 14 | if v and (not v.limitedTime or not formatDaysRemaining(v.limitedTime, true)) then 15 | if npc ~= 'chrystian' then 16 | if v.npcShop and v.npcShop:find(npc) then 17 | newFormat[#newFormat+1] = {i, k} 18 | end 19 | else 20 | if not v.npcShop and not v.qpPrice and mainAssets.__furnitures[i] then 21 | newFormat[#newFormat+1] = {i, k} 22 | end 23 | end 24 | end 25 | if npc == 'all' then 26 | newFormat[#newFormat+1] = {i, k} 27 | end 28 | end 29 | npcsStores.shops[npc] = newFormat 30 | end 31 | end 32 | 33 | checkIfPlayerHasFurniture = function(player, furniture) 34 | for _, v in next, players[player].houseData.furnitures.placed[players[player].houseData.currentSaveSlot] do 35 | if v.type == furniture then 36 | return true 37 | end 38 | end 39 | for _, v in next, players[player].houseData.furnitures.stored do 40 | if v.type == furniture then 41 | return true 42 | end 43 | end 44 | return false 45 | end 46 | 47 | mergeItemsWithFurnitures = function(t1, t2) -- Merge bag items with furnitures 48 | local newTbl = table_copy(t1) 49 | for i, v in next, t2 do 50 | newTbl[i+1000] = v.n 51 | end 52 | return newTbl 53 | end -------------------------------------------------------------------------------- /source/places/_checkLocation/isInHouse.lua: -------------------------------------------------------------------------------- 1 | checkLocation_isInHouse = function(player) 2 | if not players[player] then return false end 3 | local id = tonumber(players[player].houseData.houseid) 4 | local house = tonumber(players[player].place:sub(7)) 5 | if id == house then 6 | return true 7 | end 8 | return false 9 | end -------------------------------------------------------------------------------- /source/places/_placesData.lua: -------------------------------------------------------------------------------- 1 | places = { 2 | market = { 3 | id = 1, 4 | opened = '-', 5 | exitSensor = {5037, 230}, 6 | tp_town = {3473, 7770}, 7 | spawnAtLeft = true, 8 | }, 9 | hospital = { 10 | id = 2, 11 | opened = '-', 12 | exitSensor = {4142, 3635}, 13 | tp_town = {4850, 7770}, 14 | }, 15 | police = { 16 | id = 3, 17 | opened = '-', 18 | exitSensor = {7275, 6210}, 19 | tp_town = {1090, 7570}, 20 | }, 21 | buildshop = { 22 | id = 4, 23 | opened = '08:00 19:00', 24 | tp_town = {495, 7570}, 25 | exitSensor = {144, 230}, 26 | }, 27 | dealership = { 28 | id = 5, 29 | opened = '07:00 19:00', 30 | tp_town = {5000, 7770}, 31 | exitSensor = {8550, 230}, 32 | }, 33 | bank = { 34 | id = 6, 35 | opened = '07:00 19:00', 36 | tp_town = {2775, 7770}, 37 | exitSensor = {5540, 5230}, 38 | afterExit = function(player) 39 | if room.bankBeingRobbed then 40 | local shield = addImage('1566af4f852.png', '$'..player, -45, -45) 41 | players[player].robbery.usingShield = true 42 | addTimer(function() 43 | removeImage(shield) 44 | players[player].robbery.usingShield = false 45 | end, 7000, 1) 46 | end 47 | end 48 | }, 49 | pizzeria = { 50 | id = 7, 51 | opened = '-', 52 | tp_town = {4410, 7770}, 53 | exitSensor = {14080, 230}, 54 | }, 55 | fishShop = { 56 | id = 8, 57 | opened = '-', 58 | tp_town = {6030, 7770}, 59 | exitSensor = {12648, 230}, 60 | }, 61 | furnitureStore = { 62 | id = 9, 63 | opened = '08:00 19:00', 64 | tp_town = {5770, 7770}, 65 | exitSensor = {16070, 230}, 66 | }, 67 | town = { 68 | id = 10, 69 | opened = '-', 70 | exitSensor = {980, 8610}, 71 | tp_mine = {1260, 8650}, 72 | }, 73 | mine = { 74 | id = 11, 75 | opened = '-', 76 | exitSensor = {1210, 8645}, 77 | tp_town = {895, 8600}, 78 | }, 79 | mine_excavation = { 80 | id = 12, 81 | opened = '-', 82 | exitSensor = {5433, 8122}, 83 | tp_town = {5415, 7770}, 84 | }, 85 | cafe = { 86 | id = 13, 87 | opened = '-', 88 | exitSensor = {6090, 230}, 89 | tp_island = {10470, 7770}, 90 | }, 91 | potionShop = { 92 | id = 14, 93 | opened = '11:00 19:00', 94 | tp_island = {9895, 7770}, 95 | exitSensor = {10575, 230}, 96 | }, 97 | seedStore = { 98 | id = 15, 99 | opened = '08:00 19:00', 100 | tp_island = {12000, 7770}, 101 | exitSensor = {11430, 230}, 102 | }, 103 | boatShop = { 104 | id = 16, 105 | opened = '-', 106 | exitSensor = {1917, 8810}, 107 | tp_boatShop = {1455, 9300}, 108 | afterExit = function(player) 109 | showBoatShop(player, 1) 110 | showTextArea(1053, string.rep('\n', 10), player, 1425, 9125, 50, 200, 0, 0, 0, false, 111 | function(player) 112 | players[player].place = 'mine' 113 | setNightMode(player) 114 | movePlayer(player, 1873, 8810, false) 115 | end) 116 | end, 117 | } 118 | } -------------------------------------------------------------------------------- /source/places/bank/_properties.lua: -------------------------------------------------------------------------------- 1 | room.bank = { 2 | paperCurrentPlace = random(1, 13), 3 | paperImages = {}, 4 | paperPlaces = { 5 | {x = 500, y = 240}, -- Jason's Workshop 6 | {x = 7150, y = 6085}, -- Police Station, next to sherlock 7 | {x = 7300, y = 5960}, -- Police Station, office 8 | {x = 8200, y = 6400}, -- Police Station, jail 9 | {x = 4980, y = 240}, -- Market 10 | {x = 14700, y = 240}, -- Pizzeria 11 | {x = 13130, y = 240}, -- Fish Shop 12 | {x = 17500, y = 1710}, -- Oliver's Farm, garden 13 | {x = 12120, y = 240}, -- Seed Store 14 | {x = 6480, y = 240}, -- Café 15 | {x = 10750, y = 240}, -- Potion Shop 16 | {x = 11000, y = 7770}, -- Island, next to bridge 17 | {x = 15970, y = 1705}, -- Remi's restaurant 18 | {x = 700, y = 8180}, -- Mine 19 | {x = 5800, y = 5235}, -- Bank 20 | {x = 4750, y = 3621}, -- Hospital (P) 21 | }, 22 | } 23 | 24 | room.bankBeingRobbed = false 25 | room.bankRobbingTime = 60 26 | room.bankImages = {} 27 | room.bankTrashImages = {} 28 | room.bankRobStep = nil 29 | room.bankDoors = {'', '', '', '', ''} 30 | room.bankVaultPassword = random(0,9) .. random(0,9) .. random(0,9) .. random(0,9) -------------------------------------------------------------------------------- /source/places/bank/robbingAssets.lua: -------------------------------------------------------------------------------- 1 | reloadBankAssets = function() 2 | if not room.bankBeingRobbed then 3 | addGround(9998, 262+5000, 251+4955, {type = 12, color = 0xdad0b5, width = 24, height = 80}) 4 | else 5 | removeGround(9998) 6 | end 7 | end 8 | 9 | addBankRobbingAssets = function() 10 | if room.bankBeingRobbed then return end 11 | room.bankBeingRobbed = true 12 | 13 | for name in next, ROOM.playerList do 14 | if not players[name].driving then 15 | showTextArea(1029, '