the scripting thread

"eventually EUO will get to the point its (sic) unplayable" - Dudle

Moderator: EUO Moderators

Re: the scripting thread

Postby Catherine » Sun Aug 10, 2014 6:26 am

Woot! Thanks, looks like we can do what I intend (especially that egg hack to normalize for heroic etc, great stuff!). I think a sensible idea is I finish off x2 100x100's*, stuff them with scripts and use them as a testing base for all of this. That way we can progress quicker (less checking), have them in-game for people to tinker with and have a basis for a larger project.

One tiny, and one stupid question - how do I tint items? Not the maptile versions, but just normal items. e.g. moss is 5d1. However much I try, I cannot add a simple black tint to it (to change it from moss to soot). The triple hex code for black is 000, so I imagined it would have been easy. 0x0005d1 nor 0x5d1000 works :?


Ok, been doing my reading - can you attach scripts to items?

Code: Select all
function es_soot(m)

m:set=0x00005d1

end


Can this also be used to create split items? e.g.

Code: Select all
function es_floatingcrystal(m)

m:set=0x441c51e

end


I'm hoping that'd make a brazier base with a floating crystal on top, but can't check.




Stupid question - Quest NPCs. I've already worked out how to set a named, friendly patrolling NPC - but how to add the conversation trees? e.g. JOB > "I am a farmer". etc.


*One is complete already, with back-story, NPCs, theme etc all planned. Difficulty is ~roughly 10% harder than mino halls, but it's less of a hunting map atm than an interactive experience.

Code: Select all
function lvl001reset(id, px, py, z)

   for x=6,8 do
      for y=4,10 do
         set_and_send_new_tile(x,y,z,95) -- 95 is the red tile
      end
   end
   reset_trigger(7,3,z,1)

end

function lvl001wrong(id, x, y, z)

   -- reset all tiles
   -- lvl001reset(id,x,y,z)
   
   -- send plyr back to start
   send_player_to_xy(id,7,12,true) -- don't check trigs (may cause loop)
end

function lvl001green(id, x, y, z)

   set_and_send_new_tile(x,y,z,222) -- 222 is the green tile
end

function lvl001final(id, x, y, z)

   lvl001green(id,x,y,z)
   reset_trigger(7,3,z,0) -- disables the barrier
   
end


In Egg's original puzzle, I never understood how this knew what was a green and red tile, or the x,y locations of them. It seemed to be missing something? Also, the step function is the reset, could we make it timed?

Added to this, is there a way to set a function so that say, pulling a lever -> a friendly spawner becoming hostile? I know about mkevil, but I'm guessing the mob would have to be wiped then replaced with an evil equivalent? Obviously, there'd have to be a reset so the friendly mob eventually respawned.
User avatar
Catherine
English correct bastard.
 
Posts: 1250
Joined: Mon Sep 08, 2003 2:40 am

Re: the scripting thread

Postby LordMortiferus » Mon Aug 11, 2014 1:49 am

Basics of tinting:
# If an avatar or an item has grey areas chances are these grey parts can be tinted. Everything not grey is not affected by tinting, e.g. moss. Still some grey areas may not tint cause the grey is not pure grey as values for RGB are not equal (see RGB colour space).

# There is a difference between avatar and item tinting. Avatars can be colored with any color avaiable in the triple hexcode color space. Note, while the triple hexcode for black is 0x000 this does not tint an avatar black. E.g. 0x000200 equals 0x200, so the digits that define tinting remain blank. The closets to black would be 0x100200.
Items do tint as a change of material (see ..\euo\dat\materials.txt). E.g. blackrock will return a blackish item, vamp a reddish item. It does not matter if you convert a mob avatar into an item - the tinting mechanic stay different. E.g. 0x134 is a skull, 0x7134 is a gold skull, 0xf134 is a crystal skull.

# Tinted avatars and items can be placed by Maped and should show their respective color change. Add item/avatar and left click again to change its code.

Splitavtars:
# Technically you can use an item as the head of a mob, but the feet need to be a mob sprite in any case. (there may be issues with drawing the item sprite, but I think it works atm without issues). A brazier base with a crystal on top should not work, unless egg adds a brazier mob to the mob list...

Convos:
# no real clue, other than the stuff I did post over in the Maped thread. Maybe I have some time next week to tinker with this.

Your script:
# have to go over it when I have a bit more time at hand.

Make Evil:
# no problem, though I cannot find a mkevil() function in the LUA API. Nevertheless, you can use m:set_align(ALIGN_EVIL) to make the mob evil after setting m = get_mon_ptr(x,y) with x,y being the coords of the NPC.
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby Catherine » Mon Aug 11, 2014 2:18 am

LordMortiferus wrote:Basics of tinting:
# If an avatar or an item has grey areas chances are these grey parts can be tinted. Everything not grey is not affected by tinting, e.g. moss. Still some grey areas may not tint cause the grey is not pure grey as values for RGB are not equal (see RGB colour space).



Ok, that's a shame. While I understand why the various sprites in MapEd have unique codes, there seems to be room to have a set of grey-scaled ones such as 5ca,5f2-4 for the common items such as gems, splats (147, 528 etc) and splashes (5d0,5d1).

File under: wishlist.

Related to this, a tiny nit-pick - the two free-floating 'flows' (5d2, 5d3) are slightly off-centre to the base tiles (26,27) - you can tell this by using the maptile, then placing one as an item on top of it.
User avatar
Catherine
English correct bastard.
 
Posts: 1250
Joined: Mon Sep 08, 2003 2:40 am

Re: the scripting thread

Postby Catherine » Fri Aug 15, 2014 12:20 am

Ok - is it possible to use the timer code to ensure that map alterations are reset after X time?

e.g.

Code: Select all
   -- spawn timer (should be placed at unreachable position of the map)
   m = spawn_at(0x364, 0, 0, z, false)   
   -- save x,y coords to timer
   m:set_dmg_dice(x)
   m:set_dmg_sides(y)
   -- set timer
   m.timer = 10
   m.heartbeat_func="cat_timer"   
   -- deactivate stp-fea
   map=get_map_ptr(z)
   map:set_feat_val(x, y, 0)
end

function cat_timer(m)
   -- timer
   m.timer = m.timer - 1
   if m.timer <= 0 then

   -- retrieve x,y coords for stp-fea
      local x = m:get_dmg_dice()
      local y = m:get_dmg_sides()   
      -- reactivate timer
      map=get_map_ptr(m.map_level)
      map:set_feat_val(x, y, 1)   
      -- kill off timer
      hurt(m.id,m.hp+1,"time is up")
   end
end


By inserting:
Code: Select all
 for x=6,8 do
      for y=4,10 do
         set_and_send_new_tile(x,y,z,95) -- 95 is the red tile
      end
 


The basic idea is to have a step trigger that changes a load of scenery that resets after time X, whatever the player's actions. e.g. Step -> tiles change -> timer is set -> timer ends, tiles reset automatically. I also know that a version of this exists in-game, in the Jungle map (has two walls crashing together).

Also - please, Egg, could you post some active examples. i.e.

1) The Jungle squish one - since this includes a timer as well as tile changes & a reset.
2) Any simple "Use lever > removes barrier". I'm being dumb but I cannot find a single example of this, barring: Found the <swi> feature. Derp. New question: can <swi> effect different levels? Is it possible to have a <swi> change something on a different map?

3) Dialogue - m.talk_line="Hello stranger!"; << This is obviously what the NPC says after you do a <t>alk. Is there a m.talk_line("job")="I'm a lumberjack"? e.g. How to trigger these. Do they even go in the LUA section? How do you do NPC dialogues? Edit: found a discussion by Lord that states it's out of LUA's control - manually writing them atm.

5) Use trigger - summon a portal that has a lxy attached. No idea how to do this. Or have any <a> switch --> tile change + <function>. e.g. Pull switch --> portal appears that can warp you elsewhere. I suspect this will require a script, like the brazier / sea monster puzzle.


[Edit: found the <swi> feature. I am dumb. Some stuff still needs work though]


TL;DR

I can't LUA.
User avatar
Catherine
English correct bastard.
 
Posts: 1250
Joined: Mon Sep 08, 2003 2:40 am

Re: the scripting thread

Postby LordMortiferus » Sun Aug 17, 2014 6:37 am

Yeah you can change maptiles using the stp-script. There are at least two possible ways to do it. Either by using for-iterations as you have posted.
Alternatively, you could create an array of the the submap you want to past over the section of your map, e.g. cat_submap = {222,210,223,123} - you can paste the maptiles within this array using
Code: Select all
paste_sub_map (data,lvl,hx,hy,hw,hh,mask)

data = cat_submap
lvl = maplevel
hx = x-coord
hy = y-coord
hw = width of the submap, e.g. 2 tiles -> first row would be 222, 210
hh = height of the submap, e.g. 2 tiles -> second row would be 223, 123
mask = is a maptile that will not be exchanged, e.g. mask = 156 means that if the region of your map contains a maptile = 156 this will not be changed by the script.

Here is the complete function that is called by paste_sub_map (taken from mapfuncs.lua):
Code: Select all
function paste_sub_map (data,lvl,hx,hy,hw,hh,mask)

   map=get_map_ptr(lvl)
   
   for x=0,hw-1 do
      for y=0,hh-1 do
      
         idx=y*hw+x+1
         t=data[idx]
         if t~=nil and t~=mask then
            map:set_tile(x+hx,y+hy,t)
         end
      end
   end
end

When you change maptiles in the line of sight of a player you probably have to call "update_everyones_fov(p)" -- p being the player who stepped onto the stp-fea in this case.

as for you other questions:
1) there is no timer involved with the squish trap.
2) not sure, especially if the map has not been loaded before
3) what I meant is that scripting convos with LUA is beyond my scope of experience, but I am sure you can use LUA to script convos with the functions from the API I posted elsewhere.
5) the following function will create a portal at x,y that teleports you to desx,desy on deslevel
Code: Select all
map:add_feat(x,y,TRIG_PORTAL,desx,desy,deslevel,Item(-1))
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby eggmceye » Fri Aug 29, 2014 8:13 pm

using morty's maped cut/paste hack I have made a merged version of the Mage Tower ...

lvl259small.png
You do not have the required permissions to view the files attached to this post.
User avatar
eggmceye
hello
 
Posts: 9882
Joined: Mon Mar 11, 2002 3:55 pm
Location: Sydney, Australia

Re: the scripting thread

Postby LordMortiferus » Thu Sep 04, 2014 1:52 am

Here is the instruction for the copy&paste script add-on for Maped.

How to install:
1) Within your EUO folder create a subfolder called scripts.maps:
..\EUO\scripts.maps\
2) Either download the lua file directly from my dropbox or paste the script into an empty text file and save it with the *.lua extension. Eitherway the this lua script file goes into ..\EUO\scripts.maps\

What part of the script is of any importance to you:
Code: Select all
function load_map_666(lvl, load_on_the_fly) -- change map number if needed
Change the 666 into the maplevel number you want to copy or paste from, e.g. 001, 032, 260 (note it has to be a three digit number).
[code]   local func = "copy" -- copy or paste
   local xy_start = {0,0} -- {x,y} -- needs to be set for copy or paste
   local xy_end = {30,30} -- {x,y} -- only essential for copy[/code]
func = "copy" -- inbetween the quotes you either write copy or paste depending on what you want to do.
xy_start = {x,y} -- this defines the starting point (upper left corner) of the area you want to copy from or paste over something.
xy_end = {x,y} -- if you copy this defines the end point (lower right corner) of the area you want to copy.
[code]   local cp_tiles = true -- set to false if you do not want to copy&paste tiles
   local cp_items = true -- set to false if you do not want to copy&paste items
   local cp_feat = true -- set to false if you do not want to copy&paste features
   local cp_spawner = true -- set to false if you do not want to copy&paste spawners

Depending on what you want to copy or paste you can set cp_tiles, cp_items, cp_feat and cp_spawner to either true or false. If set to true it will be copy&pasted and if set to false it won't copy nor paste. Note: pasting spawner, items or features will result in overwriting the existing data instead of merging them.

How to copy:
1) open the script with an editor
2) enter the level number you want to copy from at "function load_map_xxx"
3) set func = "copy"
4) set xy_start and xy_end to the appropriate coordinates. Setting xy_end to "xy_end = {300,300} will copy the whole map (thanks max)
5) define what you type of data you want to copy (tiles, items, features, spawner)
6) save the script
7a) start Maped and open the map level you want to copy
7b) if Maped was already running go to the map level you want to copy and reload the map and scripts with "ctrl+r"
8) your euo folder should now contain a file called chunk_size.lua and depending on what you wanted to copy: tile_cache.lua, item_cache.lua, feat_cache.lua and/or spawner_cache.lua
9) done copying

How to paste:
2) enter the level number you want to paste to at "function load_map_xxx"
3) set func = "paste"
4) set xy_start to the appropriate coordinates you want to paste to (upper left corner of the area) - make sure you map is large enough for the chunk.
5) again define the data you want to paste by setting cp_tiles etc. to either false or true.
6) save the script
7) likely Maped is still running, go to the map level you want to paste into and reload the script by "ctrl+r"
8) The chunk should now be pasted into you map, make sure everything looks fine and save using "w" or by quit&save "q"

How to deactivate the script:
1) if you are done pasting change back func to func = "copy" to prevent accidental pasting!
2) also I recommend setting "function load_map_xxx" to some unused map level.
3) you may want to delete chunk_size.lua, tile_cache.lua, item_cache.lua, feat_cache.lua and spawner_cache.lua in your ..\euo\ folder

Protip: The cache files can be used to create sub map arrays for LUA scripts.
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby Celerion » Fri Oct 31, 2014 2:59 am

The time of the EUO-server has been changed from local Sydney-time to UTC (Coordinated Universal Time). This makes it way easier for my auxbox-script to calculate the remaining time of Double-XP and the days to Double-XP (counting down from 7). So here's the updated version. As always, it's called 'auxbox.lua' and should be copied to "C:\...\euo\clientscripts". Make sure, there's not much other stuff in that folder, i.e. it should be the only script in that folder. (Make a backup of your folder first.)
Code: Select all
-- auxbox.lua with classes, rewritten by Celerion, 10-2014.

-- Configuration: Set the options to either 'true' or 'false':

SHOW_ARRANGE_INFOS                  = true

SHOW_REALWORLD_TIME                 = true
REALWORLD_TIME_24_HOURS_FORMAT      = true
REALWORLD_TIME_WITH_SECONDS         = false

SHOW_SESSION_TIME                   = true
SESSION_TIME_WITH_DAYS              = true
SESSION_TIME_WITH_SECONDS           = false

SHOW_DOUBLE_XP_INFO                 = true
DOUBLE_XP_INFO_WITH_DAYS            = false
DOUBLE_XP_INFO_WITH_SECONDS         = true
SHOW_DAYS_TO_DOUBLE_XP              = true
SHOW_HOURS_TO_DOUBLE_XP             = true

SHOW_DAMAGE_DEALT_PER_SECOND_LINE   = true
SHOW_DAMAGE_TAKEN_PER_SECOND_LINE   = true
SHOW_RECENT_DAMAGE_DEALT_LINES      = false

SHOW_NUMLOCK_WARNING                = true
SHOW_SCRIPT_RELOAD_MESSAGE          = false
SHOW_EUO_MESSAGE                    = false


------------- End of Configuration -----------

AuxboxWriter = {}

    function AuxboxWriter:new()
        -- Some magic to setup a Lua-class here.
        -- See "http://www.lua.org/pil/16.html" for details.
        -- Or better, just don't worry about it ...
        local o = {}
        setmetatable(o, self)
        self.__index = self
        self.clock = Clock:new()
        self.auxbox_next_line = 0
        self.cd = 0
        -- The Lua-script seems to get some variables, objects
        -- and even a function from the EUO-client. I store them
        -- in the "from_EUO"-table to mark their origin:
        self.from_EUO = {}
        self.from_EUO.d = d
        self.from_EUO.SELECT_ABILITY = SELECT_ABILITY
        self.from_EUO.SELECT_READY = SELECT_READY
        self.from_EUO.SELECT_BUY = SELECT_BUY
        self.from_EUO.SELECT_BANK = SELECT_BANK
        self.from_EUO.auxbox_ability_binds = auxbox_ability_binds
        self.from_EUO.g_dpst = g_dpst
        self.from_EUO.g_dtpst = g_dtpst
        -- Data for "Damage per Second":
        self.last_session_seconds = 0
        self.last_4_dpst = {}
        for i = 1, 4 do
            table.insert(self.last_4_dpst, self.from_EUO.g_dpst)
        end
        self.last_4_dtpst = {}
        for i = 1, 4 do
            table.insert(self.last_4_dtpst, self.from_EUO.g_dtpst)
        end
        self.last_dpst = self.from_EUO.g_dpst
        self.recent_dmg = {0, 0, 0, 0}
        return o
    end

    function AuxboxWriter:auxbox_loop()
        local w = self.from_EUO.d:auxbox_get_width()
        local h = self.from_EUO.d:auxbox_get_height()
        self.from_EUO.d:auxbox_clear()
        self.auxbox_next_line = 0
        if not self.from_EUO.d:ok_to_draw_play_window() then
            return
        end
        self.cd = self.from_EUO.d:get_curr_display()
        self:show_contents()
    end

    function AuxboxWriter:auxbox_prop_line(prop_name, prop_val)
        local pvl = 0
        if prop_name == nil then prop_name = "" end
        if prop_val == nil then prop_val = "" end
        local filler = string.rep(" ", 25 - string.len(prop_name) - string.len(prop_val))
        self.auxbox_next_line = self.auxbox_next_line + 1
        self.from_EUO.d:auxbox_set_line(self.auxbox_next_line, string.format("%s %s %s", prop_name, filler, prop_val))
    end

    function AuxboxWriter:auxbox_blank_line()
        self.auxbox_next_line = self.auxbox_next_line + 1
    end

    function AuxboxWriter:show_contents()
        if self.cd == 1 then
            if SHOW_ARRANGE_INFOS == true then
                self:auxbox_arrange_info()
            end
            return
        end
        if SHOW_REALWORLD_TIME == true then self:auxbox_time() end
        if SHOW_SESSION_TIME == true then self:auxbox_session_time() end
        if SHOW_DOUBLE_XP_INFO == true then self:auxbox_double_xp_info() end
        if SHOW_DAMAGE_DEALT_PER_SECOND_LINE == true or
           SHOW_DAMAGE_TAKEN_PER_SECOND_LINE == true or
           SHOW_RECENT_DAMAGE_DEALT_LINES    == true then
            self:auxbox_damage_per_second()
        end
        if SHOW_NUMLOCK_WARNING == true then self:auxbox_numlock_warning() end
        if SHOW_SCRIPT_RELOAD_MESSAGE == true then self:auxbox_f5_message() end
        if SHOW_EUO_MESSAGE == true then self:auxbox_euo_message() end
end

    function AuxboxWriter:auxbox_session_time()
        self:auxbox_prop_line("Session time:", self.clock:get_session_time())
        self:auxbox_blank_line()
    end

    function AuxboxWriter:auxbox_time()
        self:auxbox_prop_line("Real World Time:", self.clock:get_local_time_in_configured_format())
    end

    function AuxboxWriter:auxbox_double_xp_info()
        local info = self.clock:get_double_xp_info()
        if info.days == 0 then
            self:auxbox_prop_line("Double-XP:", info.timestr)
            self:auxbox_blank_line()
            return
        end
        if SHOW_DAYS_TO_DOUBLE_XP == true then
            if info.days == 1 then
                self:auxbox_prop_line("Tomorrow's Double-XP.")
                if SHOW_HOURS_TO_DOUBLE_XP == true then
                    self:auxbox_prop_line("Hours to Double-XP:", info.timestr)
                end
                self:auxbox_blank_line()
                return
            end
            if info.days > 1 and info.days <= self.clock.days_in_advance then
                self:auxbox_prop_line(info.days .. " days until Double-XP.")
                self:auxbox_blank_line()
                return
            end
        end
   end
 
    function AuxboxWriter:auxbox_numlock_warning()
        if self.from_EUO.d:numlock() then
            self:auxbox_blank_line()
            self:auxbox_prop_line("Please turn numlock off!")
        end
    end

    function AuxboxWriter:auxbox_euo_message()
        self:auxbox_blank_line()
        self:auxbox_prop_line("Forums: forums.swut.net")
        self:auxbox_prop_line("Manual: euotopia.com/manual")
        self:auxbox_prop_line("F12 for main menu.")
        self:auxbox_blank_line()
    end

    function AuxboxWriter:auxbox_f5_message()
        self:auxbox_prop_line("Press Alt-F5 to Reset", "")
    end

    function AuxboxWriter:auxbox_damage_per_second()

        -- Damage Per Second -- original script provided by LordMortiferus
        local session_seconds = self.clock:get_session_seconds()

        self.from_EUO.g_dpst = g_dpst
        self.from_EUO.g_dtpst = g_dtpst

        if session_seconds > self.last_session_seconds then
            self.last_session_seconds = session_seconds
            self.last_4_dpst[4] = self.last_4_dpst[3]
            self.last_4_dpst[3] = self.last_4_dpst[2]
            self.last_4_dpst[2] = self.last_4_dpst[1]
            self.last_4_dpst[1] = self.from_EUO.g_dpst   
            self.last_4_dtpst[4] = self.last_4_dtpst[3]
            self.last_4_dtpst[3] = self.last_4_dtpst[2]
            self.last_4_dtpst[2] = self.last_4_dtpst[1]
            self.last_4_dtpst[1] = self.from_EUO.g_dtpst   
        end
   
        if self.last_dpst ~= self.from_EUO.g_dpst then
            self.recent_dmg[4] = self.recent_dmg[3]
            self.recent_dmg[3] = self.recent_dmg[2]
            self.recent_dmg[2] = self.recent_dmg[1]
            self.recent_dmg[1] = self.from_EUO.g_dpst - self.last_dpst
            self.last_dpst = self.from_EUO.g_dpst
        end
   
        if SHOW_DAMAGE_DEALT_PER_SECOND_LINE == true then
            self:auxbox_prop_line("Dmg Dealt / Sec", string.format("%d", (self.last_4_dpst[1] - self.last_4_dpst[4])  / 4))
        end
        if SHOW_DAMAGE_TAKEN_PER_SECOND_LINE == true then
            self:auxbox_prop_line("Dmg Taken / Sec", string.format("%d", (self.last_4_dtpst[1] - self.last_4_dtpst[4])  / 4))
        end
        if SHOW_RECENT_DAMAGE_DEALT_LINES == true then
            self:auxbox_prop_line("Recent Dmg Dealt", "")
            self:auxbox_prop_line("", string.format("%d  %d  %d  %d", self.recent_dmg[4], self.recent_dmg[3], self.recent_dmg[2], self.recent_dmg[1]))
        end
    end

    function AuxboxWriter:auxbox_arrange_info()
        local filterTextLines = [[Hit the following keys
to filter item types:

w: weapons
W: wearables
p: potions
s: shields
u: usable
j: jewellry
f: food
U: unidentified
h: slot-head
t: slot-torso
l: slot-legs
b: slot-boots
g: slot-gloves
r: slot-rings
n: slot-neck
S: spells & scrolls
G: gems
R: reagants, etc
A: cancel filtering
v: cancel filtering]]

        local mode = self.from_EUO.d:get_statbox_mode()
        local txta = self:split(filterTextLines, "\n")

        if mode == self.from_EUO.SELECT_ABILITY then
            self:auxbox_prop_line("Hit F-key to bind currently")
            self:auxbox_prop_line("selected spell")
            self:auxbox_blank_line()
            self.from_EUO.auxbox_ability_binds()
        else
            for i = 1, #txta
            do
                self:auxbox_prop_line(txta[i])
            end
            self:auxbox_blank_line()
            self:auxbox_prop_line("Search with /")
            if mode == self.from_EUO.SELECT_READY then
                self:auxbox_prop_line("Press ENTER to equip")
            elseif mode == self.from_EUO.SELECT_BUY then       
                self:auxbox_prop_line("Press ENTER to buy")
            elseif mode == self.from_EUO.SELECT_BANK then
                self:auxbox_prop_line("Press ENTER to transfer one")
                self:auxbox_prop_line("Press Shift+ENTER for 10")
                self:auxbox_prop_line("Press TAB for whole stack")
            end
        end
    end

    function AuxboxWriter:split(s, plain_sep)
        -- Celerion's split-function (split at plain separator):
        local stringtable = {}
        local start = 1
        local found = string.find(s, plain_sep, start)
        while found ~= nil do
            table.insert(stringtable, string.sub(s, start, found - 1))
            start = found + string.len(plain_sep)
            found = string.find(s, plain_sep, start)
        end
        if start <= string.len(s) then
            table.insert(stringtable, string.sub(s, start))
        end
        return stringtable
    end

-- End of Class "AuxboxWriter"


Clock = {}

    function Clock:new()
        -- The class-magic again:
        local o = {}
        setmetatable(o, self)
        self.__index = self
        self.local_seconds_at_start = os.time()
        self.session_seconds = 0
        self.days_in_advance = 7
        return o
    end

    function Clock:set_sessions_seconds()
        local diff = os.difftime(os.time(), self.local_seconds_at_start)
        if diff > self.session_seconds then
            self.session_seconds = diff
        end
    end

    function Clock:get_local_time_in_configured_format()
        local timeformat = ""
        if REALWORLD_TIME_24_HOURS_FORMAT == true then
            timeformat = "%H:%M"
        else
            timeformat = "%I:%M"
        end
        if REALWORLD_TIME_WITH_SECONDS == true then
            timeformat = timeformat .. ":%S"
        end
        if REALWORLD_TIME_24_HOURS_FORMAT ~= true then
            timeformat = timeformat .. "%p"
        end
        return os.date(timeformat)
    end

    function Clock:get_session_seconds()
        self:set_sessions_seconds()
        return self.session_seconds
    end

    function Clock:get_session_time()
        self:set_sessions_seconds()
        return self:seconds_to_time_string(self.session_seconds, SESSION_TIME_WITH_DAYS, SESSION_TIME_WITH_SECONDS)
    end

    function Clock:get_double_xp_info()
        local oneday = 86400
        local twodays = 172800
        local info = {days = -1, timestr = ""}
        local utcttable = os.date("!*t")
        local restsecs = 0

        -- For testing:
        -- utcttable.wday = 6
        -- utcttable.day = 3
        -- utcttable.hour = 0
        -- utcttable.min = 0
        -- utcttable.sec = 0

        -- Do we have Double-XP? (For wday, Saturday is 7, Sunday is 1):
        if utcttable.wday == 7 and utcttable.day < 8 or
           utcttable.wday == 1 and utcttable.day <= 8 and utcttable.day >= 2
        then
            info.days = 0
            restsecs = twodays - (utcttable.hour * 3600 + utcttable.min * 60 + utcttable.sec)
            -- Sunday - One day has already passed:
            if utcttable.wday == 1 then
                restsecs = restsecs - oneday
            end
            info.timestr = self:seconds_to_time_string(restsecs, DOUBLE_XP_INFO_WITH_DAYS, DOUBLE_XP_INFO_WITH_SECONDS)
            return info
        end

        -- Double-XP in next days?
        if SHOW_DAYS_TO_DOUBLE_XP ~= true then
            return info
        end
        local i = 1
        local secs = 0
        local utcseconds = os.time(utcttable)
        local t = {}
        while i <= self.days_in_advance do
            secs = utcseconds + oneday * i
            t = os.date("*t", secs)
            if t.wday == 7 and t.day < 8 then
                break
            end
            i = i + 1
        end
        info.days = i
        if SHOW_HOURS_TO_DOUBLE_XP ~= true then
            return info
        end
        if info.days == 1 then
            restsecs = oneday - (utcttable.hour * 3600 + utcttable.min * 60 + utcttable.sec)
            info.timestr = self:seconds_to_time_string(restsecs, false, false)
        end
        return info
    end

    function Clock:seconds_to_time_string(secs, show_days, show_secs)
        local oneday = 86400
        local onehour = 3600
        local oneminute = 60
        local rest = 0
        local tstr = ""
        local t = {}
        if show_days == true then
            t.days = math.floor(secs / oneday)
            rest = secs - t.days * oneday
            t.hours = math.floor(rest / onehour)
            rest = rest - t.hours * onehour
            tstr = string.format("%02d:%02d:", t.days, t.hours)
        else
            t.hours = math.floor(secs / onehour)
            rest = secs - t.hours * onehour
            tstr = string.format("%02d:", t.hours)
        end
        t.mins = math.floor(rest / oneminute)
        rest = rest - t.mins * oneminute
        t.secs = math.floor(rest)
        if show_secs == true then
            tstr = tstr .. string.format("%02d:%02d", t.mins, t.secs)
        else
            tstr = tstr .. string.format("%02d", t.mins)
        end
        return tstr
    end

-- End of Class "Clock"


function auxbox()
    auxboxwriter:auxbox_loop()
end

auxboxwriter = AuxboxWriter:new()
Celerion
I'll be going back to Tibia next week.
 
Posts: 48
Joined: Sat Dec 15, 2012 6:29 am

Re: the scripting thread

Postby Keighn » Sun Nov 02, 2014 3:16 am

eggmceye wrote:using morty's maped cut/paste hack I have made a merged version of the Mage Tower ...

lvl259small.png


Is there still a limited map size or does this functional script bypass that?
Photobucket Suckz Monkey Nutz
User avatar
Keighn
Stop posting already --;
 
Posts: 4787
Joined: Sat Jun 26, 2004 10:13 am
Location: From the depths of Oregon he returns.... KEIGHN!!!!

Re: the scripting thread

Postby LordMortiferus » Sun Nov 02, 2014 5:33 am

You are still limited to 250x250, or what ever the numbers are, tiles for a map. In fact to use the copy&paste script effectively you have set the size of the map you want to paste to prior. The script will not resize your map if the chunk is larger than the destination.
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby Keighn » Sun Nov 02, 2014 7:01 am

Ah good to know. No mega mega 1kx1k maps. Someday perhaps.
User avatar
Keighn
Stop posting already --;
 
Posts: 4787
Joined: Sat Jun 26, 2004 10:13 am
Location: From the depths of Oregon he returns.... KEIGHN!!!!

Re: the scripting thread

Postby LordMortiferus » Sun May 17, 2015 9:59 pm

@Egg, @Ched:
Can I use the following function as a delay/sleeptimer to create custom heartbeats of less than a second without causing havoc to the server?
Code: Select all
function sleep(n)  -- seconds.milliseconds
  local t0 = os.clock()
  while os.clock() - t0 <= n do end
end


Edit:
I tested the sleep function using a switch that moves the player several tiles with sleep in between. It does work, however any action done by the player is delayed until the end of the switch script.
Here is the raft script atm:
Code: Select all
function sleep(n)  -- seconds.milliseconds
  local t0 = os.clock()
  while os.clock() - t0 <= n do end
end

function cc_waterslide(id,x,y,z)
   p = get_sent_ptr(id)
   map=get_map_ptr(z)
   local_msg(p,"\29You grab one of the rotten rafts, lower it into the water and hop onto it before the current takes it away.")
   
   local xys = {{9,61,0.5},{8,61,0.5},{7,61,0.5},{6,61,0.5},{5,61,0.5},{4,61,0.5},{3,61,0.5},{2,61,0.5},
   {2,60,1},{2,59,1},{2,58,1},{2,57,1},{2,56,1},{2,55,1},{2,54,1},{2,53,1},{2,52,1},{2,51,1},{2,50,1},{2,49,1},{2,48,1},{2,47,1},{2,46,1},
   {3,46,0.5},{4,46,0.5},{5,46,0.5},{6,46,0.5},{7,46,0.5},
   {8,48,0.4},{9,48,0.4},{10,48,0.4},{11,48,0.4},{12,48,0.4},{13,48,0.4},
   {12,52,0.3},{11,52,0.3},{10,52,0.3},{9,52,0.3},{8,52,0.3},{7,52,0.3},{6,52,0.3},
   {7,55,0.2},
   {8,57,0.2},{9,57,0.2},{10,57,0.2},{11,57,0.2},{12,57,0.2},{13,57,0.2},{14,57,0.2},{15,57,0.2},{16,57,0.2},{17,57,0.2},{18,57,0.2},
   {17,61,0.2},{16,61,0.3},{15,61,0.3},{14,61,0.3},{13,61,0.4},{12,61,0.4}}
   
   
   for i = 1,#xys do
   set_and_send_new_tile(xys[i][1], xys[i][2],z, 40)
   if i > 1 then
      set_and_send_new_tile(xys[i-1][1], xys[i-1][2],z, 126)
   end
   send_player_to_xy(p.id, xys[i][1], xys[i][2])
   if xys[i][1] == 12 and xys[i][2] == 52 then
      local_msg(p,"\29There seens to be a good spot ahead to reach the south shore!")
   elseif xys[i][1] == 12 and xys[i][2] == 61 then
      local_msg(p,"\29There seens to be a good spot ahead to reach the south shore!")
      sleep(0.2)
      set_and_send_new_tile(xys[i][1], xys[i][2],z, 126)
      local_msg(p,"\29The raft sinks! You better get on land quick!")
      return
   end
   update_everyones_fov(x,y,z)
   sleep(xys[i][3])
   end

end
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby Celerion » Wed May 20, 2015 9:34 am

LordMortiferus wrote:Can I use the following function as a delay/sleeptimer to create custom heartbeats of less than a second without causing havoc to the server?
....
Edit: I tested the sleep function using a switch that moves the player several tiles with sleep in between. It does work, however any action done by the player is delayed until the end of the switch script.

Yeah, this kind of sleep-functions use to freeze the whole program. Therefore GUI-kits use to offer different sleep-like functions (which keep the GUI intact). Perl/Tk, for example, offers the after()-method.
Now, EUO isn't written in Tk, but there should be something similar.

If I remember correctly, EUO keeps jumping into the script again and again. Maybe you could just set a global counter in the script. And return from the function unless the counter has reached a certain value.
Not sure, as I can't test anything here, of course.
Celerion
I'll be going back to Tibia next week.
 
Posts: 48
Joined: Sat Dec 15, 2012 6:29 am

Re: the scripting thread

Postby LordMortiferus » Thu May 21, 2015 2:12 am

Thanks for the info Cel. I am not totally sure what you mean though by jumping into the script again and again - If I am not mistaken that is only the case with a heartbeat function which is called every second. Other scripts are only executed once as far as I know. I wouldn't mind if the GUI locks up as long anything else, especially the server, is save.

You can use EftV to test scripts for EUO. Execute moasv.exe to open the debug window and then you can start EtfV to test stuff.
Edit: you can close moasv.exe with ctrl+c
Last edited by LordMortiferus on Thu May 21, 2015 5:45 am, edited 2 times in total.
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby LordMortiferus » Thu May 21, 2015 5:20 am

I found this page on LUA sleep functions

So in my example I am using a "Busy Wait" which is not performance friendly. Would the following function be any better:
Code: Select all
function sleep(n)
  local ntime = os.clock() + n
  repeat until os.clock() > ntime
end
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby LordMortiferus » Wed Jul 29, 2015 4:08 am

Rock paper shotgun has an interview with the creator of Brogue (roguelike game) about random dungeon creation. I paste a link to the interview here in case someone is interested and I may return to it and read it myself when I have more time.
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby LordMortiferus » Sat Feb 20, 2016 9:50 pm

For those who are eager to learn some scripting basics, Kris from Ancient Dos Games / Pixelmusement made a crash course video on old QBasic:
User avatar
LordMortiferus
Girls only want boyfriends who have great skills.
 
Posts: 759
Joined: Tue Dec 01, 2009 10:23 pm

Re: the scripting thread

Postby Keighn » Sun Feb 21, 2016 9:47 am

My brother in law was mentioning his interest in programming and he says he does it for fun. Oddly, the college he's attending has him run through the basics and math. Seems he was rusty enough to have to take the classes. I hadn't realized a lot of businesses will have various workers program while at home and send in the work. I guess contracting out in some degree.

I still read and look at it but just can't grasp the language. Couldn't even learn Spanish which is far simpler IMHO. Ah, if only gaming think tanking paid.
User avatar
Keighn
Stop posting already --;
 
Posts: 4787
Joined: Sat Jun 26, 2004 10:13 am
Location: From the depths of Oregon he returns.... KEIGHN!!!!

Re: the scripting thread

Postby Devlin » Wed Feb 21, 2018 9:44 pm

Using colours in auxbox causes the right-align padding to break (i suspect because of the string length being artificially padded by the colour codes)

Image

Has anyone got a fix to take the colour codes into account and stop them being counted by the auxbox_prop_line() function?
User avatar
Devlin
I used to bake rockcakes in my bakery.
 
Posts: 188
Joined: Tue Jan 22, 2008 12:30 pm
Location: United Kingdom

Re: the scripting thread

Postby Chedich » Sat Feb 24, 2018 5:40 am

Devlin wrote:Using colours in auxbox causes the right-align padding to break (i suspect because of the string length being artificially padded by the colour codes)

Has anyone got a fix to take the colour codes into account and stop them being counted by the auxbox_prop_line() function?


Threw this together for you. I haven't really tested it properly though, so feel free to give some feedback.

Code: Select all
function auxbox_prop_line(prop_name, prop_val)
   local pvl=0
   if prop_name==nil then prop_name="" end
   if prop_val==nil then prop_val="" end
   local filler = string.rep(" ", 25 - ched_propline_strlen(prop_name) - ched_propline_strlen(prop_val))
   auxbox_next_line = auxbox_next_line + 1
   d:auxbox_set_line(auxbox_next_line, string.format("%s %s %s", prop_name, filler, prop_val))
end

function ched_propline_strlen(prop_strlen)
   local string_length = 0
   if type(prop_strlen) == "number" then
      prop_strlen = tostring(prop_strlen)
   end
   for i=0, #prop_strlen do
      local string_byte = prop_strlen:byte(i)
      if string_byte ~= nil then
         if string_byte == 0x7B then
            string_length = string_length - 4
         else
            string_length = string_length + 1
         end
      end
   end
      
   return string_length
end
Chedich
Post in swahili or SHUT THE FUCK UP!
 
Posts: 235
Joined: Wed Jan 14, 2004 12:51 am

PreviousNext

Return to EUO Development

Who is online

Users browsing this forum: No registered users and 3 guests