Advertisement
Guest User

Scrap Mechanic /give Command

a guest
Jul 30th, 2021
545
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 35.96 KB | None | 0 0
  1. dofile( "$SURVIVAL_DATA/Scripts/game/survival_shapes.lua" )
  2. dofile( "$SURVIVAL_DATA/Scripts/game/survival_harvestable.lua" )
  3. dofile( "$SURVIVAL_DATA/Scripts/game/survival_constants.lua" )
  4. dofile( "$SURVIVAL_DATA/Scripts/game/managers/ElevatorManager.lua"  )
  5. dofile( "$SURVIVAL_DATA/Scripts/game/managers/RespawnManager.lua" )
  6. dofile( "$SURVIVAL_DATA/Scripts/game/managers/BeaconManager.lua" )
  7. dofile( "$SURVIVAL_DATA/Scripts/game/managers/UnitManager.lua" )
  8. dofile( "$SURVIVAL_DATA/Scripts/game/managers/QuestManager.lua" )
  9. dofile( "$SURVIVAL_DATA/Scripts/game/util/Timer.lua" )
  10. dofile( "$SURVIVAL_DATA/Scripts/game/survival_units.lua" )
  11. dofile( "$SURVIVAL_DATA/Scripts/game/util/recipes.lua" )
  12.  
  13. SurvivalGame = class( nil )
  14. SurvivalGame.enableLimitedInventory = true
  15. SurvivalGame.enableRestrictions = true
  16. SurvivalGame.enableFuelConsumption = true
  17. SurvivalGame.enableAmmoConsumption = true
  18. SurvivalGame.enableUpgradeCost = true
  19.  
  20. local SyncInterval = 400 -- 400 ticks | 10 seconds
  21.  
  22.  
  23. function SurvivalGame.server_onCreate( self )
  24.     print( "SurvivalGame.server_onCreate" )
  25.     self.sv = {}
  26.     self.sv.saved = self.storage:load()
  27.     print( "Saved:", self.sv.saved )
  28.     if self.sv.saved == nil then
  29.         self.sv.saved = {}
  30.         self.sv.saved.data = self.data
  31.         printf( "Seed: %.0f", self.sv.saved.data.seed )
  32.         self.sv.saved.overworld = sm.world.createWorld( "$SURVIVAL_DATA/Scripts/game/worlds/Overworld.lua", "Overworld", { dev = self.sv.saved.data.dev }, self.sv.saved.data.seed )
  33.         self.storage:save( self.sv.saved )
  34.     end
  35.     self.data = nil
  36.  
  37.     print( self.sv.saved.data )
  38.     g_survivalDev = true
  39.     if self.sv.saved.data and self.sv.saved.data.dev then
  40.         g_godMode = true
  41.        
  42.     end
  43.  
  44.     self:loadCraftingRecipes()
  45.  
  46.     g_elevatorManager = ElevatorManager()
  47.     g_elevatorManager:sv_onCreate()
  48.  
  49.     g_respawnManager = RespawnManager()
  50.     g_respawnManager:sv_onCreate( self.sv.saved.overworld )
  51.  
  52.     g_beaconManager = BeaconManager()
  53.     g_beaconManager:sv_onCreate()
  54.  
  55.     g_unitManager = UnitManager()
  56.     g_unitManager:sv_onCreate( self.sv.saved.overworld )
  57.  
  58.     g_questManager = QuestManager()
  59.     g_questManager:sv_onCreate( self )
  60.     g_questManager:sv_activateQuest( quest_use_terminal )
  61.  
  62.     if g_survivalDev then
  63.         g_questManager:sv_completeQuest( quest_pickup_logbook )
  64.     end
  65.  
  66.     -- Game script managed global warehouse table
  67.     self.warehouses = sm.storage.load( STORAGE_CHANNEL_WAREHOUSES )
  68.     if self.warehouses then
  69.         print( "Loaded warehouses:" )
  70.         print( self.warehouses )
  71.     else
  72.         self.warehouses = {}
  73.         self:sv_e_saveWarehouses()
  74.     end
  75.     g_warehouses = self.warehouses
  76.  
  77.  
  78.     self.sv.time = sm.storage.load( STORAGE_CHANNEL_TIME )
  79.     if self.sv.time then
  80.         print( "Loaded timeData:" )
  81.         print( self.sv.time )
  82.     else
  83.         self.sv.time = {}
  84.         self.sv.time.timeOfDay = 6 / 24 -- 06:00
  85.         self.sv.time.timeProgress = true
  86.         sm.storage.save( STORAGE_CHANNEL_TIME, self.sv.time )
  87.     end
  88.     self:sv_updateClientData()
  89.  
  90.     self.sv.syncTimer = Timer()
  91.     self.sv.syncTimer:start( 0 )
  92.  end
  93.  
  94. function SurvivalGame.server_onRefresh( self )
  95.     g_craftingRecipes = nil
  96.     g_refineryRecipes = nil
  97.     self:loadCraftingRecipes()
  98. end
  99.  
  100. function SurvivalGame.client_onCreate( self )
  101.  
  102.     self.cl = {}
  103.     self.cl.time = {}
  104.     self.cl.time.timeOfDay = 0.0
  105.     self.cl.time.timeProgress = true
  106.  
  107.     if sm.isHost and g_survivalDev then
  108.         self:bindChatCommands()
  109.     end
  110.  
  111.     if not sm.isHost then
  112.         self:loadCraftingRecipes()
  113.     end
  114.  
  115.     if g_respawnManager == nil then
  116.         assert( not sm.isHost )
  117.         g_respawnManager = RespawnManager()
  118.     end
  119.     g_respawnManager:cl_onCreate()
  120.  
  121.     if g_beaconManager == nil then
  122.         assert( not sm.isHost )
  123.         g_beaconManager = BeaconManager()
  124.     end
  125.     g_beaconManager:cl_onCreate()
  126.  
  127.     if g_unitManager == nil then
  128.         assert( not sm.isHost )
  129.         g_unitManager = UnitManager()
  130.     end
  131.     g_unitManager:cl_onCreate()
  132.  
  133.     if g_questManager == nil then
  134.         assert( not sm.isHost )
  135.         g_questManager = QuestManager()
  136.     end
  137.     g_questManager:cl_onCreate()
  138.  
  139.     -- Music effect
  140.     g_survivalMusic = sm.effect.createEffect( "SurvivalMusic" )
  141.     assert(g_survivalMusic)
  142.  
  143.     -- Survival HUD
  144.     g_survivalHud = sm.gui.createSurvivalHudGui()
  145.     assert(g_survivalHud)
  146. end
  147.  
  148. function SurvivalGame.bindChatCommands( self )
  149.     sm.game.bindChatCommand( "/ammo", { { "int", "quantity", true } }, "cl_onChatCommand", "Give ammo (default 50)" )
  150.     sm.game.bindChatCommand( "/spudgun", {}, "cl_onChatCommand", "Give the spudgun" )
  151.     sm.game.bindChatCommand( "/gatling", {}, "cl_onChatCommand", "Give the potato gatling gun" )
  152.     sm.game.bindChatCommand( "/shotgun", {}, "cl_onChatCommand", "Give the fries shotgun" )
  153.     sm.game.bindChatCommand( "/sunshake", {}, "cl_onChatCommand", "Give 1 sunshake" )
  154.     sm.game.bindChatCommand( "/baguette", {}, "cl_onChatCommand", "Give 1 revival baguette" )
  155.     sm.game.bindChatCommand( "/keycard", {}, "cl_onChatCommand", "Give 1 keycard" )
  156.     sm.game.bindChatCommand( "/powercore", {}, "cl_onChatCommand", "Give 1 powercore" )
  157.     sm.game.bindChatCommand( "/components", { { "int", "quantity", true } }, "cl_onChatCommand", "Give <quantity> components (default 10)" )
  158.     sm.game.bindChatCommand( "/glowsticks", { { "int", "quantity", true } }, "cl_onChatCommand", "Give <quantity> components (default 10)" )
  159.     sm.game.bindChatCommand( "/tumble", { { "bool", "enable", true } }, "cl_onChatCommand", "Set tumble state" )
  160.     sm.game.bindChatCommand( "/god", {}, "cl_onChatCommand", "Mechanic characters will take no damage" )
  161.     sm.game.bindChatCommand( "/respawn", {}, "cl_onChatCommand", "Respawn at last bed (or at the crash site)" )
  162.     sm.game.bindChatCommand( "/encrypt", {}, "cl_onChatCommand", "Restrict interactions in all warehouses" )
  163.     sm.game.bindChatCommand( "/decrypt", {}, "cl_onChatCommand", "Unrestrict interactions in all warehouses" )
  164.     sm.game.bindChatCommand( "/limited", {}, "cl_onChatCommand", "Use the limited inventory" )
  165.     sm.game.bindChatCommand( "/unlimited", {}, "cl_onChatCommand", "Use the unlimited inventory" )
  166.     sm.game.bindChatCommand( "/ambush", { { "number", "magnitude", true }, { "int", "wave", true } }, "cl_onChatCommand", "Starts a 'random' encounter" )
  167.     --sm.game.bindChatCommand( "/recreate", {}, "cl_onChatCommand", "Recreate world" )
  168.     sm.game.bindChatCommand( "/timeofday", { { "number", "timeOfDay", true } }, "cl_onChatCommand", "Sets the time of the day as a fraction (0.5=mid day)" )
  169.     sm.game.bindChatCommand( "/timeprogress", { { "bool", "enabled", true } }, "cl_onChatCommand", "Enables or disables time progress" )
  170.     sm.game.bindChatCommand( "/day", {}, "cl_onChatCommand", "Disable time progression and set time to daytime" )
  171.     sm.game.bindChatCommand( "/spawn", { { "string", "unitName", true } }, "cl_onChatCommand", "Spawn a unit: 'woc', 'tapebot', 'totebot', 'haybot'" )
  172.     sm.game.bindChatCommand( "/harvestable", { { "string", "harvestableName", true } }, "cl_onChatCommand", "Create a harvestable: 'tree', 'stone'" )
  173.     sm.game.bindChatCommand( "/cleardebug", {}, "cl_onChatCommand", "Clear debug draw objects" )
  174.     sm.game.bindChatCommand( "/export", { { "string", "name", false } }, "cl_onChatCommand", "Exports blueprint $SURVIVAL_DATA/LocalBlueprints/<name>.blueprint" )
  175.     sm.game.bindChatCommand( "/import", { { "string", "name", false } }, "cl_onChatCommand", "Imports blueprint $SURVIVAL_DATA/LocalBlueprints/<name>.blueprint" )
  176.     sm.game.bindChatCommand( "/starterkit", {}, "cl_onChatCommand", "Spawn a starter kit" )
  177.     sm.game.bindChatCommand( "/mechanicstartkit", {}, "cl_onChatCommand", "Spawn a starter kit for starting at mechanic station" )
  178.     sm.game.bindChatCommand( "/pipekit", {}, "cl_onChatCommand", "Spawn a pipe kit" )
  179.     sm.game.bindChatCommand( "/foodkit", {}, "cl_onChatCommand", "Spawn a food kit" )
  180.     sm.game.bindChatCommand( "/seedkit", {}, "cl_onChatCommand", "Spawn a seed kit" )
  181.     sm.game.bindChatCommand( "/die", {}, "cl_onChatCommand", "Kill the player" )
  182.     sm.game.bindChatCommand( "/sethp", { { "number", "hp", false } }, "cl_onChatCommand", "Set player hp value" )
  183.     sm.game.bindChatCommand( "/setwater", { { "number", "water", false } }, "cl_onChatCommand", "Set player water value" )
  184.     sm.game.bindChatCommand( "/setfood", { { "number", "food", false } }, "cl_onChatCommand", "Set player food value" )
  185.     sm.game.bindChatCommand( "/aggroall", {}, "cl_onChatCommand", "All hostile units will be made aware of the player's position" )
  186.     sm.game.bindChatCommand( "/goto", { { "string", "name", false } }, "cl_onChatCommand", "Teleport to predefined position" )
  187.     sm.game.bindChatCommand( "/raid", { { "int", "level", false }, { "int", "wave", true }, { "number", "hours", true } }, "cl_onChatCommand", "Start a level <level> raid at player position at wave <wave> in <delay> hours." )
  188.     sm.game.bindChatCommand( "/stopraid", {}, "cl_onChatCommand", "Cancel all incoming raids" )
  189.     sm.game.bindChatCommand( "/disableraids", { { "bool", "enabled", false } }, "cl_onChatCommand", "Disable raids if true" )
  190.     sm.game.bindChatCommand( "/camera", {}, "cl_onChatCommand", "Spawn a SplineCamera tool" )
  191.     sm.game.bindChatCommand( "/noaggro", { { "bool", "enable", true } }, "cl_onChatCommand", "Toggles the player as a target" )
  192.     sm.game.bindChatCommand( "/killall", {}, "cl_onChatCommand", "Kills all spawned units" )
  193.  
  194.     sm.game.bindChatCommand( "/printglobals", {}, "cl_onChatCommand", "Print all global lua variables" )
  195.     sm.game.bindChatCommand( "/clearpathnodes", {}, "cl_onChatCommand", "Clear all path nodes in overworld" )
  196.     sm.game.bindChatCommand( "/enablepathpotatoes", { { "bool", "enable", true } }, "cl_onChatCommand", "Creates path nodes at potato hits in overworld and links to previous node" )
  197.  
  198.     sm.game.bindChatCommand( "/activatequest",  { { "string", "uuid", true } }, "cl_onChatCommand", "Activate quest" )
  199.     sm.game.bindChatCommand( "/completequest",  { { "string", "uuid", true } }, "cl_onChatCommand", "Complete quest" )
  200.  
  201.     -- Chat Mod Commands
  202.     sm.game.bindChatCommand( "/give", { {"string", "name", false}, {"int", "quantity", true}}, "ChatMod_ProccessGiveCommand", "Gives the player a cetain item.")
  203. end
  204.  
  205. function SurvivalGame.client_onClientDataUpdate( self, clientData )
  206.     self.cl.time = clientData.time
  207.  
  208.     if not g_survivalDev and clientData.dev and not sm.isHost then
  209.         self:bindChatCommands()
  210.     end
  211.  
  212.     g_survivalDev = clientData.dev
  213. end
  214.  
  215. function SurvivalGame.cl_n_questMsg( self, params )
  216.     g_questManager:cl_handleMsg( params )
  217. end
  218.  
  219. function SurvivalGame.loadCraftingRecipes( self )
  220.     LoadCraftingRecipes({
  221.         workbench = "$SURVIVAL_DATA/CraftingRecipes/workbench.json",
  222.         dispenser = "$SURVIVAL_DATA/CraftingRecipes/dispenser.json",
  223.         cookbot = "$SURVIVAL_DATA/CraftingRecipes/cookbot.json",
  224.         craftbot = "$SURVIVAL_DATA/CraftingRecipes/craftbot.json",
  225.         dressbot = "$SURVIVAL_DATA/CraftingRecipes/dressbot.json"
  226.     })
  227. end
  228.  
  229. function SurvivalGame.server_onFixedUpdate( self, timeStep )
  230.     -- Update time
  231.     local prevTime = self.sv.time.timeOfDay
  232.     if self.sv.time.timeProgress then
  233.         self.sv.time.timeOfDay = self.sv.time.timeOfDay + timeStep / DAYCYCLE_TIME
  234.     end
  235.     local newDay = self.sv.time.timeOfDay >= 1.0
  236.     if newDay then
  237.         self.sv.time.timeOfDay = math.fmod( self.sv.time.timeOfDay, 1 )
  238.     end
  239.  
  240.     if self.sv.time.timeOfDay >= DAYCYCLE_DAWN and prevTime < DAYCYCLE_DAWN then
  241.         g_unitManager:sv_initNewDay()
  242.     end
  243.  
  244.     -- Ambush
  245.     --if not g_survivalDev then
  246.     --  for _,ambush in ipairs( AMBUSHES ) do
  247.     --      if self.sv.time.timeOfDay >= ambush.time and ( prevTime < ambush.time or newDay ) then
  248.     --          self:sv_ambush( { magnitude = ambush.magnitude, wave = ambush.wave } )
  249.     --      end
  250.     --  end
  251.     --end
  252.  
  253.     -- Client and save sync
  254.     self.sv.syncTimer:tick()
  255.     if self.sv.syncTimer:done() then
  256.         self.sv.syncTimer:start( SyncInterval )
  257.         sm.storage.save( STORAGE_CHANNEL_TIME, self.sv.time )
  258.         self:sv_updateClientData()
  259.     end
  260.  
  261.     g_elevatorManager:sv_onFixedUpdate()
  262.     g_unitManager:sv_onFixedUpdate()
  263.     g_questManager:sv_onFixedUpdate()
  264. end
  265.  
  266. function SurvivalGame.sv_updateClientData( self )
  267.     self.network:setClientData( { time = self.sv.time, dev = g_survivalDev } )
  268. end
  269.  
  270. function SurvivalGame.client_onUpdate( self, dt )
  271.     -- Update time
  272.     if self.cl.time.timeProgress then
  273.         self.cl.time.timeOfDay = math.fmod( self.cl.time.timeOfDay + dt / DAYCYCLE_TIME, 1.0 )
  274.     end
  275.     sm.game.setTimeOfDay( self.cl.time.timeOfDay )
  276.  
  277.     -- Update lighting values
  278.     local index = 1
  279.     while index < #DAYCYCLE_LIGHTING_TIMES and self.cl.time.timeOfDay >= DAYCYCLE_LIGHTING_TIMES[index + 1] do
  280.         index = index + 1
  281.     end
  282.     assert( index <= #DAYCYCLE_LIGHTING_TIMES )
  283.  
  284.     local light = 0.0
  285.     if index < #DAYCYCLE_LIGHTING_TIMES then
  286.         local p = ( self.cl.time.timeOfDay - DAYCYCLE_LIGHTING_TIMES[index] ) / ( DAYCYCLE_LIGHTING_TIMES[index + 1] - DAYCYCLE_LIGHTING_TIMES[index] )
  287.         light = sm.util.lerp( DAYCYCLE_LIGHTING_VALUES[index], DAYCYCLE_LIGHTING_VALUES[index + 1], p )
  288.     else
  289.         light = DAYCYCLE_LIGHTING_VALUES[index]
  290.     end
  291.     sm.render.setOutdoorLighting( light )
  292. end
  293.  
  294. function SurvivalGame.client_showMessage( self, params )
  295.     sm.gui.chatMessage( params )
  296. end
  297.  
  298. -- Proccess Give
  299. function SurvivalGame.ChatMod_ProccessGiveCommand(self, params)
  300.     itemToGive = nil
  301.     if string.match( params[2], "%x%x%x%x%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%-%x%x%x%x%x%x%x%x%x%x%x%x") then
  302.         itemToGive = sm.uuid.new(params[2])
  303.     else
  304.         itemToGive = _G[params[2]]
  305.     end
  306.     self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = itemToGive, quantity = ( params[3] or 1 ) } )
  307.     SurvivalGame.client_showMessage(self, "Gave you " .. params[2] .. " (" .. params[3] .. ")")
  308. end
  309.  
  310. function SurvivalGame.cl_onChatCommand( self, params )
  311.     if params[1] == "/ammo" then
  312.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = obj_plantables_potato, quantity = ( params[2] or 50 ) } )
  313.     elseif params[1] == "/spudgun" then
  314.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = tool_spudgun, quantity = 1 } )
  315.     elseif params[1] == "/gatling" then
  316.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = tool_gatling, quantity = 1 } )
  317.     elseif params[1] == "/shotgun" then
  318.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = tool_shotgun, quantity = 1 } )
  319.     elseif params[1] == "/sunshake" then
  320.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = obj_consumable_sunshake, quantity = 1 } )
  321.     elseif params[1] == "/baguette" then
  322.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = obj_consumable_longsandwich, quantity = 1 } )
  323.     elseif params[1] == "/keycard" then
  324.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = obj_survivalobject_keycard, quantity = 1 } )
  325.     elseif params[1] == "/camera" then
  326.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = sm.uuid.new( "5bbe87d3-d60a-48b5-9ca9-0086c80ebf7f" ), quantity = 1 } )
  327.     elseif params[1] == "/powercore" then
  328.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = obj_survivalobject_powercore, quantity = 1 } )
  329.     elseif params[1] == "/components" then
  330.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = obj_consumable_component, quantity = ( params[2] or 10 ) } )
  331.     elseif params[1] == "/glowsticks" then
  332.         self.network:sendToServer( "sv_giveItem", { player = sm.localPlayer.getPlayer(), item = obj_consumable_glowstick, quantity = ( params[2] or 10 ) } )
  333.     elseif params[1] == "/god" then
  334.         self.network:sendToServer( "sv_switchGodMode" )
  335.     elseif params[1] == "/encrypt" then
  336.         self.network:sendToServer( "sv_enableRestrictions", true )
  337.     elseif params[1] == "/decrypt" then
  338.         self.network:sendToServer( "sv_enableRestrictions", false )
  339.     elseif params[1] == "/unlimited" then
  340.         self.network:sendToServer( "sv_setLimitedInventory", false )
  341.     elseif params[1] == "/limited" then
  342.         self.network:sendToServer( "sv_setLimitedInventory", true )
  343.     elseif params[1] == "/ambush" then
  344.         self.network:sendToServer( "sv_ambush", { magnitude = params[2] or 1, wave = params[3] } )
  345.     elseif params[1] == "/recreate" then
  346.         self.network:sendToServer( "sv_recreateWorld", sm.localPlayer.getPlayer() )
  347.     elseif params[1] == "/timeofday" then
  348.         self.network:sendToServer( "sv_setTimeOfDay", params[2] )
  349.     elseif params[1] == "/timeprogress" then
  350.         self.network:sendToServer( "sv_setTimeProgress", params[2] )
  351.     elseif params[1] == "/day" then
  352.         self.network:sendToServer( "sv_setTimeOfDay", 0.5 )
  353.         self.network:sendToServer( "sv_setTimeProgress", false )
  354.     elseif params[1] == "/die" then
  355.         self.network:sendToServer( "sv_killPlayer", { player = sm.localPlayer.getPlayer() })
  356.     elseif params[1] == "/spawn" then
  357.         local rayCastValid, rayCastResult = sm.localPlayer.getRaycast( 100 )
  358.         if rayCastValid then
  359.             local spawnParams = {
  360.                 uuid = sm.uuid.new( "00000000-0000-0000-0000-000000000000" ),
  361.                 world = sm.localPlayer.getPlayer().character:getWorld(),
  362.                 position = rayCastResult.pointWorld,
  363.                 yaw = 0.0
  364.             }
  365.             if params[2] == "woc" then
  366.                 spawnParams.uuid = unit_woc
  367.             elseif params[2] == "tapebot" or params[2] == "tb" then
  368.                 spawnParams.uuid = unit_tapebot
  369.             elseif params[2] == "redtapebot" or params[2] == "rtb" then
  370.                 spawnParams.uuid = unit_tapebot_red
  371.             elseif params[2] == "totebot" or params[2] == "green" or params[2] == "t" then
  372.                 spawnParams.uuid = unit_totebot_green
  373.             elseif params[2] == "haybot" or params[2] == "h" then
  374.                 spawnParams.uuid = unit_haybot
  375.             elseif params[2] == "worm" then
  376.                 spawnParams.uuid = unit_worm
  377.             elseif params[2] == "farmbot" or params[2] == "f" then
  378.                 spawnParams.uuid = unit_farmbot
  379.             elseif params[2] then
  380.                 spawnParams.uuid = sm.uuid.new( params[2] )
  381.             end
  382.             self.network:sendToServer( "sv_spawnUnit", spawnParams )
  383.         end
  384.     elseif params[1] == "/harvestable" then
  385.         local character = sm.localPlayer.getPlayer().character
  386.         if character then
  387.             local harvestableUuid = sm.uuid.new( "00000000-0000-0000-0000-000000000000" )
  388.             if params[2] == "tree" then
  389.                 harvestableUuid = sm.uuid.new( "c4ea19d3-2469-4059-9f13-3ddb4f7e0b79" )
  390.             elseif params[2] == "stone" then
  391.                 harvestableUuid = sm.uuid.new( "0d3362ae-4cb3-42ae-8a08-d3f9ed79e274" )
  392.             elseif params[2] == "soil" then
  393.                 harvestableUuid = hvs_soil
  394.             elseif params[2] == "fencelong" then
  395.                 harvestableUuid = sm.uuid.new( "c0f19413-6d8e-4b20-819a-949553242259" )
  396.             elseif params[2] == "fenceshort" then
  397.                 harvestableUuid = sm.uuid.new( "144b5e79-483e-4da6-86ab-c575d0fdcd11" )
  398.             elseif params[2] == "fencecorner" then
  399.                 harvestableUuid = sm.uuid.new( "ead875db-59d0-45f5-861e-b3075e1f8434" )
  400.             elseif params[2] == "beehive" then
  401.                 harvestableUuid = hvs_farmables_beehive
  402.             elseif params[2] == "cotton" then
  403.                 harvestableUuid = hvs_farmables_cottonplant
  404.             elseif params[2] then
  405.                 harvestableUuid = sm.uuid.new( params[2] )
  406.             end
  407.             local spawnParams = { world = character:getWorld(), uuid = harvestableUuid, position = character.worldPosition, quat = sm.vec3.getRotation( sm.vec3.new( 0, 1, 0 ), sm.vec3.new( 0, 0, 1 ) )  }
  408.             self.network:sendToServer( "sv_spawnHarvestable", spawnParams )
  409.         end
  410.     elseif params[1] == "/cleardebug" then
  411.         sm.debugDraw.clear()
  412.     elseif params[1] == "/export" then
  413.         local rayCastValid, rayCastResult = sm.localPlayer.getRaycast( 100 )
  414.         if rayCastValid and rayCastResult.type == "body" then
  415.             local importParams = {
  416.                 name = params[2],
  417.                 body = rayCastResult:getBody()
  418.             }
  419.             self.network:sendToServer( "sv_exportCreation", importParams )
  420.         end
  421.     elseif params[1] == "/import" then
  422.         local rayCastValid, rayCastResult = sm.localPlayer.getRaycast( 100 )
  423.         if rayCastValid then
  424.             local importParams = {
  425.                 world = sm.localPlayer.getPlayer().character:getWorld(),
  426.                 name = params[2],
  427.                 position = rayCastResult.pointWorld
  428.             }
  429.             self.network:sendToServer( "sv_importCreation", importParams )
  430.         end
  431.     elseif params[1] == "/noaggro" then
  432.         if type( params[2] ) == "boolean" then
  433.             self.network:sendToServer( "sv_n_switchAggroMode", { aggroMode = not params[2] } )
  434.         else
  435.             self.network:sendToServer( "sv_n_switchAggroMode", { aggroMode = not sm.game.getEnableAggro() } )
  436.         end
  437.     else
  438.         self.network:sendToServer( "sv_onChatCommand", params )
  439.     end
  440. end
  441.  
  442. function SurvivalGame.sv_giveItem( self, params )
  443.     sm.container.beginTransaction()
  444.     sm.container.collect( params.player:getInventory(), params.item, params.quantity, false )
  445.     sm.container.endTransaction()
  446. end
  447.  
  448. function SurvivalGame.sv_switchGodMode( self )
  449.     g_godMode = not g_godMode
  450.     self.network:sendToClients( "client_showMessage", "GODMODE: " .. ( g_godMode and "On" or "Off" ) )
  451. end
  452.  
  453. function SurvivalGame.sv_n_switchAggroMode( self, params )
  454.     sm.game.setEnableAggro(params.aggroMode )
  455.     self.network:sendToClients( "client_showMessage", "AGGRO: " .. ( params.aggroMode and "On" or "Off" ) )
  456. end
  457.  
  458. function SurvivalGame.sv_enableRestrictions( self, state )
  459.     sm.game.setEnableRestrictions( state )
  460.     self.network:sendToClients( "client_showMessage", ( state and "Restricted" or "Unrestricted"  ) )
  461. end
  462.  
  463. function SurvivalGame.sv_setLimitedInventory( self, state )
  464.     sm.game.setLimitedInventory( state )
  465.     self.network:sendToClients( "client_showMessage", ( state and "Limited inventory" or "Unlimited inventory"  ) )
  466. end
  467.  
  468. function SurvivalGame.sv_ambush( self, params )
  469.     if sm.exists( self.sv.saved.overworld ) then
  470.         sm.event.sendToWorld( self.sv.saved.overworld, "sv_ambush", params )
  471.     end
  472. end
  473.  
  474. function SurvivalGame.sv_recreateWorld( self, player )
  475.     local character = player:getCharacter()
  476.     if character:getWorld() == self.sv.saved.overworld then
  477.         self.sv.saved.overworld:destroy()
  478.         self.sv.saved.overworld = sm.world.createWorld( "$SURVIVAL_DATA/Scripts/game/worlds/Overworld.lua", "Overworld", { dev = g_survivalDev }, self.sv.saved.data.seed )
  479.         self.storage:save( self.sv.saved )
  480.  
  481.         local params = { pos = character:getWorldPosition(), dir = character:getDirection() }
  482.         self.sv.saved.overworld:loadCell( math.floor( params.pos.x/64 ), math.floor( params.pos.y/64 ), player, "sv_recreatePlayerCharacter", params )
  483.  
  484.         self.network:sendToClients( "client_showMessage", "Recreating world" )
  485.     else
  486.         self.network:sendToClients( "client_showMessage", "Recreate world only allowed for overworld" )
  487.     end
  488. end
  489.  
  490. function SurvivalGame.sv_setTimeOfDay( self, timeOfDay )
  491.     if timeOfDay then
  492.         self.sv.time.timeOfDay = timeOfDay
  493.         self.sv.syncTimer.count = self.sv.syncTimer.ticks -- Force sync
  494.     end
  495.     self.network:sendToClients( "client_showMessage", ( "Time of day set to "..self.sv.time.timeOfDay ) )
  496. end
  497.  
  498. function SurvivalGame.sv_setTimeProgress( self, timeProgress )
  499.     if timeProgress ~= nil then
  500.         self.sv.time.timeProgress = timeProgress
  501.         self.sv.syncTimer.count = self.sv.syncTimer.ticks -- Force sync
  502.     end
  503.     self.network:sendToClients( "client_showMessage", ( "Time scale set to "..( self.sv.time.timeProgress and "on" or "off ") ) )
  504. end
  505.  
  506. function SurvivalGame.sv_killPlayer( self, params )
  507.     params.damage = 9999
  508.     sm.event.sendToPlayer( params.player, "sv_e_receiveDamage", params )
  509. end
  510.  
  511. function SurvivalGame.sv_spawnUnit( self, params )
  512.     sm.event.sendToWorld( params.world, "sv_e_spawnUnit", params )
  513. end
  514.  
  515. function SurvivalGame.sv_spawnHarvestable( self, params )
  516.     sm.event.sendToWorld( params.world, "sv_spawnHarvestable", params )
  517. end
  518.  
  519. function SurvivalGame.sv_exportCreation( self, params )
  520.     local obj = sm.json.parseJsonString( sm.creation.exportToString( params.body ) )
  521.     sm.json.save( obj, "$SURVIVAL_DATA/LocalBlueprints/"..params.name..".blueprint" )
  522. end
  523.  
  524. function SurvivalGame.sv_importCreation( self, params )
  525.     sm.creation.importFromFile( params.world, "$SURVIVAL_DATA/LocalBlueprints/"..params.name..".blueprint", params.position )
  526. end
  527.  
  528. function SurvivalGame.sv_onChatCommand( self, params, player )
  529.     if params[1] == "/tumble" then
  530.         if params[2] ~= nil then
  531.             player.character:setTumbling( params[2] )
  532.         end
  533.         if player.character:isTumbling() then
  534.             self.network:sendToClients( "client_showMessage", "Player is tumbling" )
  535.         else
  536.             self.network:sendToClients( "client_showMessage", "Player is not tumbling" )
  537.         end
  538.  
  539.     elseif params[1] == "/sethp" then
  540.         sm.event.sendToPlayer( player, "sv_e_debug", { hp = params[2] } )
  541.  
  542.     elseif params[1] == "/setwater" then
  543.         sm.event.sendToPlayer( player, "sv_e_debug", { water = params[2] } )
  544.  
  545.     elseif params[1] == "/setfood" then
  546.         sm.event.sendToPlayer( player, "sv_e_debug", { food = params[2] } )
  547.  
  548.     elseif params[1] == "/goto" then
  549.         local pos
  550.         if params[2] == "here" then
  551.             pos = player.character:getWorldPosition()
  552.         elseif params[2] == "start" then
  553.             pos = START_AREA_SPAWN_POINT
  554.         elseif params[2] == "hideout" then
  555.             pos = sm.vec3.new( 32, -1248, 100 )
  556.         else
  557.             self.network:sendToClient( player, "client_showMessage", "Unknown place" )
  558.         end
  559.         if pos then
  560.             local cellX, cellY = math.floor( pos.x/64 ), math.floor( pos.y/64 )
  561.             self.sv.saved.overworld:loadCell( cellX, cellY, player, "sv_recreatePlayerCharacter", { pos = pos, dir = player.character:getDirection() } )
  562.         end
  563.  
  564.     elseif params[1] == "/respawn" then
  565.         sm.event.sendToPlayer( player, "sv_e_respawn" )
  566.  
  567.     elseif params[1] == "/printglobals" then
  568.         print( "Globals:" )
  569.         for k,_ in pairs(_G) do
  570.             print( k )
  571.         end
  572.  
  573.     elseif params[1] == "/activatequest" then
  574.         local uuid = params[2]
  575.         if uuid then
  576.             g_questManager:sv_activateQuest( uuid )
  577.         else
  578.             g_questManager:sv_activateAllQuests()
  579.         end
  580.     elseif params[1] == "/completequest" then
  581.         local uuid = params[2]
  582.         if uuid then
  583.             g_questManager:sv_completeQuest( uuid )
  584.         else
  585.             g_questManager:sv_completeAllQuests()
  586.         end
  587.     elseif params[1] == "/clearpathnodes"
  588.         or params[1] == "/enablepathpotatoes"
  589.         or params[1] == "/starterkit"
  590.         or params[1] == "/mechanicstartkit"
  591.         or params[1] == "/pipekit"
  592.         or params[1] == "/foodkit"
  593.         or params[1] == "/seedkit"
  594.         or params[1] == "/aggroall"
  595.         or params[1] == "/raid"
  596.         or params[1] == "/stopraid"
  597.         or params[1] == "/disableraids"
  598.         or params[1] == "/killall"
  599.     then
  600.         params.player = player
  601.         if sm.exists( player.character ) then
  602.             sm.event.sendToWorld( player.character:getWorld(), "sv_e_onChatCommand", params )
  603.         end
  604.     end
  605. end
  606.  
  607. function SurvivalGame.server_onPlayerJoined( self, player, newPlayer )
  608.     print( player.name, "joined the game" )
  609.  
  610.     if newPlayer then --Player is first time joiners
  611.         local inventory = player:getInventory()
  612.  
  613.         sm.container.beginTransaction()
  614.  
  615.         if g_survivalDev then
  616.             --Hotbar
  617.             sm.container.setItem( inventory, 0, tool_sledgehammer, 1 )
  618.             sm.container.setItem( inventory, 1, tool_spudgun, 1 )
  619.             sm.container.setItem( inventory, 7, obj_plantables_potato, 50 )
  620.             sm.container.setItem( inventory, 8, tool_lift, 1 )
  621.             sm.container.setItem( inventory, 9, tool_connect, 1 )
  622.  
  623.             --Actual inventory
  624.             sm.container.setItem( inventory, 10, tool_paint, 1 )
  625.             sm.container.setItem( inventory, 11, tool_weld, 1 )
  626.         else
  627.             sm.container.setItem( inventory, 0, tool_sledgehammer, 1 )
  628.             sm.container.setItem( inventory, 1, tool_lift, 1 )
  629.         end
  630.  
  631.         sm.container.endTransaction()
  632.  
  633.         local spawnPoint = START_AREA_SPAWN_POINT
  634.         if g_survivalDev then
  635.             spawnPoint = SURVIVAL_DEV_SPAWN_POINT
  636.         end
  637.         if not sm.exists( self.sv.saved.overworld ) then
  638.             sm.world.loadWorld( self.sv.saved.overworld )
  639.         end
  640.         self.sv.saved.overworld:loadCell( math.floor( spawnPoint.x/64 ), math.floor( spawnPoint.y/64 ), player, "sv_createNewPlayer" )
  641.     else
  642.         local inventory = player:getInventory()
  643.  
  644.         local sledgehammerCount = sm.container.totalQuantity( inventory, tool_sledgehammer )
  645.         if sledgehammerCount == 0 then
  646.             sm.container.beginTransaction()
  647.             sm.container.collect( inventory, tool_sledgehammer, 1 )
  648.             sm.container.endTransaction()
  649.         elseif sledgehammerCount > 1 then
  650.             sm.container.beginTransaction()
  651.             sm.container.spend( inventory, tool_sledgehammer, sledgehammerCount - 1 )
  652.             sm.container.endTransaction()
  653.         end
  654.  
  655.         local tool_lift_creative = sm.uuid.new( "5cc12f03-275e-4c8e-b013-79fc0f913e1b" )
  656.         local creativeLiftCount = sm.container.totalQuantity( inventory, tool_lift_creative )
  657.         if creativeLiftCount > 0 then
  658.             sm.container.beginTransaction()
  659.             sm.container.spend( inventory, tool_lift_creative, creativeLiftCount )
  660.             sm.container.endTransaction()
  661.         end
  662.  
  663.         local liftCount = sm.container.totalQuantity( inventory, tool_lift )
  664.         if liftCount == 0 then
  665.             sm.container.beginTransaction()
  666.             sm.container.collect( inventory, tool_lift, 1 )
  667.             sm.container.endTransaction()
  668.         elseif liftCount > 1 then
  669.             sm.container.beginTransaction()
  670.             sm.container.spend( inventory, tool_lift, liftCount - 1 )
  671.             sm.container.endTransaction()
  672.         end
  673.     end
  674.     g_unitManager:sv_onPlayerJoined( player )
  675.     g_questManager:sv_onPlayerJoined( player )
  676. end
  677.  
  678. function SurvivalGame.server_onPlayerLeft( self, player )
  679.     print( player.name, "left the game" )
  680.     g_elevatorManager:sv_onPlayerLeft( player )
  681. end
  682.  
  683. function SurvivalGame.sv_e_saveWarehouses( self )
  684.     sm.storage.save( STORAGE_CHANNEL_WAREHOUSES, self.warehouses )
  685.     print( "Saved warehouses:" )
  686.     print( self.warehouses )
  687. end
  688.  
  689. function SurvivalGame.sv_e_requestWarehouseRestrictions( self, params )
  690.     -- Send the warehouse restrictions to the world that asked
  691.     print("SurvivalGame.sv_e_requestWarehouseRestrictions")
  692.  
  693.     -- Warehouse get
  694.     local warehouse = nil
  695.     if params.warehouseIndex then
  696.         warehouse = self.warehouses[params.warehouseIndex]
  697.     end
  698.     if warehouse then
  699.         sm.event.sendToWorld( params.world, "server_updateRestrictions", warehouse.restrictions )
  700.     end
  701. end
  702.  
  703. function SurvivalGame.sv_e_setWarehouseRestrictions( self, params )
  704.     -- Set the restrictions for this warehouse and propagate the restrictions to all floors
  705.  
  706.     -- Warehouse get
  707.     local warehouse = nil
  708.     if params.warehouseIndex then
  709.         warehouse = self.warehouses[params.warehouseIndex]
  710.     end
  711.  
  712.     if warehouse then
  713.         for _, newRestrictionSetting in pairs( params.restrictions ) do
  714.             if warehouse.restrictions[newRestrictionSetting.name] then
  715.                 warehouse.restrictions[newRestrictionSetting.name].state = newRestrictionSetting.state
  716.             else
  717.                 warehouse.restrictions[newRestrictionSetting.name] = newRestrictionSetting
  718.             end
  719.         end
  720.         self.warehouses[params.warehouseIndex] = warehouse
  721.         self:sv_e_saveWarehouses()
  722.  
  723.         for i, world in ipairs( warehouse.worlds ) do
  724.             if sm.exists( world ) then
  725.                 sm.event.sendToWorld( world, "server_updateRestrictions", warehouse.restrictions )
  726.             end
  727.         end
  728.     end
  729. end
  730.  
  731. function SurvivalGame.sv_e_createElevatorDestination( self, params )
  732.     print( "SurvivalGame.sv_e_createElevatorDestination" )
  733.     print( params )
  734.  
  735.     -- Warehouse get or create
  736.     local warehouse
  737.     if params.warehouseIndex then
  738.         warehouse = self.warehouses[params.warehouseIndex]
  739.     else
  740.         assert( params.name == "ELEVATOR_ENTRANCE" )
  741.         warehouse = {}
  742.         warehouse.world = params.portal:getWorldA()
  743.         warehouse.worlds = {}
  744.         warehouse.exits = params.exits
  745.         warehouse.maxLevels = params.maxLevels
  746.         warehouse.index = #self.warehouses + 1
  747.         warehouse.restrictions = { erasable = { name = "erasable", state = false }, connectable = { name = "connectable", state = false } }
  748.         self.warehouses[#self.warehouses + 1] = warehouse
  749.         self:sv_e_saveWarehouses()
  750.     end
  751.  
  752.  
  753.     -- Level up
  754.     local level
  755.     if params.level then
  756.         if params.name == "ELEVATOR_UP" then
  757.             level = params.level + 1
  758.         elseif params.name == "ELEVATOR_DOWN" then
  759.             level = params.level - 1
  760.         elseif params.name == "ELEVATOR_EXIT" then
  761.             if #warehouse.exits > 0 then
  762.                 for _,cell in ipairs( warehouse.exits ) do
  763.                     if not sm.exists( warehouse.world ) then
  764.                         sm.world.loadWorld( warehouse.world )
  765.                     end
  766.                     local name = params.name.." "..cell.x..","..cell.y
  767.                     sm.portal.addWorldPortalHook( warehouse.world, name, params.portal )
  768.                     print( "Added portal hook '"..name.."' in world "..warehouse.world.id )
  769.  
  770.                     g_elevatorManager:sv_loadBForPlayersInElevator( params.portal, warehouse.world, cell.x, cell.y )
  771.                 end
  772.             else
  773.                 sm.log.error( "No exit hint found, this elevator is going nowhere!" )
  774.             end
  775.             return
  776.         else
  777.             assert( false )
  778.         end
  779.     else
  780.         if params.name == "ELEVATOR_EXIT" then
  781.             level = warehouse.maxLevels
  782.         elseif params.name == "ELEVATOR_ENTRANCE" then
  783.             level = 1
  784.         else
  785.         end
  786.     end
  787.  
  788.     -- Create warehouse world
  789.     local worldData = {}
  790.     worldData.level = level
  791.     worldData.warehouseIndex = warehouse.index
  792.     worldData.maxLevels = warehouse.maxLevels
  793.     local world = sm.world.createWorld( "$SURVIVAL_DATA/Scripts/game/worlds/WarehouseWorld.lua", "WarehouseWorld", worldData )
  794.     print( "Created WarehouseWorld "..world.id )
  795.  
  796.     -- Use the same restrictions for the new floor as the other floors
  797.     warehouse.worlds[#warehouse.worlds+1] = world
  798.     if warehouse.restrictions then
  799.         sm.event.sendToWorld( world, "server_updateRestrictions", warehouse.restrictions )
  800.     end
  801.     -- Elevator portal hook
  802.     local name
  803.     if params.name == "ELEVATOR_UP" then
  804.         name = "ELEVATOR_DOWN"
  805.     elseif params.name == "ELEVATOR_DOWN" then
  806.         name = "ELEVATOR_UP"
  807.     else
  808.         name = params.name
  809.     end
  810.     sm.portal.addWorldPortalHook( world, name, params.portal )
  811.     print( "Added portal hook '"..name.."' in world "..world.id )
  812.  
  813.     g_elevatorManager:sv_loadBForPlayersInElevator( params.portal, world, 0, 0 )
  814. end
  815.  
  816. function SurvivalGame.sv_e_elevatorEvent( self, params )
  817.     print( "SurvivalGame.sv_e_elevatorEvent" )
  818.     print( params )
  819.     g_elevatorManager[params.fn]( g_elevatorManager, params )
  820. end
  821.  
  822. function SurvivalGame.sv_createNewPlayer( self, world, x, y, player )
  823.     local params = { player = player, x = x, y = y }
  824.     sm.event.sendToWorld( self.sv.saved.overworld, "sv_spawnNewCharacter", params )
  825. end
  826.  
  827. function SurvivalGame.sv_recreatePlayerCharacter( self, world, x, y, player, params )
  828.     local yaw = math.atan2( params.dir.y, params.dir.x ) - math.pi/2
  829.     local pitch = math.asin( params.dir.z )
  830.     local newCharacter = sm.character.createCharacter( player, self.sv.saved.overworld, params.pos, yaw, pitch )
  831.     player:setCharacter( newCharacter )
  832.     print( "Recreate character in new world" )
  833.     print( params )
  834. end
  835.  
  836. function SurvivalGame.sv_e_respawn( self, params )
  837.     if params.player.character and sm.exists( params.player.character ) then
  838.         g_respawnManager:sv_requestRespawnCharacter( params.player )
  839.     else
  840.         local spawnPoint = START_AREA_SPAWN_POINT
  841.         if g_survivalDev then
  842.             spawnPoint = SURVIVAL_DEV_SPAWN_POINT
  843.         end
  844.         if not sm.exists( self.sv.saved.overworld ) then
  845.             sm.world.loadWorld( self.sv.saved.overworld )
  846.         end
  847.         self.sv.saved.overworld:loadCell( math.floor( spawnPoint.x/64 ), math.floor( spawnPoint.y/64 ), params.player, "sv_createNewPlayer" )
  848.     end
  849. end
  850.  
  851. function SurvivalGame.sv_loadedRespawnCell( self, world, x, y, player )
  852.     g_respawnManager:sv_respawnCharacter( player, world )
  853. end
  854.  
  855. function SurvivalGame.sv_e_onSpawnPlayerCharacter( self, player )
  856.     if player.character and sm.exists( player.character ) then
  857.         g_respawnManager:sv_onSpawnCharacter( player )
  858.         g_beaconManager:sv_onSpawnCharacter( player )
  859.     else
  860.         sm.log.warning("SurvivalGame.sv_e_onSpawnPlayerCharacter for a character that doesn't exist")
  861.     end
  862. end
  863.  
  864. function SurvivalGame.sv_e_markBag( self, params )
  865.     if sm.exists( params.world ) then
  866.         sm.event.sendToWorld( params.world, "sv_e_markBag", params )
  867.     else
  868.         sm.log.warning("SurvivalGame.sv_e_markBag in a world that doesn't exist")
  869.     end
  870. end
  871.  
  872. function SurvivalGame.sv_e_unmarkBag( self, params )
  873.     if sm.exists( params.world ) then
  874.         sm.event.sendToWorld( params.world, "sv_e_unmarkBag", params )
  875.     else
  876.         sm.log.warning("SurvivalGame.sv_e_unmarkBag in a world that doesn't exist")
  877.     end
  878. end
  879.  
  880. -- Beacons
  881. function SurvivalGame.sv_e_createBeacon( self, params )
  882.     if sm.exists( params.beacon.world ) then
  883.         sm.event.sendToWorld( params.beacon.world, "sv_e_createBeacon", params )
  884.     else
  885.         sm.log.warning( "SurvivalGame.sv_e_createBeacon in a world that doesn't exist" )
  886.     end
  887. end
  888.  
  889. function SurvivalGame.sv_e_destroyBeacon( self, params )
  890.     if sm.exists( params.beacon.world ) then
  891.         sm.event.sendToWorld( params.beacon.world, "sv_e_destroyBeacon", params )
  892.     else
  893.         sm.log.warning( "SurvivalGame.sv_e_destroyBeacon in a world that doesn't exist" )
  894.     end
  895. end
  896.  
  897. function SurvivalGame.sv_e_unloadBeacon( self, params )
  898.     if sm.exists( params.beacon.world ) then
  899.         sm.event.sendToWorld( params.beacon.world, "sv_e_unloadBeacon", params )
  900.     else
  901.         sm.log.warning( "SurvivalGame.sv_e_unloadBeacon in a world that doesn't exist" )
  902.     end
  903. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement