-- f1 farm gameplay logic (SQL-backed state) -- Keeps existing creature IDs, item IDs, and message IDs. local function _script_dir() local src = debug.getinfo(1, "S").source if type(src) ~= "string" then return "" end if src:sub(1, 1) == "@" then src = src:sub(2) end src = src:gsub("\\", "/") local dir = src:match("^(.*)/") if dir == nil then return "" end return dir .. "/" end local function _dofile_rel(name) return dofile(_script_dir() .. name) end local role_store = _dofile_rel("f1_role_store.lua") local plot_store = _dofile_rel("f1_plot_store.lua") local map_def = _dofile_rel("f1_mappings.lua") local world_restore = _dofile_rel("f1_world_restore.lua") local M = {} local function _now() return os.time() end local function _msg_simple(RoleID, textMsgId) local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 1) msg.AddMsgEvent(MsgID, 1, textMsgId) msg.DispatchRoleMsgEvent(RoleID, MsgID) end local function _get_role(RoleID) if role_store.schemaReady() then return role_store.getRole(RoleID) or { usadbLevelRaw = 0, usadbExp = 0, usadbEnter = 0 } end return role_store.legacyGet(RoleID) end local function _set_role(RoleID, patch) if role_store.schemaReady() then return role_store.setRole(RoleID, patch) end return role_store.legacySet(RoleID, patch) end local function _ensure_farm_role(RoleID) if role_store.schemaReady() then role_store.ensureRole(RoleID) end local r = _get_role(RoleID) local zero = r.usadbLevelRaw or 0 local farmlevel = zero % 10 if farmlevel == 0 then zero = zero + 1 farmlevel = 1 _set_role(RoleID, { usadbLevelRaw = zero }) r.usadbLevelRaw = zero end return r end local function _get_plot(MapID, InstanceID, x, y, z) if not plot_store.schemaReady() then return nil end return plot_store.getPlot(MapID, InstanceID, x, y, z) end local function _set_plot(MapID, InstanceID, x, y, z, patch) if not plot_store.schemaReady() then return false end return plot_store.setPlot(MapID, InstanceID, x, y, z, patch) end local function _get_pos(MapID, InstanceID, TargetID) local x, y, z = unit.GetPosition(MapID, InstanceID, TargetID) return x, y, z end local function _expected_type_for_plot(plot, currentTypeId) if plot == nil then return currentTypeId end if plot.Stage == map_def.STAGE_MOUND then return map_def.MOUND_BASIC end local def = map_def.plants[plot.PlantId] if def == nil then return currentTypeId end if plot.Stage == map_def.STAGE_SEED then return def.seed elseif plot.Stage == map_def.STAGE_SEEDLING then return def.seedling elseif plot.Stage == map_def.STAGE_HARVEST then return def.harvest end return currentTypeId end local function _replace_creature_if_needed(MapID, InstanceID, TargetID, TargetTypeID, x, y, z, expectedTypeId) if expectedTypeId == nil or expectedTypeId == 0 or expectedTypeId == TargetTypeID then return TargetID, TargetTypeID end map.MapDeleteCreature(MapID, InstanceID, TargetID) local newId = map.MapCreateCreature(MapID, InstanceID, expectedTypeId, x, y, z) return newId, expectedTypeId end -- Sync: update stage by time (DB) and ensure the world object matches. function M.syncPlotFromDB(MapID, InstanceID, TargetID, TargetTypeID) local x, y, z = _get_pos(MapID, InstanceID, TargetID) if not plot_store.schemaReady() then return TargetID, TargetTypeID, nil, x, y, z end local plot = _get_plot(MapID, InstanceID, x, y, z) if plot == nil then return TargetID, TargetTypeID, nil, x, y, z end local now = _now() if plot.Stage == map_def.STAGE_SEEDLING and plot.StageStartTime > 0 then local def = map_def.plants[plot.PlantId] if def ~= nil and def.growSeconds ~= nil then if (now - plot.StageStartTime) >= def.growSeconds then _set_plot(MapID, InstanceID, x, y, z, { Stage = map_def.STAGE_HARVEST, StageStartTime = 0 }) plot.Stage = map_def.STAGE_HARVEST plot.StageStartTime = 0 end end end local expected = _expected_type_for_plot(plot, TargetTypeID) local newId, newType = _replace_creature_if_needed(MapID, InstanceID, TargetID, TargetTypeID, x, y, z, expected) return newId, newType, plot, x, y, z end local function _cooldown_ok(plot, RoleID, now) local owner = (plot and plot.OwnerRoleID) or 0 local last = (plot and plot.LastPlotTime) or 0 local elapsed = (last == 0) and map_def.COOLDOWN_SECONDS or os.difftime(now, last) return elapsed >= map_def.COOLDOWN_SECONDS or owner ~= RoleID end local function _award_farm_exp(RoleID, addExp) local r = _ensure_farm_role(RoleID) local zero = r.usadbLevelRaw or 0 local farmlevel = zero % 10 local farmexp = r.usadbExp or 0 if farmlevel >= 9 then _msg_simple(RoleID, 420033) return end local inc = map_def.harvest_exp[addExp] or 0 farmexp = farmexp + inc _set_role(RoleID, { usadbExp = farmexp }) local ex = (map_def.farm_exp[farmlevel] or 0) - farmexp local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 1) msg.AddMsgEvent(MsgID, 1, 420032) msg.AddMsgEvent(MsgID, 9, farmexp) msg.AddMsgEvent(MsgID, 9, ex) msg.DispatchRoleMsgEvent(RoleID, MsgID) end function M.onPlayerEnter(MapID, InstanceID, RoleID) _ensure_farm_role(RoleID) local r = _get_role(RoleID) if (r.usadbEnter or 0) == 0 then _set_role(RoleID, { usadbLevelRaw = 0, usadbExp = 0, usadbEnter = 1 }) r = _get_role(RoleID) end local farmexp = r.usadbExp or 0 if farmexp >= 0 then local mount = map.MapCreateCreature(MapID, InstanceID, 5800121, 146, 1634, 86) map.SetMapScriptData(MapID, InstanceID, 1, 1, mount) end if farmexp >= 58790 then local mount = map.GetMapScriptData(MapID, InstanceID, 1, 1) if mount ~= nil and mount ~= 0 then map.MapDeleteCreature(MapID, InstanceID, mount) end local mount2 = map.MapCreateCreature(MapID, InstanceID, 5800122, 146, 1634, 86) map.SetMapScriptData(MapID, InstanceID, 1, 1, mount2) end if farmexp >= 274790 then local mount = map.GetMapScriptData(MapID, InstanceID, 1, 1) if mount ~= nil and mount ~= 0 then map.MapDeleteCreature(MapID, InstanceID, mount) end local mount3 = map.MapCreateCreature(MapID, InstanceID, 5800123, 146, 1634, 86) map.SetMapScriptData(MapID, InstanceID, 1, 1, mount3) end end function M.onPlayerLeave(MapID, InstanceID, RoleID) local mount = map.GetMapScriptData(MapID, InstanceID, 1, 1) if mount ~= nil and mount ~= 0 then map.MapDeleteCreature(MapID, InstanceID, mount) end end function M.onInit(MapID, InstanceID, CreatureID, CreatureTypeID) -- Restore farm world objects (plots + pet holes/pets) from SQL on instance init. if world_restore ~= nil and world_restore.onInit ~= nil then world_restore.onInit(MapID, InstanceID, CreatureID, CreatureTypeID) end end function M.onRoleEnterArea(MapID, InstanceID, RoleID, ObjAreaID) if ObjAreaID == 705 then role.RoleGotoNewMap(MapID, InstanceID, RoleID, 3424073512, 610, 23094, 669) end end function M.s7000011_Use(MapID, InstanceID, TypeID, RoleID) local r = _ensure_farm_role(RoleID) local zero = r.usadbLevelRaw or 0 local farmlevel = zero % 10 local farmexp = r.usadbExp or 0 if farmlevel < 9 then farmexp = farmexp + 10 if farmexp >= (map_def.farm_exp[farmlevel] or 0) then farmexp = farmexp - (map_def.farm_exp[farmlevel] or 0) zero = zero + 1 farmlevel = farmlevel + 1 _set_role(RoleID, { usadbLevelRaw = zero, usadbExp = farmexp }) local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 1) msg.AddMsgEvent(MsgID, 1, 420031) msg.AddMsgEvent(MsgID, 9, farmlevel) msg.DispatchRoleMsgEvent(RoleID, MsgID) else _set_role(RoleID, { usadbExp = farmexp }) local ex = (map_def.farm_exp[farmlevel] or 0) - farmexp local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 1) msg.AddMsgEvent(MsgID, 1, 420032) msg.AddMsgEvent(MsgID, 9, farmexp) msg.AddMsgEvent(MsgID, 9, ex) msg.DispatchRoleMsgEvent(RoleID, MsgID) end else _msg_simple(RoleID, 420033) end end function M.c5800091_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) if TalkIndex == -1 then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420075) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 21, 4) msg.AddMsgEvent(MsgID, 1, 930431) msg.AddMsgEvent(MsgID, 21, 5) msg.AddMsgEvent(MsgID, 1, 100002) msg.DispatchRoleMsgEvent(RoleID, MsgID) elseif TalkIndex == 4 then map.CreateInstance(1711288576, RoleID) role.RoleGotoNewMap(MapID, InstanceID, RoleID, 1711288576, 291, 1000, 109) end end function M.c6020002_OnInvest(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) role.AddRoleItem(MapID, InstanceID, RoleID, 4100007, 5, 6, 8, 102) end function M.f1_GetOnePerfectMap(MapID, InstanceID, RoleID) return RoleID end function M.f1_CanEnterWhenOnline(MapID, RoleID) return 3424073512, 610, 23094, 669 end function M.f1_GetExporMapAndCoord(MapID, InstanceID, RoleID) return 1, 3424073512, 610, 23094, 669 end function M.f1_CanEnter(MapID, InstanceID, RoleID) return 1 end function M.c5800090_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) local num = role.GetRoleItemNum(RoleID, 6601172) local r = _ensure_farm_role(RoleID) local zero = r.usadbLevelRaw or 0 local farmlevel = zero % 10 local farmexp = r.usadbExp or 0 local need = (map_def.farm_exp[farmlevel] or 0) - farmexp if TalkIndex == -1 then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420074) msg.AddMsgEvent(MsgID, 9, farmlevel) msg.AddMsgEvent(MsgID, 9, need) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 21, 4) msg.AddMsgEvent(MsgID, 1, 420075) msg.AddMsgEvent(MsgID, 21, 5) msg.AddMsgEvent(MsgID, 1, 420009) msg.DispatchRoleMsgEvent(RoleID, MsgID) return end if TalkIndex ~= 4 then return end if farmexp < (map_def.farm_exp[farmlevel] or 0) then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420089) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 21, 5) msg.AddMsgEvent(MsgID, 1, 420009) msg.DispatchRoleMsgEvent(RoleID, MsgID) return end if farmlevel >= 9 then _msg_simple(RoleID, 420033) return end local required = 10 + (farmlevel - 1) * 15 if num < required then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420076) msg.AddMsgEvent(MsgID, 9, required) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 21, 5) msg.AddMsgEvent(MsgID, 1, 420009) msg.DispatchRoleMsgEvent(RoleID, MsgID) return end role.RemoveFromRole(MapID, InstanceID, RoleID, 6601172, required, 420) farmexp = farmexp - (map_def.farm_exp[farmlevel] or 0) zero = zero + 1 farmlevel = farmlevel + 1 _set_role(RoleID, { usadbLevelRaw = zero, usadbExp = farmexp }) local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 1) msg.AddMsgEvent(MsgID, 1, 420031) msg.AddMsgEvent(MsgID, 9, farmlevel) msg.DispatchRoleMsgEvent(RoleID, MsgID) end function M.mound_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) local plot, x, y, z TargetID, TargetTypeID, plot, x, y, z = M.syncPlotFromDB(MapID, InstanceID, TargetID, TargetTypeID) local now = _now() _ensure_farm_role(RoleID) if plot ~= nil and plot.Stage ~= map_def.STAGE_MOUND then if plot.Stage == map_def.STAGE_SEED then return M.seed_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) elseif plot.Stage == map_def.STAGE_SEEDLING then return M.seedling_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) elseif plot.Stage == map_def.STAGE_HARVEST then return M.harvest_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) end end local plot0 = _get_plot(MapID, InstanceID, x, y, z) or { PlantId = 0, Stage = map_def.STAGE_MOUND, OwnerRoleID = 0, LastPlotTime = 0, } if TalkIndex == -1 then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420001) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 21, 11) msg.AddMsgEvent(MsgID, 1, 420079) msg.AddMsgEvent(MsgID, 21, 12) msg.AddMsgEvent(MsgID, 1, 420080) msg.AddMsgEvent(MsgID, 21, 13) msg.AddMsgEvent(MsgID, 1, 420081) msg.AddMsgEvent(MsgID, 21, 14) msg.AddMsgEvent(MsgID, 1, 420082) msg.AddMsgEvent(MsgID, 21, 15) msg.AddMsgEvent(MsgID, 1, 420083) msg.AddMsgEvent(MsgID, 21, 16) msg.AddMsgEvent(MsgID, 1, 420084) msg.AddMsgEvent(MsgID, 21, 17) msg.AddMsgEvent(MsgID, 1, 420085) msg.AddMsgEvent(MsgID, 21, 18) msg.AddMsgEvent(MsgID, 1, 420086) msg.AddMsgEvent(MsgID, 21, 19) msg.AddMsgEvent(MsgID, 1, 420087) msg.AddMsgEvent(MsgID, 21, 10) msg.AddMsgEvent(MsgID, 1, 420009) msg.DispatchRoleMsgEvent(RoleID, MsgID) return end local plantId = map_def.plant_by_talk[TalkIndex] if plantId == nil then return end if not _cooldown_ok(plot0, RoleID, now) then _msg_simple(RoleID, 420012) return end local r = _ensure_farm_role(RoleID) local farmlevel = (r.usadbLevelRaw or 0) % 10 if farmlevel < plantId then _msg_simple(RoleID, 420030) return end local maxp = map_def.farm_max_plants[farmlevel] or 0 local farmnum = plot_store.countActivePlants(RoleID) if farmnum >= maxp then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 1) msg.AddMsgEvent(MsgID, 1, 420011) msg.AddMsgEvent(MsgID, 9, farmlevel) msg.AddMsgEvent(MsgID, 9, farmnum) msg.DispatchRoleMsgEvent(RoleID, MsgID) return end local def = map_def.plants[plantId] if def == nil then return end local numSeed = role.GetRoleItemNum(RoleID, def.seedItemId) if numSeed < 1 then _msg_simple(RoleID, 420010) return end role.RemoveFromRole(MapID, InstanceID, RoleID, def.seedItemId, 1, 420) map.MapDeleteCreature(MapID, InstanceID, TargetID) local seedmound = map.MapCreateCreature(MapID, InstanceID, def.seed, x, y, z) cre.SetCreatureScriptData(MapID, InstanceID, seedmound, 1, 1, RoleID) _set_plot(MapID, InstanceID, x, y, z, { PlantId = plantId, Stage = map_def.STAGE_SEED, OwnerRoleID = RoleID, StageStartTime = 0 }) end function M.seed_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) local plot, x, y, z TargetID, TargetTypeID, plot, x, y, z = M.syncPlotFromDB(MapID, InstanceID, TargetID, TargetTypeID) if plot == nil then return end local seedowner = plot.OwnerRoleID or 0 if TalkIndex == -1 then if seedowner == RoleID then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420094) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 21, 11) msg.AddMsgEvent(MsgID, 1, 420014) msg.AddMsgEvent(MsgID, 21, 10) msg.AddMsgEvent(MsgID, 1, 420009) msg.DispatchRoleMsgEvent(RoleID, MsgID) end return end if TalkIndex ~= 11 then return end if seedowner ~= RoleID then return end local num = role.GetRoleItemNum(RoleID, 4100007) if num <= 0 then _msg_simple(RoleID, 420017) return end local m = map_def.creature_to_plant[TargetTypeID] if m == nil then return end local def = map_def.plants[m.plantId] if def == nil then return end role.RemoveFromRole(MapID, InstanceID, RoleID, 4100007, 1, 420) map.MapDeleteCreature(MapID, InstanceID, TargetID) local now = _now() local seedlings = map.MapCreateCreature(MapID, InstanceID, def.seedling, x, y, z) cre.SetCreatureScriptData(MapID, InstanceID, seedlings, 1, 1, RoleID) cre.SetCreatureScriptData(MapID, InstanceID, seedlings, 1, 2, now) _set_plot(MapID, InstanceID, x, y, z, { Stage = map_def.STAGE_SEEDLING, StageStartTime = now }) end function M.seed_OnDisappear(MapID, InstanceID, TargetID, Ai) if not plot_store.schemaReady() then return end local x, y, z = _get_pos(MapID, InstanceID, TargetID) local plot = _get_plot(MapID, InstanceID, x, y, z) local seedowner = (plot and plot.OwnerRoleID) or cre.GetCreatureScriptData(MapID, InstanceID, TargetID, 1, 1) or 0 local now = _now() local mound = map.MapCreateCreature(MapID, InstanceID, map_def.MOUND_BASIC, x, y, z) cre.SetCreatureScriptData(MapID, InstanceID, mound, 1, 1, seedowner) cre.SetCreatureScriptData(MapID, InstanceID, mound, 1, 2, now) _set_plot(MapID, InstanceID, x, y, z, { PlantId = 0, Stage = map_def.STAGE_MOUND, OwnerRoleID = seedowner, LastPlotTime = now, StageStartTime = 0 }) end function M.seedling_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) local plot, x, y, z TargetID, TargetTypeID, plot, x, y, z = M.syncPlotFromDB(MapID, InstanceID, TargetID, TargetTypeID) if plot == nil then return end if plot.Stage == map_def.STAGE_HARVEST then return M.harvest_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) end local def = map_def.plants[plot.PlantId] if def == nil then return end local now = _now() local seedowner = plot.OwnerRoleID or 0 local s = (plot.StageStartTime == 0) and 0 or os.difftime(now, plot.StageStartTime) if TalkIndex == -1 then if s >= (def.growSeconds or 0) then return end if seedowner == RoleID then local totalMin = math.floor((def.growSeconds or 0) / 60) local remMin = math.floor(totalMin - (s / 60)) if remMin < 0 then remMin = 0 end local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420016) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 9, remMin) msg.AddMsgEvent(MsgID, 21, 11) msg.AddMsgEvent(MsgID, 1, 420018) msg.AddMsgEvent(MsgID, 21, 10) msg.AddMsgEvent(MsgID, 1, 420009) msg.DispatchRoleMsgEvent(RoleID, MsgID) end return end if TalkIndex ~= 11 then return end if seedowner ~= RoleID then return end local num = role.GetRoleItemNum(RoleID, 4100901) local num2 = role.GetRoleItemNum(RoleID, 4100902) if num <= 0 and num2 <= 0 then _msg_simple(RoleID, 420021) return end if num2 > 0 then role.RemoveFromRole(MapID, InstanceID, RoleID, 4100902, 1, 420) else role.RemoveFromRole(MapID, InstanceID, RoleID, 4100901, 1, 420) end map.MapDeleteCreature(MapID, InstanceID, TargetID) local harvest = map.MapCreateCreature(MapID, InstanceID, def.harvest, x, y, z) cre.SetCreatureScriptData(MapID, InstanceID, harvest, 1, 1, seedowner) _set_plot(MapID, InstanceID, x, y, z, { Stage = map_def.STAGE_HARVEST, StageStartTime = 0 }) end function M.seedling_OnDisappear(MapID, InstanceID, TargetID, Ai) if not plot_store.schemaReady() then return end local x, y, z = _get_pos(MapID, InstanceID, TargetID) local plot = _get_plot(MapID, InstanceID, x, y, z) if plot == nil then return end local def = map_def.plants[plot.PlantId] if def == nil then return end local seedowner = plot.OwnerRoleID or 0 local harvest = map.MapCreateCreature(MapID, InstanceID, def.harvest, x, y, z) cre.SetCreatureScriptData(MapID, InstanceID, harvest, 1, 1, seedowner) _set_plot(MapID, InstanceID, x, y, z, { Stage = map_def.STAGE_HARVEST, StageStartTime = 0 }) if seedowner ~= 0 then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 13, 1) msg.AddMsgEvent(MsgID, 1, 420023) msg.AddMsgEvent(MsgID, 5, TargetID) msg.DispatchRoleMsgEvent(seedowner, MsgID) end end function M.harvest_OnTalk(MapID, InstanceID, TargetID, TargetTypeID, RoleID, TalkIndex) local plot, x, y, z TargetID, TargetTypeID, plot, x, y, z = M.syncPlotFromDB(MapID, InstanceID, TargetID, TargetTypeID) if plot == nil then return end local seedowner = plot.OwnerRoleID or 0 local def = map_def.plants[plot.PlantId] if def == nil then return end if TalkIndex == -1 then if seedowner == RoleID then local MsgID = msg.BeginMsgEvent() msg.AddMsgEvent(MsgID, 20, 420024) msg.AddMsgEvent(MsgID, 24, TargetID) msg.AddMsgEvent(MsgID, 5, TargetTypeID) msg.AddMsgEvent(MsgID, 21, 11) msg.AddMsgEvent(MsgID, 1, 420025) msg.AddMsgEvent(MsgID, 21, 10) msg.AddMsgEvent(MsgID, 1, 420009) msg.DispatchRoleMsgEvent(RoleID, MsgID) end return end if TalkIndex ~= 11 then return end if seedowner ~= RoleID then return end role.AddRoleItem(MapID, InstanceID, RoleID, def.harvestItemId, 1, 6, 8, 102) if def.harvestItemId == 6601163 then if role.GetTrialState(RoleID, 6047) == 0 then role.OpenTrain(RoleID, 6047) end if AchievementTrial_AddProgress then AchievementTrial_AddProgress(RoleID, 6047, 1) end end map.MapDeleteCreature(MapID, InstanceID, TargetID) local now = _now() local mound = map.MapCreateCreature(MapID, InstanceID, map_def.MOUND_BASIC, x, y, z) cre.SetCreatureScriptData(MapID, InstanceID, mound, 1, 1, seedowner) cre.SetCreatureScriptData(MapID, InstanceID, mound, 1, 2, now) _set_plot(MapID, InstanceID, x, y, z, { PlantId = 0, Stage = map_def.STAGE_MOUND, OwnerRoleID = seedowner, LastPlotTime = now, StageStartTime = 0 }) _award_farm_exp(RoleID, TargetTypeID) end function M.harvest_OnDisappear(MapID, InstanceID, TargetID, Ai) if not plot_store.schemaReady() then return end local x, y, z = _get_pos(MapID, InstanceID, TargetID) local plot = _get_plot(MapID, InstanceID, x, y, z) local seedowner = (plot and plot.OwnerRoleID) or cre.GetCreatureScriptData(MapID, InstanceID, TargetID, 1, 1) or 0 local now = _now() local mound = map.MapCreateCreature(MapID, InstanceID, map_def.MOUND_BASIC, x, y, z) cre.SetCreatureScriptData(MapID, InstanceID, mound, 1, 1, seedowner) cre.SetCreatureScriptData(MapID, InstanceID, mound, 1, 2, now) _set_plot(MapID, InstanceID, x, y, z, { PlantId = 0, Stage = map_def.STAGE_MOUND, OwnerRoleID = seedowner, LastPlotTime = now, StageStartTime = 0 }) end return M