Jump to content
FapFap

Amplifiers

Recommended Posts

Hey can someone explain me how amplifier works? ex: this is Mini Amplifier( lv 10-40 )

Quote

function ItemUse_WeiXing( role , Item )
    local statelv = 1
    local ChaStateLv = GetChaStateLv ( role , STATE_SBJYGZ )
    if ChaStateLv > statelv then
        SystemNotice ( role , "Better fruit in effect. Please try again later." )
        UseItemFailed ( role )
        return
    end
    local lv_star = GetChaAttr( role , ATTR_LV) 
    if lv_star > 40 then
        SystemNotice ( role , "Effective only for those below Lv 40" )
        UseItemFailed ( role )
        return
    end
    SystemNotice ( role , "Mini Amplifier has been used." )    
    local statetime = 60+5*(lv_star-1)
    local Cha_Boat = 0
    Cha_Boat = GetCtrlBoat ( role )
    if Cha_Boat ==  nil then
        AddState( role , role , STATE_SBJYGZ , statelv , statetime )
    else
        AddState( Cha_Boat , Cha_Boat , STATE_SBJYGZ , statelv , statetime )
    end
end

What i want to know is where to edit the Double Exp it adds?

2. How to make it give random Time when you use it!  Like i used it and i got 3min double exp.. next time i use it i get 4min and soo.. random..

3. Is there a possibility to make amp run even if you relog? ex: i used amp and i had dc or i went off, when i log back on, the time continues right where i left, and how?!..

Edited by FapFap

Share this post


Link to post
Share on other sites
  1. EXP effect is determined on function ShareTeamExp (I guess it's called like that, located on exp_and_level.lua).
  2. Yes, just change statetime to math.random(X, Y). Values must be in seconds.
  3. Yes, by using serialize functions table.save and table.load.

Share this post


Link to post
Share on other sites
print('Loading amplifier.lua')
--[[----------------------------------------
amplifier handler for KOP/TOP/PKO 1.3X
version 1.1
[email protected]
credits: [email protected] for code review
--------------------------------------------
INFO:
EXP and DROP rate no longer used as states
Single file data
Upon getting killed (by monsters and players), players will lose their bonus
EXP and DROP rate will persist throughout diconnection and/or server restart
every couple minutes, players will receive a message on the remaining time
players will not be allowed to use lower tier amps if a higher tier is active
players will be notified when an amp has come to an end
TODO:
Autocreate folders
poor performance (better if load once on enter_map/enter_game)
--]]----------------------------------------

local string,os,math,io,table = string,os,math,io,table

if table.load == nil then error('serialize.lua cannot be found!') end

local minToSec = minToSec or function(min) return min * 60 end
local ToClockFormat = ToClockFormat or function(sec)
  local num = tonumber(sec)
  if(num == 0)then return "00:00:00" else
    now_hour = string.format("%02.f",math.floor(num / 3600 ))
    now_minute = string.format("%02.f",math.floor(num / 60 - (now_hour*60)))
    now_second = string.format("%02.f",math.floor(num - now_hour*3600 - now_minute*60))
    return now_hour..":"..now_minute..":"..now_second
  end
end

local file_exists = file_exists or function(name)
  local f = io.open(name, 'r')
  if(f ~= nil)then io.close(f) return true
  else return false end
end

local explode = explode or function(separator, str)
  local pos, arr = 0, {}
  for st, sp in function() return string.find(str, separator, pos, true) end do
    table.insert(arr, string.sub(str, pos, st-1))
    pos = sp + 1
  end
  table.insert(arr, string.sub(str, pos))
  return arr
end

local function num2hex(IN)
  local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
  while IN>0 do
    I=I+1
    IN,D=math.floor(IN/B),math.mod(IN,B)+1
    OUT=string.sub(K,D,D)..OUT
  end return OUT
end

ampData_conf = {
  path       = GetResPath('../lua/database/'),
  db         = 'persistamp.dat'
}

local function initamp()
  -- itemid,state,statelv,lvmin,lvma,minutes,functionName
  local lm = LV_LIMIT
  -- EXP FRUITS
  amp.add(0898, 'xp', 002, 30, lm, 015, 'ItemUse_MoreItemAndExpGz')   -- Mystical Fruit
  amp.add(1128, 'xp', 002, 00, 40, 005, 'ItemUse_WeiXing')            -- mini amp
  amp.add(2586, 'xp', 3.5, 75, lm, 030, 'ItemUse_MoreExpGzLv3x5A')    -- 3.5x EXP amp
  amp.add(2587, 'xp', 004, 80, lm, 030, 'ItemUse_MoreExpGzLv4A')      -- 4x EXP amp
  amp.add(2645, 'xp', 002, 00, lm, 120, 'ItemUse_ZJSB')               -- Mid Amplifier of Strive
  amp.add(2646, 'xp', 002, 00, lm, 240, 'ItemUse_GJSB')               -- High Amplifier of Strive
  amp.add(2647, 'xp', 002, 00, lm, 360, 'ItemUse_CJSB')               -- Super Amplifier of Strive
  amp.add(2648, 'xp', 002, 00, lm, 480, 'ItemUse_MHSB')               -- Ultra Amplifier of Strive
  amp.add(3094, 'xp', 002, 00, lm, 030, 'ItemUse_MoreExpGzA')         -- amp of strive
  amp.add(3095, 'xp', 2.5, 60, lm, 030, 'ItemUse_MoreExpGzLv3A')      -- hi amp of strive
  amp.add(3844, 'xp', 002, 00, lm, 015, 'ItemUse_MoreExpGz')          -- heavens berry
  amp.add(5638, 'xp', 002, 40, lm, 015, 'ItemUse_molilucky')          -- Novice 2X Exp Fruit
  amp.add(5639, 'xp', 003, 50, lm, 030, 'ItemUse_moliegis')           -- 3x Exp Fruit
  amp.add(5694, 'xp', 3.5, 75, lm, 030, 'ItemUse_MoreExpGzLv3x5A')    -- 3.5x EXP amp
  amp.add(5695, 'xp', 004, 80, lm, 030, 'ItemUse_MoreExpGzLv4A')      -- 4x EXP amp
  amp.add(5767, 'xp', 003, 70, lm, 030, 'ItemUse_HighExpGzLv3A')      -- 3x EXP amp
  amp.add(6405, 'xp', 002, 00, 40, 015, 'ItemUse_molilucky')          -- Magic Lucky Fruit
  amp.add(6406, 'xp', 005, 50, 75, 030, 'ItemUse_molibless1')         -- Magic Blessing Fruit
  amp.add(8330, 'xp', 003, 50, lm, 030, 'ItemUse_moliegis')           -- 3x Exp Fruit
  -- DROP FRUITS
  amp.add(3096, 'mf', 002, 00, lm, 030, 'ItemUse_MoreItemGzA')        -- amp of luck
  amp.add(3097, 'mf', 003, 60, lm, 030, 'ItemUse_MoreItemGzLv3A')     -- hi amp of luck
  amp.add(3845, 'mf', 002, 00, lm, 015, 'ItemUse_MoreItemGz')         -- charmed berry
  amp.add(5640, 'mf', 003, 60, lm, 030, 'ItemUse_molimoney')          -- 3x Drop Fruit
  amp.add(8331, 'mf', 003, 60, lm, 030, 'ItemUse_molimoney')          -- 3x Drop Fruit
  -- CLEAN DATABASE IF NECCESSARY
  amp.cleandata()
end

ampData_fruit = {}
local function ampData_addFruit(id, bonus, rate, minLv, maxLv, min, funcName)
  ampData_fruit[id] = {
    bonus   = bonus,
    rate    = rate,
    minLv   = minLv,
    maxLv   = maxLv,
    min     = min
  }
  -- hook original ItemUse_* to call/replace custom one (UseAmpDefault)
  _G[funcName] = function(cha, item)
    UseAmpDefault(cha, item)
  end
end

-- Creates a database file given path and filename
local function CreateDatabase(path, db)
  if not file_exists(path..db) then
    local f = io.open(path..db, 'a')
    table.save({}, path..db)
    f:close()
  end
  return table.load(path..db)
end

-- reading routine of database file
-- id - Player ID
-- type - 'xp' or 'mf'
local function GetChaAmpData(id, type)
  local t = amp.loadtable(ampData_conf['path'], ampData_conf['db'])
  if t[id] == nil then return 1,nil end
  local a,b = string.find(t[id], type)
  if not a and not b then return 1,nil end
  b = b + 2
  local c = string.find(t[id], ';', b)
  local data = string.sub(t[id], b, c-1)
  -- exp=statelv,os.time;
  local ret = explode(',', data)
  ret[1] = tonumber(ret[1])
  ret[2] = tonumber(ret[2], 16) -- hex here
  return ret[1], ret[2]
end

-- writing routine of database file
-- insert "state" into file for persistency
-- id - Player ID
-- type - 'xp' or 'mf'
-- ampState - the level of the state
-- statesec - remaining time of state in seconds
local function InsertToAmpDatabase(id, type, ampState, statesec)
  local t = amp.loadtable(ampData_conf['path'], ampData_conf['db'])
  local str = type..'='..ampState..','..statesec..';'
  if t[id] == nil then t[id] = str
  else
    local a,b = string.find(t[id], type)
    if not a and not b then t[id] = t[id]..str
    else -- recursion here cuz im lazy
      amp.deldata(id, type)
      return InsertToAmpDatabase(id, type, ampState, statesec)
    end
  end
  table.save(t, ampData_conf['path']..ampData_conf['db'])
end

-- deletion of state in database
-- id - Player ID
-- type - state to delete
local function DeleteAmpData(id, type)
  local t = amp.loadtable(ampData_conf['path'], ampData_conf['db'])
  local a,b = string.find(t[id], type)
  if not a and not b then return end
  b = b + 2
  local c = string.find(t[id], ';', b)
  local str = string.sub(t[id], a, c)
  local d = string.gsub(t[id], str, '')
  t[id] = d
  if t[id] == '' then t[id] = nil end
  table.save(t, ampData_conf['path']..ampData_conf['db'])
end

-- automatic cleans db upon loaded/updateall
local function CleanAmpData()
  local t = amp.loadtable(ampData_conf['path'], ampData_conf['db'])
  for i,v in pairs(t) do
    local chaState,chaTime = amp.getdata(i, 'xp')
    if chaState ~= 1 and chaTime ~= nil then
      if os.time() >= chaTime then amp.deldata(i, 'xp') end
    end
    chaState,chaTime = amp.getdata(i, 'mf')
    if chaState ~= 1 and chaTime ~= nil then
      if os.time() >= chaTime then amp.deldata(i, 'mf') end
    end
  end
end

-- function to remove states upon death, called by GetExp_MKP (monster kill player)
-- and by GetExp_PKP (player kill player)
local function ClearAmpOnDeath(dead)
  local charId = GetCharID(dead)
  local chaState,chaTime = amp.getdata(charId, 'xp')
  if chaState ~= 1 then
    SystemNotice(dead, chaState..'x EXP bonus has vanished...')
    amp.deldata(charId, 'xp')
  end
  chaState,chaTime = amp.getdata(charId, 'mf')
  if chaState ~= 1 then
    SystemNotice(dead, chaState..'x LUCK bonus has vanished...')
    amp.deldata(charId, 'mf')
  end
end

-- used function and provided interface
amp = {
  loadtable     = CreateDatabase,
  insert        = InsertToAmpDatabase,
  getdata       = GetChaAmpData,
  add           = ampData_addFruit,
  init          = initamp,
  timer         = player_timer,
  pkp           = GetExp_PKP,
  mkp           = GetExp_MKP,
  deldata       = DeleteAmpData,
  cleandata     = CleanAmpData,
  clear         = ClearAmpOnDeath,
} amp.init()

-- persistency upon updateall?
playerampdata =
playerampdata or {}

-- timer to notify players:
-- when exp vanishes
-- remaining time left
-- todo: do not constantly load serialize file
function player_timer(cha)
  amp.timer(cha)
  playerampdata[cha] = playerampdata[cha] or {}
  if playerampdata[cha].xpstate == nil and playerampdata[cha].xptime == nil then
    playerampdata[cha].xpstate, playerampdata[cha].xptime = amp.getdata(GetCharID(cha), 'xp')
  end
  if playerampdata[cha].xpstate ~= 1 and playerampdata[cha].xptime ~= nil then
    if os.time() >= playerampdata[cha].xptime then
      local charId = GetCharID(cha)
      BickerNotice(cha, playerampdata[cha].xpstate..'x EXP bonus has vanished...')
      amp.deldata(charId, 'xp')
      playerampdata[cha].xpstate, playerampdata[cha].xptime = nil,nil
    end
    local tick = GetChaParam(cha, 1)
    playerampdata[cha].xpcycle =
    playerampdata[cha].xpcycle or math.random(120,240)
    if math.mod(tick, playerampdata[cha].xpcycle) == 0 then
      playerampdata[cha].xpstate, playerampdata[cha].xptime = amp.getdata(GetCharID(cha), 'xp')
      if os.time() < playerampdata[cha].xptime then
        local stateTime = playerampdata[cha].xptime - os.time()
        BickerNotice(cha, 'Remaining '..playerampdata[cha].xpstate..'x EXP: '..ToClockFormat(stateTime)..'!')
        playerampdata[cha].xpcycle = math.random(120,240)
      end
    end
  end
  if playerampdata[cha].mfstate == nil and playerampdata[cha].mftime == nil then
    playerampdata[cha].mfstate, playerampdata[cha].mftime = amp.getdata(GetCharID(cha), 'mf')
  end
  if playerampdata[cha].mfstate ~= 1 and playerampdata[cha].mftime ~= nil then
    if os.time() >= playerampdata[cha].mftime then
      local charId = GetCharID(cha)
      BickerNotice(cha, playerampdata[cha].mfstate..'x DROP bonus has vanished...')
      amp.deldata(charId, 'mf')
      playerampdata[cha].mfstate, playerampdata[cha].mftime = nil,nil
    end
    local tick = GetChaParam(cha, 1)
    playerampdata[cha].mfcycle =
    playerampdata[cha].mfcycle or math.random(120,240)
    if math.mod(tick, playerampdata[cha].mfcycle) == 0 then
      playerampdata[cha].mfstate, playerampdata[cha].mftime = amp.getdata(GetCharID(cha), 'mf')
      if os.time() < playerampdata[cha].mftime then
        local stateTime = playerampdata[cha].mftime - os.time()
        BickerNotice(cha, 'Remaining '..playerampdata[cha].mfstate..'x DROP: '..ToClockFormat(stateTime)..'!')
        playerampdata[cha].mfcycle = math.random(120,240)
      end
    end
  end
end

-- GetExp_MKP hooks (to clear amp data upon death)
function GetExp_MKP(dead, atk)
  amp.mkp(dead, atk)
  amp.clear(dead)
end

-- GetExp_PKP hooks (to clear amp data upon death)
function GetExp_PKP(dead, atk)
  amp.pkp(dead, atk)
  amp.clear(dead)
end

local getstatehook = GetChaStateLv
-- maybe hook and change param for obtion to serialize?
function GetChaStateLv(cha, state)
  if state == STATE_SBJYGZ then
    local charId = GetCharID(cha)
    local chaState,chaTime = amp.getdata(charId, 'xp')
    if chaState == 2.5 then chaState = 3 end
    if chaState == 001 then chaState = 0 end
    return chaState
  elseif state == STATE_SBBLGZ then
    local charId = GetCharID(cha)
    local chaState,chaTime = amp.getdata(charId, 'mf')
    if chaState == 2.5 then chaState = 3 end
    if chaState == 001 then chaState = 0 end
    return chaState
  else
    return getstatehook(cha, state)
  end
end

-- custom ItemUse_ function that will be called
function UseAmpDefault(cha, item)
  local charId = GetCharID(cha)
  local t = amp.loadtable(ampData_conf['path'], ampData_conf['db'])
  -- check if the amp is functional
  local ampId = GetItemID(item)
  if ampData_fruit[ampId] == nil then
    SystemNotice(cha, 'Amplifier has expired. Please use again later...')
    UseItemFailed(cha)
    return
  end
  -- check if player has a better amp
  local ampState,ampType = ampData_fruit[ampId].rate,ampData_fruit[ampId].bonus
  local chaState,chaTime = amp.getdata(charId, ampType)
  if chaState > ampState then
    SystemNotice(cha, 'Better fruit in effect. Please use again later...')
    UseItemFailed(cha)
    return
  end
  -- check if said amp is currently in effect
  if chaState == ampState then
    local statetime = chaTime - os.time()
    BickerNotice(cha, 'Current fruit still in effect for '..ToClockFormat(statetime)..'!')
    UseItemFailed(cha)
    return
  end
  -- check if player level is in range to use amp
  local chaLv = Lv(cha)
  if chaLv > ampData_fruit[ampId].maxLv then
    SystemNotice(cha, 'Effective only against players lv: '..ampData_fruit[ampId].maxLv..' and below!')
    UseItemFailed(cha)
    return
  end
  if chaLv < ampData_fruit[ampId].minLv then
    SystemNotice(cha, 'Only players lv: '..ampData_fruit[ampId].minLv..'+ may use!')
    UseItemFailed(cha)
    return
  end
  -- add state and time to db (this should be done only on leave_map/leave_game) 
  -- but would require GameServer hex for "GetChaStateTime(stateID)
  local time = minToSec(ampData_fruit[ampId].min)
  local statesec = num2hex(os.time() + time) -- hex here
  amp.insert(charId, ampType, ampState, statesec)
  BickerNotice(cha, 'Feel the effect of '..GetItemName(ampId)..' for '..ToClockFormat(time)..'!')
  playerampdata[cha] =
  playerampdata[cha] or {}
  playerampdata[cha][ampType..'state'], playerampdata[cha][ampType..'time'] = amp.getdata(charId, ampType)
end
  • Like 1

kong.png

a2.png

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...