Page 1 of 2

Shaiya - WayPoint System

Posted: Thu Oct 09, 2008 11:21 pm
by zer0
I'm working on a waypoint system for shaiya, the functions are pretty simple rotate_to(degrees) and move_to(pos) functions (pos is table w/x,y,z values).

Here is a extract of some of the code. You won't b able to compile, but is pretty easy to read.

Code: Select all

function Avatar:move_to(pos)
    local l_check_interval = 250
    local l_pos_cur = self:get_position()
    debug_message("pos (" .. math.floor(l_pos_cur.x) .. "," .. math.floor(l_pos_cur.z) .. ")")
    debug_message("move_to (" .. math.floor(pos.x) .. "," .. math.floor(pos.z) .. ")")
    local l_pos_relative = {
        x=(pos.x - l_pos_cur.x),
        y=(pos.z - l_pos_cur.z),
    }
    local l_deg = get_quadrantal_angle(l_pos_relative)
    self:rotate_to(l_deg)
    local l_tolerance = 5
    
    local l_pos_new = {
        min_x=(pos.x - l_tolerance),
        max_x=(pos.x + l_tolerance),
        min_z=(pos.z - l_tolerance),
        max_z=(pos.z + l_tolerance),
    }
    
    while (true) do
        l_pos_cur = self:get_position()
        --debug_message("cur_pos (" .. math.floor(l_pos_cur.x) .. "," .. math.floor(l_pos_cur.z) .. ")")
        if (l_pos_cur.x >= l_pos_new.min_x and 
            l_pos_cur.x <= l_pos_new.max_x and
            l_pos_cur.z >= l_pos_new.min_z and 
            l_pos_cur.z <= l_pos_new.max_z)then
                break;
        end
        self:move(DIRECTION_UP, 250)
        coroutine.yield()
    end
    debug_message("moved_to (" .. math.floor(l_pos_cur.x) .. "," .. math.floor(l_pos_cur.z) .. ")")
end

function Avatar:rotate_to(degrees)
    local l_pos_cur = self:get_rotation(l_pos)
    local l_deg_cur = get_quadrantal_angle(l_pos_cur)
    debug_message("deg_cur: " .. l_deg_cur)
    debug_message("deg_new: " .. degrees)
    local l_increment = 1
    local l_pos_new = {
        x=math.cos(math.rad(degrees)),
        y=math.sin(math.rad(degrees)),
    }
    --debug_message("l_x: " .. l_pos_new.x .. ", " .. "l_y: " .. l_pos_new.y)

    local l_tolerance = (l_increment / 90)
    local l_direction = get_rotate_direction(l_deg_cur, degrees)
    l_pos_new.min_x = l_pos_new.x - l_tolerance
    l_pos_new.max_x = l_pos_new.x + l_tolerance
    l_pos_new.min_y = l_pos_new.y - l_tolerance
    l_pos_new.max_y = l_pos_new.y + l_tolerance

    while (true) do
        self:spin(l_direction, l_increment)
        l_pos_cur = self:get_rotation(l_pos)
        --debug_message("l_cx: " .. l_pos_cur.x .. ", " .. "l_cy: " .. l_pos_cur.y)
        if (l_pos_cur.x >= l_pos_new.min_x and 
            l_pos_cur.x <= l_pos_new.max_x and
            l_pos_cur.y >= l_pos_new.min_y and 
            l_pos_cur.y <= l_pos_new.max_y)then
                break;
        end
        coroutine.yield()
    end
    --debug_message("l_cx: " .. l_pos_cur.x .. ", " .. "l_cy: " .. l_pos_cur.y)
    --Avatar:move(DIRECTION_UP, 500)
    l_deg_cur = get_quadrantal_angle(l_pos_cur)
    debug_message("l_deg_cur: " .. l_deg_cur)
end

function get_quadrantal_angle(pos)
    -- find out the opposite angle of the right sided triangle.
    local l_deg_cur = 90 - (math.deg(math.atan(pos.x / pos.y)))
    debug_message("l_deg_cur: " .. l_deg_cur)
    -- If it's in the 3rd or 4th Quadrant then add 180 degrees.
    if (get_quadrant(pos) >= 3) then
        l_deg_cur = l_deg_cur + 180
    end
    return round(l_deg_cur, 0) % 360
end

function get_quadrant(pos)
    if (pos.x >= 0) then 
        if (pos.y >= 0) then
            return 1
        else
            return 4
        end
    else
        if (pos.y >= 0) then
            return 2
        else
            return 3
        end
    end
end
Everything works except one function, I need to work out if the rotation should occur clockwise (CW), or counter-clockwise (CCW), depending on which will be closest.
I'm lost on how to do it, here is the prototype:

Code: Select all

--[[ 
  Get the closest rotation direction.
  @param degree The current degrees that object is facing (0-360).
  @param degree_new The new degree that object wants to face (0-360).
  @return Rotation direction, DIRECTION_RIGHT for ClockWise (CW), DIRECTION_LEFT for CCW.
]]--
function get_rotate_direction(degree, degree_new)
  -- if should rotate left
  --  return DIRECTION_LEFT
  -- else 
  --  return DIRECTION_RIGHT
end
Anyone feel like filling in the solution for the function?

This thread had a issue just like this, though I'm not sure which code I should port.
http://board.flashkit.com/board/showthread.php?t=766397

Re: Shaiya - WayPoint System

Posted: Fri Oct 10, 2008 12:56 am
by zer0
nvm, I found the issue, I was using degrees instead of radians. Here is the function to all those interested.

Code: Select all

--[[
  Get the closest rotation direction.
  @param degree The current degrees that object is facing (0-360).
  @param degree_new The new degree that object wants to face (0-360).
  @return Rotation direction, DIRECTION_RIGHT for ClockWise (CW), DIRECTION_LEFT for CCW.
]]--
function get_rotate_direction(degree, degree_new)
    l_d_rad = math.rad(degree)
    l_d_new_rad = math.rad(degree_new)
    local l_diff = math.atan2(math.sin(l_d_new_rad-l_d_rad),math.cos(l_d_new_rad-l_d_rad));
    --debug_message("l_diff="..l_diff)
    if (l_diff >= 0) then
        return DIRECTION_RIGHT
    else
        return DIRECTION_LEFT
    end
end

Re: Shaiya - WayPoint System

Posted: Fri Oct 10, 2008 5:11 am
by Administrator
Wow. This is incredibly similar to my Holic code. Though, mine has quite a bit more advanced AI built into it (ie. constructing detour paths around obstructions) (which is not necessarily a good thing; as it just seems to keep giving me more bugs to work out).

Well, you already solved it, but here's what I did anyways.

Code: Select all

function angleDifference(angle1, angle2)
  if( math.abs(angle2 - angle1) > math.pi ) then
    return (math.pi * 2) - math.abs(angle2 - angle1);
  else
    return math.abs(angle2 - angle1);
  end
end
Then you can just measure which angle is smaller, and rotate in that direction.

Code: Select all

        angleDif = angleDifference(PlayerAngle, targetAngle);

        if( angleDifference(targetAngle, PlayerAngle + 0.01) < angleDif ) then
          -- rotate right
        else
          -- rotate left
        end

Re: Shaiya - WayPoint System

Posted: Fri Oct 10, 2008 7:37 pm
by holycow1
this is an awesome idea. I was thinking of the same thing when testing out deaznracers fighter v 1. if its set to only attack certain colors of mobs, wouldnt it quit working once you level up and the mobs are no longer the colors specified. a bot that would run around the map to certain areas is an excellent idea. there are maps on the aeria forum that gives monster spawn points and levels if that helps.

Re: Shaiya - WayPoint System

Posted: Fri Oct 10, 2008 11:06 pm
by Administrator
Could you provide a link to these maps? They might be of some assistance here (depending on how detailed zero plans to make his waypoint system).

Re: Shaiya - WayPoint System

Posted: Sat Oct 11, 2008 12:33 am
by holycow1
sure thing elverion

http://forums.aeriagames.com/viewtopic. ... 74f7b291aa

not sure if you guys have seen this forum
its got alot of information on the game in general

so far ive been reading mpc cheetah and cheat engines forums looking for stuff to tinker with
just havin fun watchin deaz's bot thrash mobs while i watch house ^^

still new to CE but finished the tutorial and kinda figured out addresses still trying to figure out how to make a trainer

Re: Shaiya - WayPoint System

Posted: Sun Oct 12, 2008 1:28 am
by zer0
here is how I think I'll create the algorithm.

- In the maps main trails will have mini-paths that consist of several nodes. They are basically small paths to get from one main trail junction to the next.
- their will be additional branch nodes, set off of a main trail node that have set levels that lead to similar level mobs.
- once the avatar gets to a grind spot his on his own, until he levels.
- then traverse the mob path backwards to get back on the main trail.
- continue onwards.
- when a main trail junction occurs, randomly decide which one to choose (this could be improved by a weighting system, but for now it would be fine).

Dynamic collision detection would be advantageous, I have a crude version for when mobs are grinding, but getting jammed on paths is a red flag for being a bot, which is why a node system may be more appropriate.

This is a good mob locator:
http://shaiya.kendor.org/shaiya.php

Re: Shaiya - WayPoint System

Posted: Sun Oct 12, 2008 3:12 am
by Administrator
One thing I did was to constantly check your X,Y coordinates against previous (say, half a second ago) coordinates. If they do not differ by some amount, then assume the character is stuck. Depending on the situation, it would construct a set of temporary waypoints around the obstruction.

Pretty much, this:
path.GIF
path.GIF (1.63 KiB) Viewed 7409 times
The player (blue dot) is trying to get to the next waypoint (green dot). However, the obstruction (red block) is in the way. We hit it, and stopped moving. So we construct a set of temporary waypoints (red dots) around the object. The first waypoint could be positioned directly behind the player (angle + PI). The next could be a some angle that would still position the waypoint "behind" the player, but also move them a bit to one side. The final waypoint would continue to move them further out to the side, and a bit in front of the object (hopefully, behind the object, too). The temporary waypoints should provide a relatively "smooth" rotation rather than be very rigid and bot-like. Once that final temporary waypoint is reached, continue the normal path.

Re: Shaiya - WayPoint System

Posted: Mon Oct 13, 2008 8:00 am
by zer0
For smaller areas that works well, but to traverse long distances, I don't think it would work so well.

I have done something a little similar in my collision detection when in grinding mode, basically the avatar moves back a bit, then either turns, left or right, for X amount, then tries again. For smaller objects it works fine. For large sections though your in trouble. :)

The waypoint system works extremely well, but it's time consuming to list all the nav points. Here is what the array looks like.

Code: Select all

        main_path={
            --[]={x=,y=,z=,child={}},
            [1]={x=177,z=396,child={2}},
            [2]={x=246,z=381,child={3},mob={3}}, -- J
            [3]={x=281,z=363,child={4}},
            [4]={x=371,z=323,child={5}},
            [5]={x=434,z=304,child={6}},
            [6]={x=530,z=308,child={7}},
            [7]={x=633,z=371,child={11,22},mob={4}}, -- J
            -- Aridon North Gate.
            [8]={x=264,z=225,child={9,50}},
            [9]={x=261,z=249,child={10}},
            [10]={x=251,z=337,child={2}},
            [11]={x=689, z=443, child={12,40}}, -- J
            [12]={x=790, z=507, child={13}}, -- J
            [13]={x=871, z=462, child={14}},
            [14]={x=1002, z=461, child={15}},
            [15]={x=1054, z=421, child={16}},
            [16]={x=1151, z=408, child={17}},
            [17]={x=1247, z=310, child={18}},
            [18]={x=1262, z=227, child={19,27}}, -- J
            [19]={x=1159, z=236, child={20,18},mob={6}},
            [20]={x=1071, z=284, child={1000,19}},
            -- Artlum Mine N
            [21]={x=955, z=277, child={24,1000}}, -- J
            [22]={x=708, z=327, child={23}}, -- J
            [23]={x=819, z=290, child={21},mob={5}},
            [24]={x=988, z=215, child={21},mob={7}},
            -- Artlum Mine Inside (not good to go in, too much jamming).
            --[25]={x=988, z=177, child={26,24}},
            --[26]={x=986, z=123, child={25},mob={5}},
            [27]={x=1317, z=165, child={28}},
            [28]={x=1345, z=164, child={29}},
            [29]={x=1366, z=193, child={30}},
            -- Frotainer Vill.
            [30]={x=1363, z=304, child={31}},
            [31]={x=1346, z=408, child={32}},
            [32]={x=1365, z=444, child={33}},
            [33]={x=1365, z=553, child={34}},
            -- Ruins - DoomFire
            [34]={x=1345, z=665, child={1001}, mob={8}},
            [35]={x=1370, z=759, child={36}},
            [36]={x=1373, z=829, child={37}, mob={8}},
            [37]={x=1384, z=983, child={38}, mob={9}},
            [38]={x=1365, z=1062, child={200}, mob={10}},
            
            --
            [40]={x=553, z=482, child={41}},
            [41]={x=436, z=556, child={42}},
            [42]={x=359, z=545, child={43}},
            [43]={x=269, z=539, child={44}},
            [44]={x=302, z=611, child={45}},
            -- Vruion Forest S
            [45]={x=340, z=665, child={46}}, -- J
            [46]={x=245, z=680, child={47}},
            [47]={x=122, z=746, child={48}},
            [48]={x=103, z=867, child={49},mob={8}},
            [49]={x=105, z=964, child={50},mob={9}},

            -- Aridon. E Gate
            [50]={x=330, z=179, child={51}},
            [51]={x=395, z=141, child={52}},
            [52]={x=443, z=143, child={53}},
            [53]={x=573, z=168, child={54}},
            [54]={x=624, z=207, child={55}},
            [55]={x=620, z=278, child={56}},
            [56]={x=531, z=292, child={6}},
            
            -- Arteria Blood Lab Area
            [60]={x=866, z=577, child={70}},
            [70]={x=781, z=626, child={71}},
            [71]={x=672, z=602, child={72,76}, mob={6}}, -- J
            [72]={x=540, z=574, child={73}},
            [73]={x=425, z=665, child={74}},
            [74]={x=425, z=665, child={45}},
            [75]={x=425, z=665, child={45}},
            [76]={x=672, z=690, child={77}},
            [77]={x=607, z=720, child={78}},
            [78]={x=490, z=705, child={79}},
            [79]={x=317, z=762, child={80}},
            [80]={x=244, z=837, child={81}},
            [81]={x=170, z=895, child={82}},
            [82]={x=200, z=990, child={}},
As you can see things are quite messy when I make mistakes and have to add another nav point. I think I'm going to have to make an application that is a GUI Tool for each map, and where you can place points, and the directions they take, and save it, probably in XML format, since I know that I can convert that fairly easily to lua.

Re: Shaiya - WayPoint System

Posted: Thu Oct 23, 2008 6:28 pm
by zer0
I've created the Waypoint GUI Tool. I'll be testing it soon.

Atm I've got higher priorities, so I have to come back to it later, probably a month or so.

Re: Shaiya - WayPoint System

Posted: Thu Oct 23, 2008 7:17 pm
by Administrator
You've made a GUI tool? Nice. How does it work? Do you have any screenshots?

Re: Shaiya - WayPoint System

Posted: Sun Oct 26, 2008 2:29 am
by zer0
Sure mate here it is.

Image

It uses and XML Map Waypoint format, to load and save data, and can export the data using XSLT, which in my case, I've used to transform the data into Lua.

Re: Shaiya - WayPoint System

Posted: Sun Oct 26, 2008 11:40 am
by Administrator
Oh, very nice. Maybe I could look into adding native XML support to MicroMacro. I'm sure that would be far more convenient than having to convert the file every time.

Re: Shaiya - WayPoint System

Posted: Mon Oct 27, 2008 1:17 am
by zer0
Yes that would be much appreciated.

I think there is a Lua XML Library that you could maybe add.
http://www.keplerproject.org/luaexpat/i ... l#overview

That way I could have all the Script data stuff in XML, and separate it from the code without having to apply XSLT transformation, and they could be changed without having to re-run the scripts. Yes that would be brilliant. :mrgreen:

Re: Shaiya - WayPoint System

Posted: Mon Oct 27, 2008 6:02 pm
by Administrator
I've added LuaExpat to MicroMacro. You should only need to update micromacro.exe with the attached file. You'll have to refer to LuaExpat's help system until I can write a small wrapper for it.

Just a bit off topic here, but I gave a quick look at your project, and it seems you're including of lib/class.lua is redundant. There is a 'classes' module that is almost identical to that. You should just be able to un-include that file, and it should all still work. Or was there some other reason you included it (compatability, improvements, etc.)?

Re: Shaiya - WayPoint System

Posted: Mon Oct 27, 2008 7:21 pm
by zer0
Just didn't know, I'm still using a fairly old version of MM from memory.

Awesome about the XMLExpat, I'll have to play with it over the next few weeks, I haven't used the library yet so I'm not very familiar with it.

edit:
commenting the class.lua worked fine, thanks for the heads up. I didn't realise there was a class module. ;)

Re: Shaiya - WayPoint System

Posted: Tue Oct 28, 2008 10:48 am
by Administrator
I've wrote up a simple module for handling XML easily. Here's an example:

test.xml

Code: Select all

<root name="Root" type="Example">
	<elem1>
		<subelement value="1" />
		<subelement value="2" />
		<subelement value="3" />
	</elem1>

	<elem2 number="1234" string="This is a string" />

	<elem3>Element 3 has a text value</elem3>
</root>

Code: Select all

  local root = xml.open(getExecutionPath() .. "/test.xml");
  printf("root._NAME: %s\n", root:getName()); -- "_name" should be 'root'
  printf("root.name: %s\n", root["name"]);   -- "name" will be set in XML


  local elem1 = root:getElement("elem1");
  elements = elem1:getElements();
  printf("\n---ELEM1---\n");
  for i,v in pairs(elements) do
    local name = v:getName();
    local value = v["value"];
    printf(" ==> [%s]: %s\n", name, value);
  end


  local elem2 = root:getElement("elem2");
  printf("\n---ELEM2---\n");
  printf("elem2.number: %d\n", elem2["number"]);
  printf("elem2.string: %s\n", elem2["string"]);

  local elem3 = root:getElement("elem3");
  printf("\n---ELEM3---\n");
  printf("elem3._VALUE: %s\n", elem3:getValue());
And the output of this is:
root._NAME: root
root.name: Root

---ELEM1---
==> [subelement]: 1
==> [subelement]: 2
==> [subelement]: 3

---ELEM2---
elem2.number: 1234
elem2.string: This is a string

---ELEM3---
elem3._VALUE: Element 3 has a text value
xml.open() opens, parses, and returns an XML data object. It is, by default, the 'root' object (which need not necessarily be 'root'). To access it's children, you can use getElement("name") (returns element by name), getElement(index) (returns element at 'index'), or getElements() (returns all elements in a table). If an element cannot be found using getElement() or getElements(), it returns nil.

Each node in the XML data tree has a _NAME and a _VALUE. These should be accessed using getName() and getValue(), and should not be changed manually. You should avoid using XML elements with attributes named _NAME or _VALUE, as this will screw things up. _NAME will always be set to the node's name from the XML file. _VALUE will be set on text objects (see elem3 in the example). Each element's attributes can be accessed directly via [] operators (ie. myElement["attribute_name"]).

Are these specifications acceptable, or does anybody have any additional needs and/or concerns?

Re: Shaiya - WayPoint System

Posted: Fri Oct 31, 2008 12:04 am
by zer0
Concerning this part..

Code: Select all

  printf("elem2.number: %d\n", elem2["number"]);
  printf("elem2.string: %s\n", elem2["string"]);
Did you know with tables, you can do this too?

Code: Select all

  printf("elem2.number: %d\n", elem2.number)
  printf("elem2.string: %s\n", elem2.string)
It's only syntactic sugar, but it makes your code a little easier to read, and is less typing.

I've noticed that you in the habit of coding C++ style in Lua, that's a habit maybe u should break. It's probably difficult for you, since you coding in both languages at the same time. I was initially coding like C++ too, but I forced myself to code like Lua, and I think my code looks a little easier to read as a result.

Can you post up the Simple XML Module? :)

Re: Shaiya - WayPoint System

Posted: Sat Nov 01, 2008 12:35 am
by Administrator
It's only syntactic sugar, but it makes your code a little easier to read, and is less typing.
I suppose. The dot(.) operator actually was used in the module. I try to avoid it when working with a strict table, and save it for 'classes' (which are just tables, anyways, I guess), but in reality, these elements are classes, too.
I've noticed that you in the habit of coding C++ style in Lua, that's a habit maybe u should break. It's probably difficult for you, since you coding in both languages at the same time.
Really? I thought quite the opposite, actually. Most of my scripts are devoid of classes, and MicroMacro is done more in a procedural way than object oriented. I can tell you from experience, though, that trying to over object-orient something makes things very difficult. I concern myself with what makes logical sense (at least to me) rather than force myself to one style or another.

Anyways, I've attached the module. Place it in lib/mods and you'll need to add a single line into lib.lua to load the module.

Code: Select all

require("xml");
You'll see the other require statements near the top. Just place that line in there and you should be fine. Remember you'll need to close and restart MicroMacro before it'll load lib.lua and, in turn, xml.lua.


The module is still subject to change. I might modify the accessing of attributes a bit, which would speed up all function calls and be a bit cleaner. Rather than using the [] or . operators, you would access it through function getAttribute(name). The difference would be that all attributes would be stored in a sub-table _ATTRIBUTES. This speeds things up by not having to run potentially lengthy queries over a large number of attributes (read: skip over _NAME, _VALUE, and internal variables). It also aids in future compatibility if something needs to be modified in the class. And, finally, it frees up _NAME and _VALUE to be used without screwing up.

Re: Shaiya - WayPoint System

Posted: Sat Nov 01, 2008 6:07 pm
by zer0
Thanks got works great.

Only a minor issue, when file can't be opened it throws an error on mods/xml.lua:158

Code: Select all

attempt to call global 'error' (a nil value)
It is a lua native function, so I couldn't work it out, perhaps u know why? :/


Otherwise, the mod works great, here is my code to open the waypoint.xml:

Code: Select all

function Xml_data:loadWaypoints(file)
    local l_xml = xml.open(file)

    local l_map = {}

    local l_xml_map = l_xml:getElements("map")
    local l_map_child_name
    local l_map_name
    local l_wp_name
    local l_wp_level
    local l_wp_links
    for k, map_child in pairs(l_xml_map) do
        l_map_child_name = map_child:getName() 
        --debug_message(l_map_child_name)
        
        if (l_map_child_name == "name") then
            l_map_name = map_child:getValue()
            l_map[l_map_name] = {}
        elseif (l_map_child_name == "waypoint") then
            l_xml_waypoint = map_child:getElements("waypoint")
            l_wp_name = map_child:getElement("name"):getValue()
            l_map[l_map_name][l_wp_name] = {}
            l_map[l_map_name][l_wp_name].x = tonumber(map_child:getElement("position"):getElement("x"):getValue())
            l_map[l_map_name][l_wp_name].z = tonumber(map_child:getElement("position"):getElement("y"):getValue())
            if (map_child:getElement("level")) then
                l_wp_level = map_child:getElement("level"):getValue()
                l_map[l_map_name][l_wp_name].level = tonumber(l_wp_level)
            end
            if (map_child:getElement("links")) then
                l_wp_links = map_child:getElement("links"):getElements()
                l_map[l_map_name][l_wp_name].links = {}
                for k, wp_link in pairs(l_wp_links) do
                    table.insert(l_map[l_map_name][l_wp_name].links, wp_link:getValue())
                    --debug_message("link[" .. k .. "]: " .. wp_link:getValue())
                end
            end
        end
    end
    return l_map;
    -- Test a Waypoint
    --[[local l_waypoint = "waypoint_52"
    debug_message("waypoint: (" ..
        l_map[l_map_name][l_waypoint].x .. ", " ..
        l_map[l_map_name][l_waypoint].z .. ", " ..
        --l_map[l_map_name][l_waypoint].level .. ", " ..
        "links(" ..
            l_map[l_map_name][l_waypoint].links[1] .. ", " ..
            l_map[l_map_name][l_waypoint].links[2] .. ", " ..
        ")" ..
        ")")]]
end
My code is enifficient and messy, I'll have to fix it up properly when I get the time.