---------------------------------------------------------------- -- level specific Server script for Property Pushback in AG small property -- this script requires a base script -- this script should be in the zone script in the DB -- updated 6/18/10 added tutorial mission stuff -- updated mrb... 9/7/10 - added brickLinkMissionID -- updated abeechler... 7/25/11 - Spider Boss clean-up included in log-out calls ---------------------------------------------------------------- -------------------------------------------------------------- -- Includes -------------------------------------------------------------- require('zone/PROPERTY/L_BASE_PROPERTY_SERVER') --////////////////////////////////////////////////////////////////////////////////// -- User Config local variables local OwnerChecked = false local GUIDMaelstrom = "{7881e0a1-ef6d-420c-8040-f59994aa3357}" -- ambient sounds for when the Maelstrom is on local GUIDPeaceful = "{c5725665-58d0-465f-9e11-aeb1d21842ba}" -- happy ambient sounds when no maestrom is preset --GROUPS, set in Happy Flower on objects local Group = { Guard = "Guard", -- mission giver npc PropertyPlaque = "PropertyPlaque", -- make sure this matching the client script PropertyVendor = "PropertyVendor", -- the object the player actually rents the property from Land_Target = "Land_Target", Spider_Scream = "Spider_Scream", -- mountain emitter for Boss screaming ROF_Targets = {"ROF_Targets_00", "ROF_Targets_01", "ROF_Targets_02", "ROF_Targets_03", "ROF_Targets_04"}, -- the groups of Spider Boss attack targets SpiderEggs = "SpiderEggs", -- the smashable egg objects capable of hatching Dark Spiderlings Rocks = "Rocks", -- the smashable rock objects Enemies = "SpiderBoss", -- the Spider Boss AI instance ZoneVolumes = {"Zone1Vol", "Zone2Vol", "Zone3Vol", "Zone4Vol", "Zone5Vol", "Zone6Vol", "Zone7Vol", "Zone8Vol", "AggroVol", "TeleVol"}, --each group contains a single volume that handles zone sensing for the map's four quadrants FXManager = "FXObject" -- the hidden object underground (small yellow box) that controls all the env fx for the map } -- Spawner networks, set in happy flower local Spawners = { Enemy = "SpiderBoss", -- this can be as many spawner networks as necessary, but all spawner networks with enemies should be listed BossSensors = {"Zone1Vol", "Zone2Vol", "Zone3Vol", "Zone4Vol", "Zone5Vol", "Zone6Vol", "Zone7Vol", "Zone8Vol", "RFS_Targets", "AggroVol", "TeleVol"}, Land_Target = "Land_Target", Spider_Scream = "Spider_Scream", -- mountain emitter for Boss screaming ROF_Targets = {"ROF_Targets_00", "ROF_Targets_01", "ROF_Targets_02", "ROF_Targets_03", "ROF_Targets_04"}, -- the spawner network for the Spider Boss attack targets PropMG = "PropertyGuard", -- spawns the mission giver for this property FXManager = "FXObject", -- the hidden object underground (small yellow box) that controls all the env fx for the map PropObjs = "BankObj", -- spawns objects that player's can interact with once a property is claimed SpiderEggs = "SpiderEggs", -- the smashable egg objects capable of hatching Dark Spiderlings Rocks = "Rocks", -- the smashable rock objects SpiderRocket = { "SpiderRocket_Bot","SpiderRocket_Mid","SpiderRocket_Top" }, -- spawns the pieces of the Spider Boss entry rocket AmbientFX = { "BirdFX","SunBeam" } -- the ambient happy effects for the property, they are on by default and are turned off if maelstrom is spawned } -- Special spawner networks that differentiate the Property versus the Instance local PropertySpawners = { Mailbox = "Mailbox", -- property mailbox Launcher = "Launcher" -- property launcher } local InstanceSpawners = { Instancer = "Instancer" -- instance interact } -- player flags. These have to be different for each property map. these are set up in the db local flags = { defeatedProperty = 71, -- when the player builds the claim marker, this flag is set placedModel = 73, -- when a player places a model for the first time, this flag is set guardFirstMission = 891, -- make sure the player has started the guards first mission, workaround for 1.9 guardMission = 320, -- last mission for the guard password = "s3kratK1ttN", -- behavior password build qb object with behaviors brickLinkMissionID = 951 -- Achievement ID to complete on property rental } local destroyedCinematic = "DestroyMaelstrom" -- What to play when we clear the property ---------------------------------------------------------------- -- leave the functions below alone ---------------------------------------------------------------- ---------------------------------------------------------------- -- Called when the player fully loads into the map, passes the variables set above, -- Sets up the map for maelstrom if the player has not defeated this map before ---------------------------------------------------------------- function onPlayerLoaded(self, msg) if OwnerChecked == false then -- only check for owner when the first player enters property checkForOwner(self) end local propertyOwner = self:GetVar("PropertyOwner") -- returns true or false if the property is rented or not local rented = false if propertyOwner ~= 0 then rented = true end self:SetVar("rented", rented) if(not rented) then -- establish a player table (if one doesn't exist), and add the loaded -- player's ID to it local playerTable = self:GetVar("PlayerTable") or {} local player = msg.playerID local playerID = player:GetID() table.insert(playerTable, playerID) self:SetVar("PlayerTable", playerTable) -- establish a player count (if one doesn't exist) and maintain accordingly local numPlayers = self:GetVar("numberOfPlayers") or 0 numPlayers = numPlayers + 1 self:SetVar("numberOfPlayers", numPlayers) end basePlayerLoaded(self,msg,newMsg) end ---------------------------------------------------------------- -- Utility function used to determine whether to spawn the -- Property Guard based on mission status ---------------------------------------------------------------- function propGuardCheck(self, msg) -- mission state local mState = msg.playerID:GetMissionState{missionID = flags.guardMission}.missionState local firstMState = msg.playerID:GetMissionState{missionID = flags.guardFirstMission}.missionState -- do we meet the requirements? if (firstMState < 8) or ((mState ~= 8) and (mState ~= 4)) then ActivateSpawner(self,Spawners.PropMG) -- spawn guard end end ---------------------------------------------------------------- -- leave the functions below alone ---------------------------------------------------------------- function onZoneLoadedInfo(self, msg) loadProperty(self) end function loadInstance(self) setGameVariables(Group,Spawners,flags) -- spawn instance only objects ActivateSpawner(self, InstanceSpawners.Instancer) end function loadProperty(self) setGameVariables(Group,Spawners,flags) -- remove unwanted objects ActivateSpawner(self, PropertySpawners.Launcher) ActivateSpawner(self, PropertySpawners.Mailbox) end ---------------------------------------------------------------- -- Adds Spider Boss property specific functionality to AG Small ---------------------------------------------------------------- function onFireEvent(self, msg) baseOnFireEvent(self, msg) end function baseOnFireEvent(self, msg) -- Receive the sending object ID and the message to parse local eventType = msg.args local sendObj = msg.senderID -- Missing a valid event type? if not eventType then return end if eventType == "RetrieveZoneData" then -- Establish a script hook to the Spider Boss self:SetVar("SpiderBossID", sendObj) -- Establish a network variable for objects to use -- to retrieve information about the spider egg network sendObj:SetVar("SpiderEggNetworkID", RetrieveSpawnerID(self, Spawners.SpiderEggs)) -- Establish a network variable for objects to use -- to retrieve information about the Rain Of Fire targets local ROFTargetGroupTable = {} -- Build an ID table for Target Groups for i, nom in ipairs(Spawners.ROF_Targets) do table.insert(ROFTargetGroupTable, RetrieveSpawnerID(self, Spawners.ROF_Targets[i])) end sendObj:SetVar("ROFTargetGroupIDTable", ROFTargetGroupTable) -- Establish a variable for objects casting the landing attack processGroupObjects(self, Group.Land_Target) -- Establish a variable for object emitting the Spider Scream processGroupObjects(self, Group.Spider_Scream) -- Process zone volumes for proper object notifications processGroupObjects(self, Group.ZoneVolumes) elseif eventType == "CheckForPropertyOwner" then -- An object has queried us for the ID of the property owner, -- return it to the sender local propertyOwner = self:GetVar("PropertyOwner") or 0 sendObj:SetNetworkVar("PropertyOwnerID", propertyOwner) elseif eventType == "ClearProperty" then -- Initiate the chain of events that process the conversion of -- the Player property local player = GAMEOBJ:GetObjectByID(self:GetVar("playerID")) -- Start the camera that shows the maelstrom dying GAMEOBJ:GetZoneControlID():NotifyClientObject{name = "PlayCinematic", paramStr = destroyedCinematic} player:SetFlag{iFlagID = flags.defeatedProperty, bFlag=true} -- Start the timer for the next phase GAMEOBJ:GetTimer():AddTimerWithCancel( 0.5, "tornadoOff", self ) end end ---------------------------------------------------------------- -- Utility function useful for group object processing ---------------------------------------------------------------- function processGroupObjects(self, group) -- We are process group objects for the Spider Boss to reference, -- obtain a handle to her local spiderBossID = self:GetVar("SpiderBossID") if(type(group) == "table") then -- Process table data according to identity if(group == Group.ZoneVolumes) then -- Loop through the zone volume group table and obtain a handle -- to each for j, groupNom in ipairs(group) do -- Iterate through the destination group and catch the first valid destination object local zoneVol = self:GetObjectsInGroup{group = groupNom, ignoreSpawners = true}.objects -- Ensure we actually executed a check local checkExecuted = false for k, obj in ipairs(zoneVol) do local exists = obj:Exists() if exists then checkExecuted = true -- Subscribe for collision events spiderBossID:SendLuaNotificationRequest{requestTarget=obj, messageName="CollisionPhantom"} -- If we are at the AggoVol obj, subscribe for an off-collision event if(groupNom == "AggroVol") then spiderBossID:SendLuaNotificationRequest{requestTarget=obj, messageName="OffCollisionPhantom"} spiderBossID:SetVar("AggroVol", obj) end break end end -- Ensure iterative execution if(not checkExecuted) then GAMEOBJ:GetTimer():AddTimerWithCancel(0.3 , "ProcessGroupObj_ZoneVolumes", self) break end end end else -- Process singular group data according to identity -- Determine through group name the variable we are setting local setVarNom = group if(group == Group.Land_Target) then setVarNom = "LandingTarget" elseif(group == Group.Spider_Scream) then setVarNom = "ScreamEmitter" end -- Obtain the objects within the desired group local groupObjects = self:GetObjectsInGroup{group = group, ignoreSpawners = true}.objects -- Ensure we actually executed a check local checkExecuted = false -- Iterate through the objects and process for the first entity for k, obj in ipairs(groupObjects) do local exists = obj:Exists() if exists then checkExecuted = true -- Store the reference spiderBossID:SetVar(setVarNom, obj) break end end -- Ensure iterative execution if(not checkExecuted) then GAMEOBJ:GetTimer():AddTimerWithCancel(0.3 , "ProcessGroupObj_" .. setVarNom, self) end end end ---------------------------------------------------------------- -- activates the spawner for the maelstrom spots ---------------------------------------------------------------- function SpawnSpots(self) -- activate all the ROF Targets for k,v in ipairs(Spawners.ROF_Targets) do ActivateSpawner(self, v) end -- activate the landing target ActivateSpawner(self, Spawners.Land_Target) end ---------------------------------------------------------------- -- deactive the spawner for the maelstrom spots and then delete them ---------------------------------------------------------------- function KillSpots(self) -- deactivate all the ROF Targets for k,v in ipairs(Spawners.ROF_Targets) do DeactivateSpawner(self,v) end for j,u in ipairs(Group.ROF_Targets) do local spots = self:GetObjectsInGroup{group = u, ignoreSpawners = true}.objects ObjectRequestDie(self,spots) end -- deactivate the land target DeactivateSpawner(self, Spawners.Land_Target) local trgt = self:GetObjectsInGroup{group = Spawners.Land_Target, ignoreSpawners = true}.objects ObjectRequestDie(self, trgt) end ---------------------------------------------------------------- -- activates the spawner for the Spider Boss crashed rocket ---------------------------------------------------------------- function SpawnCrashedRocket(self) -- activate all the rocket crash parts for k,v in ipairs(Spawners.SpiderRocket) do ActivateSpawner(self, v) end end ---------------------------------------------------------------- -- deactives the spawners for the Spider Boss crashed rocket and -- then delete them ---------------------------------------------------------------- function KillCrashedRocket(self) -- deactivate all the rocket crash parts for k,v in ipairs(Spawners.SpiderRocket) do DeactivateSpawner(self,v) DestroySpawner(self,v) end end ---------------------------------------------------------------- -- turns all the maelstrom on if the player hasn't defeated the maelstrom for this property yet ---------------------------------------------------------------- function StartMaelstrom(self,player) -- activate the Spider Boss spawner and build all the necessary sensor objects ActivateSpawner(self, Spawners.Enemy) for k,v in ipairs(Spawners.BossSensors) do ActivateSpawner(self, v) end if Spawners.BehaviorObjs then for k,v in ipairs(Spawners.BehaviorObjs) do ActivateSpawner(self,v) end end -- activate the spawner for the fx ActivateSpawner(self,Spawners.FXManager) -- activate the spawner for the mountain emitter ActivateSpawner(self,Spawners.Spider_Scream) -- activate the spawner for the eggs ActivateSpawner(self,Spawners.SpiderEggs) -- activate the spawner for the rocks ActivateSpawner(self,Spawners.Rocks) -- activate the rocket crash parts SpawnCrashedRocket(self) if Spawners.AmbientFX then for k,v in ipairs(Spawners.AmbientFX) do DeactivateSpawner(self,v) DestroySpawner(self,v) ResetSpawner(self,v) end end startTornadoFX(self) -- notify the client to change the env settings self:NotifyClientObject{ name = "maelstromSkyOn", rerouteID = player } end ---------------------------------------------------------------- -- ---------------------------------------------------------------- function baseNotifyCollisionPhantom(self,other,msg) -- This function is included to ensure the functionality -- found for this in the base script is properly cleared -- out to ensure there are no errors on accidental execution end ---------------------------------------------------------------- -- retrieve spawner ID ---------------------------------------------------------------- function RetrieveSpawnerID(self,spawnerName) local spawnerID = LEVEL:GetSpawnerByName(spawnerName) if spawnerID then return spawnerID else WarningPrint(self,'WARNING: No Spawner found for spawner named ' .. spawnerName) end end ---------------------------------------------------------------- -- called when a timer is done ---------------------------------------------------------------- function baseTimerDone(self,msg) if msg.name == "GuardFlyAway" then -- the guard is "flying" away, delete him and turn the boundry animation on if LEVEL:GetCurrentZoneID() ~= 1150 then local GuardObjs = self:GetObjectsInGroup{ group = Group.Guard, ignoreSpawners = true }.objects local Guard = false -- Iterate through the group and catch the first valid object for k,obj in ipairs(GuardObjs) do if obj:Exists() then Guard = obj break end end GAMEOBJ:GetZoneControlID():NotifyClientObject{ name = "GuardChat", paramObj = Guard } GAMEOBJ:GetTimer():AddTimerWithCancel( 5, "KillGuard", self ) end -- tell the client script to play the animation on the boundry asset elseif msg.name == "KillGuard" then KillGuard(self) elseif msg.name == "tornadoOff" then -- finds the fx manager local fxObjs = self:GetObjectsInGroup{group = Group.FXManager, ignoreSpawners = true}.objects local fx = false -- Iterate through the group and catch the first valid object for k,obj in ipairs(fxObjs) do if obj:Exists() then fx = obj break end end -- turn the tornado and vortex fx off if fx then fx:StopFXEffect{name = "TornadoDebris"} fx:StopFXEffect{name = "TornadoVortex"} fx:StopFXEffect{name = "silhouette"} else WarningPrint(self,"Warning: No object found in the group "..Group.FXManager) end GAMEOBJ:GetTimer():AddTimerWithCancel( 1.2, "ShowVendor", self ) GAMEOBJ:GetTimer():AddTimerWithCancel( 2, "ShowClearEffects", self ) elseif msg.name == "ShowClearEffects" then -- finds the fx manager local fxObjs = self:GetObjectsInGroup{group = Group.FXManager, ignoreSpawners = true}.objects local fx = false -- Iterate through the group and catch the first valid object for k,obj in ipairs(fxObjs) do if obj:Exists() then fx = obj break end end -- play the light in the center of the property to show the maelstrom being defeated if fx then fx:PlayFXEffect{name = "beam", effectType = "beamOn"} else WarningPrint(self,"Warning: No object found in the group "..Group.FXManager) end GAMEOBJ:GetTimer():AddTimerWithCancel( 2, "killSpider", self ) GAMEOBJ:GetTimer():AddTimerWithCancel( 1.5, "turnSkyOff", self ) GAMEOBJ:GetTimer():AddTimerWithCancel( 8, "killFXObject", self ) elseif msg.name == "turnSkyOff" then self:NotifyClientObject{ name = "SkyOff" } elseif msg.name == "killSpider" then -- kill all the enemies local enemies = self:GetObjectsInGroup{group = Group.Enemies}.objects ObjectRequestDie(self,enemies) for k,v in ipairs(Spawners.BossSensors) do DeactivateSpawner(self,v) DestroySpawner(self,v) end -- clean the arena DeactivateSpawner(self,Spawners.SpiderEggs) DestroySpawner(self,Spawners.SpiderEggs) DeactivateSpawner(self,Spawners.Rocks) DestroySpawner(self,Spawners.Rocks) KillSpots(self) KillCrashedRocket(self) -- deactivate the spawner for the mountain emitter DeactivateSpawner(self,Spawners.Spider_Scream) DestroySpawner(self,Spawners.Spider_Scream) local playerTable = self:GetVar("PlayerTable") or {} -- iterate through the table and find the exiting player for i, pID in ipairs(playerTable) do local player = GAMEOBJ:GetObjectByID(pID) player:Stop2DAmbientSound{m_NDAudioEventGUID = GUIDMaelstrom } -- kill the maelstrom windy sound player:Play2DAmbientSound{m_NDAudioEventGUID = GUIDPeaceful}-- start the happy bird sounds end elseif msg.name == "ShowVendor" then -- tell the client script to show the vendor GAMEOBJ:GetZoneControlID():NotifyClientObject{ name = "vendorOn" } if Spawners.AmbientFX then for k,v in ipairs(Spawners.AmbientFX) do ActivateSpawner(self,v) end end elseif msg.name == "BoundsVisOn" then -- tell the client script to turn the boundry on --GAMEOBJ:GetZoneControlID():NotifyClientObject{name = "boundsOn" } GAMEOBJ:GetZoneControlID():NotifyClientObject{name = "boundsAnim" } elseif msg.name == "runPlayerLoadedAgain" then checkForOwner(self) elseif msg.name == "pollTornadoFX" then startTornadoFX(self) elseif msg.name == "killFXObject" then local fxObjs = self:GetObjectsInGroup{group = Group.FXManager, ignoreSpawners = true}.objects local fx = false -- Iterate through the group and catch the first valid object for k,obj in ipairs(fxObjs) do if obj:Exists() then fx = obj break end end --stop the light fx if fx then fx:StopFXEffect{name = "beam"} -- kill the fx object DestroySpawner(self,Spawners.FXManager) self:SetVar("FXObjectGone", true) else WarningPrint(self,"Warning: No object found in the group "..Group.FXManager) GAMEOBJ:GetTimer():AddTimerWithCancel( 1, "killFXObject", self ) end elseif startsWith(msg.name, "ProcessGroupObj") then local processNom = split(msg.name, "_")[2] if(processNom == "LandingTarget") then processGroupObjects(self, Group.Land_Target) elseif(processNom == "ScreamEmitter") then processGroupObjects(self, Group.Spider_Scream) elseif(processNom == "ZoneVolumes") then processGroupObjects(self, Group.ZoneVolumes) end end end ---------------------------------------------------------------- -- called when the player rents a zone, turns on the property border ---------------------------------------------------------------- function onZonePropertyRented(self, msg) baseZonePropertyRented(self,msg,newMsg) if msg.playerID:GetFlag{iFlagID = 108}.bFlag == false then msg.playerID:SetFlag{iFlagID = 108, bFlag = true} end end ---------------------------------------------------------------- -- called when the player places a model ---------------------------------------------------------------- function onZonePropertyModelPlaced(self, msg) local player = msg.playerID --the player placed their first model, set the flag to true if player:GetFlag{iFlagID = 101}.bFlag == false then baseZonePropertyModelPlaced(self,msg,newMsg) --it turns off the spots and sets a player flag player:SetFlag{iFlagID = 101, bFlag = true} -- if they are one the place 4 models mission, update the tutorial if player:GetMissionState{missionID = 871}.missionState == 2 then self:SetNetworkVar("Tooltip","AnotherModel") end -- the player placed a second model, set the flag elseif player:GetFlag{iFlagID = 102}.bFlag == false then player:SetFlag{iFlagID = 102, bFlag = true} -- if they are one the place 4 models mission, update the tutorial if player:GetMissionState{missionID = 871}.missionState == 2 then self:SetNetworkVar("Tooltip","TwoMoreModels") end -- the player placed a third model, set the flag elseif player:GetFlag{iFlagID = 103}.bFlag == false then player:SetFlag{iFlagID = 103, bFlag = true} -- the player placed a third model, set the flag elseif player:GetFlag{iFlagID = 104}.bFlag == false then --tell the client to close a tooltip, if it isnt open, it shouldnt do anything self:SetNetworkVar("Tooltip","TwoMoreModelsOff") player:SetFlag{iFlagID = 104, bFlag = true} --the player has a tooltip telling them to place a model, which they just placed, so it needs to close it elseif self:GetVar("tutorial") == "placeModel" then self:SetVar("tutorial","TutorialOver") self:SetNetworkVar("Tooltip","PutAway") end end ---------------------------------------------------------------- -- called when the player picks up a model ---------------------------------------------------------------- function onZonePropertyModelPickedUp(self, msg) local player = msg.playerID -- first time the player picked up a model, set their flag if player:GetFlag{iFlagID = 109}.bFlag == false then player:SetFlag{iFlagID = 109, bFlag = true} -- if they are on the mission to pick up a model, update the tutorial if player:GetMissionState{missionID = 891}.missionState == 2 then self:SetNetworkVar("Tooltip","Rotate") end end -- if the player has already picked up a model, is on the mission, but hasnt rotated a model, update the tutorial if player:GetFlag{iFlagID = 110}.bFlag == false and player:GetMissionState{missionID = 891}.missionState == 2 then self:SetNetworkVar("Tooltip","Rotate") -- if the player is on the mission, but has done the other to parts, then just turn the tooltip off elseif player:GetMissionState{missionID = 891}.missionState == 2 then self:SetNetworkVar("Tooltip","PickUpModelOff") end end ---------------------------------------------------------------- -- called when the player removes a model from their property ---------------------------------------------------------------- function onZonePropertyModelRemoved(self, msg) local player = msg.playerID -- if this is the first time they have done it, set a flag if player:GetFlag{iFlagID = 111}.bFlag == false then player:SetFlag{iFlagID = 111, bFlag = true} end end ---------------------------------------------------------------- -- called when the player removes a model from their property while its equipped ---------------------------------------------------------------- function onZonePropertyModelRemovedWhileEquipped(self, msg) local player = msg.playerID -- if this is the first time they have done it, set a flag if player:GetFlag{iFlagID = 111}.bFlag == false then player:SetFlag{iFlagID = 111, bFlag = true} end end ---------------------------------------------------------------- -- called when the player enters property edit mode ---------------------------------------------------------------- function onZonePropertyEditBegin(self, msg) -- tell the client the player entered edit mode self:SetNetworkVar("PlayerAction","Enter") end ---------------------------------------------------------------- -- called when the player equips a model ---------------------------------------------------------------- function onZonePropertyModelEquipped(self,msg) -- tell the client the player equipped a model self:SetNetworkVar("PlayerAction","ModelEquipped") end ---------------------------------------------------------------- -- called when the player rotates a model ---------------------------------------------------------------- function onZonePropertyModelRotated(self,msg) local player = msg.playerID -- if the player hasnt rotated a model before, set a flag if player:GetFlag{iFlagID = 110}.bFlag == false then player:SetFlag{iFlagID = 110, bFlag = true} -- if they are on the mission to rotate a model, update the tutorial if player:GetMissionState{missionID = 891}.missionState == 2 then self:SetNetworkVar("Tooltip","PlaceModel") -- used in pickupmodel to close the tooltip self:SetVar("tutorial","placeModel") end end end ---------------------------------------------------------------- -- called when the player leaves property edit mode ---------------------------------------------------------------- function onZonePropertyEditEnd(self, msg) self:SetNetworkVar("PlayerAction","Exit") end ---------------------------------------------------------------- -- called from the generator object when they die ---------------------------------------------------------------- function notifyDie(self,other,msg) baseNotifyDie(self,other,msg) end ------------------------------------------------------- -- called when a player exits the zone ---------------------------------------------------------------- function onPlayerExit(self,msg) local rented = self:GetVar("rented") if(not rented) then removePlayerRef(self, msg) local numPlayers = self:GetVar("numberOfPlayers") or 0 if(numPlayers == 0) then -- Clean up any spawned Spiderlings local spiderBoss = self:GetVar("SpiderBossID") spiderBoss:FireEvent{args = "CleanupSpiders"} -- Reset the Spider Boss network DeactivateSpawner(self,Spawners.Enemy) DestroySpawner(self,Spawners.Enemy) ResetSpawner(self,Spawners.Enemy) -- Finalize zone reset basePlayerExit(self,other,msg) end else basePlayerExit(self,other,msg) end end ---------------------------------------------------------------- -- utility function handling the process of player removal ---------------------------------------------------------------- function removePlayerRef(self, msg) -- maintain the player count local numPlayers = self:GetVar("numberOfPlayers") or 0 numPlayers = numPlayers - 1 self:SetVar("numberOfPlayers", numPlayers) -- update player table local playerTable = self:GetVar("PlayerTable") or {} local player = msg.playerID local playerID = player:GetID() -- iterate through the table and find the exiting player for i, pID in ipairs(playerTable) do if(pID == playerID) then -- remove the exiting player from the table table.remove(playerTable, i) break end end self:SetVar("PlayerTable", playerTable) end ---------------------------------------------------------------- -- called from the orb when something collides with it ---------------------------------------------------------------- function notifyCollisionPhantom(self,other,msg) baseNotifyCollisionPhantom(self,other,msg) end ---------------------------------------------------------------- -- called from the quickbuild behavior model when its done rebuilding ---------------------------------------------------------------- function notifyRebuildComplete(self,other,msg) baseNotifyRebuildComplete(self,other,msg) end ---------------------------------------------------------------- -- called when notify object message is recieved ---------------------------------------------------------------- function onNotifyObject(self,msg) -- send from the guard when the player accepts the mission to rotate, pick up and put away if msg.name == "LastMissionAccepted" then local player = msg.ObjIDSender --check to see if the player already did all the stuff in the tutorial, then skip it if player:GetMissionState{missionID = 891}.missionState ~= 4 then self:SetNetworkVar("Tooltip","ThinkingHat") end end end ---------------------------------------------------------------- -- called when timers are done ---------------------------------------------------------------- function onTimerDone(self,msg) baseTimerDone(self,msg,newMsg) end ---------------------------------------------- -- Splits a string based on the pattern passed in ---------------------------------------------- function split(str, pat) local t = {} -- creates a table of strings based on the passed in pattern string.gsub(str .. pat, "(.-)" .. pat, function(result) table.insert(t, result) end) return t end ---------------------------------------------- -- Parses strings for token identification ---------------------------------------------- function startsWith(String,Start) -- finds if a string starts with a giving string. return string.sub(String,1,string.len(Start))==Start end