Bit Blot Forum

Aquaria => Modding => Topic started by: Titch on January 08, 2009, 01:32:38 pm

Title: Form modification/Creation
Post by: Titch on January 08, 2009, 01:32:38 pm
I want to get into modding, so I thought I would start by modifying one of the existing forms and perhaps creating a new one based on the modifications I've made.

I do know a bit about scripting. I've done quite a bit of programing and scripting before, including some LUA based stuff and ActionScript as well as doing a total conversion mod for Unreal. I'm just having trouble identifying which script files I should be looking at to be able to change a forms abilities and stats.

Basically my plan is to add a new right click ability to Sunlight form and some kind of rock throwing skill to Beast form, although it may change if these things turn out to be too complicated. It's mostly so I can do some interesting things whilst I get to grips with the scripting system than for any kind of full blown mod.

Thanks in advance for any help :)
Title: Re: Form modification/Creation
Post by: Chibi on January 08, 2009, 03:12:48 pm
You can already throw rocks in Beast Form, but you have to eat the creatures that live in rock huts and lob stones at Naija.
Title: Re: Form modification/Creation
Post by: Titch on January 08, 2009, 04:22:27 pm
I mean the big rock objects you pick up using Bind. I'm thinking something along the lines of being able to kick them by springing off them or similar. It might lead to some broken physics but it could make for some fun aquabatics.
Title: Re: Form modification/Creation
Post by: Danger Mouse on January 08, 2009, 04:35:13 pm
I think that would kind of detract from the current beast form since it's designed around eating other creatures for their abilities... but if you can get some practice at scripting to accomplish your goal, I can't see how that could hurt. At least you'll have some experience towards making new forms. I eventually will be getting to that point in my mod as well. So I'll definitely be watching your progress really closely as I am already working on other aspects of my mod. Share your creations with us and ask questions if you are having trouble. Good Luck! :)
Title: Re: Form modification/Creation
Post by: Titch on January 08, 2009, 04:41:50 pm
Well I agree it would make beast form over featured, but it doesn't really seem to fit well with any of the other forms. It might work with Nature/Sun form since they both have really limited combat capability but doesn't really make logical sense. If I can at least get it going I'll probably integrate it into some new form designed specifically for ninja like aquatic maneuvers or the like.
Title: Re: Form modification/Creation
Post by: Danger Mouse on January 08, 2009, 04:53:15 pm
Hmmm, Ninja Naija.... lol :) If you want to see some more ideas that have been made by me in the mods section, check out my thread for Aquaria: Lost Treasures. Maybe those would give you some more ideas, or if you even wanted you could try to make them. As I haven't gotten to that point in the mod creation process yet.
Title: Re: Form modification/Creation
Post by: Titch on January 08, 2009, 09:52:36 pm
Yeah, I've seen the various mods in process. I'm hoping I'll be able to offer some help once I'm more at home with scripting for Aquaria. It is what I'm naturally inclined to do anyway.

Anywho. I've managed to make a song and bind it up with a callback in game, so singing it will change your form. I've made a few bits for the skin for the form. I'm still not sure how to make new forms though or examine . There doesn't seem to be an XML file with a list and they don't seem to be in the entities of common folder, there isn't a template for them either. You could fake it with a setCostume(). Even doing that I'm not sure how to tie up inputs/abilities with costumes, it could mean a pretty ugly hack to get it working.
Title: Re: Form modification/Creation
Post by: Hiro on January 08, 2009, 11:37:29 pm
I know what you mean. I've seen the file that has a list of all the songs, but I've never found a way to change what the songs do... I think its something we might need Alec's help with. They did say you'd be able to make your own songs, so surely there must be a way to make them do things.
Title: Re: Form modification/Creation
Post by: Titch on January 09, 2009, 12:02:59 am
Well I've got it recognizing my own song. It's actually programing the functions of the new form state without having to do a horrible kludge that bothers me.

In songs.xml :
<Song idx="101" name="Ninja Form" slot="12" notes="4 5 3 2" script="1" vox="ninja"/>

Which is N,NW,NE,S notes (I wish their where note smilies so I could write them out better, oh well).

In songs.lua
Code: [Select]
dofile("scripts/entities/entityinclude.lua")

n=0

function castSong(index)
    n=getNaija()
    if index == 100 then
        spawnParticleEffect("bigredexplode",entity_x(n),entity_y(n))
        playSfx("ninja", 1000)
        setCostume("ninja_naija")
    end
end
EDIT 6-Billion : I worked out that my script wasn't working because I wrote najia instead of naija. Dyslexia + Programming. Not the best of bed partners.

In node_learnsong.lua
Code: [Select]
n= 0
isNinjalearned=false

function init(me)
n = getNaija()     
end


function update(me, dt)

if isNinjalearned==false then
 if node_isEntityIn(me, n) then
   setControlHint("You've found a new song! You can now use NINJA form!", 0, 0, 0, 16)
   learnSong(101)
   learnSong(102)
   isNinjalearned=True
 end
end

end

So now I've got a song that triggers a costume change and a special effect, I even got it to bring up and icon by looking at the copy of the native mod stuff. Now I've got to work out the callback for when Naija is being clicked on so I can switch the costume back and re-enable singing so it seems like a form. Once I've got that stuff I guess I'll post my progress. :)
Title: Re: Form modification/Creation
Post by: Hiro on January 09, 2009, 02:29:56 am
Well, looks like you're beyond me already (and that's even with Edwards' help for the Native mod song).
But even with what you have with the costume change, I still have no idea how you're gonna change what right click does (ie. for like the form shot or something rather than singing)...
Title: Re: Form modification/Creation
Post by: Titch on January 09, 2009, 02:33:28 am
Well I'm busy scraping the google cache of the old Wiki together and dumping it into the new Wiki so hopefully I can find out. I have a feeling the Naija entity will make a callback when it's clicked on with the right and left mouse buttons, its just a case of working out what that callback is...
Title: Re: Form modification/Creation
Post by: Danger Mouse on January 09, 2009, 05:05:32 am
That's really amazing stuff there titch... maybe you could help me with the forms for my mod?

The more talent I'm seeing around here for scripting the more I'm thinking that we should all put our heads together and assign jobs within a project, and make a colaberated mod. I'm sure it would end up really impressive instead of just the work of one individual. After all, even Alec had a couple of partners. :)
Title: Re: Form modification/Creation
Post by: Edwards on January 09, 2009, 05:35:46 am
Well I'm busy scraping the google cache of the old Wiki together and dumping it into the new Wiki so hopefully I can find out. I have a feeling the Naija entity will make a callback when it's clicked on with the right and left mouse buttons, its just a case of working out what that callback is...
This may or may not help, but if Naija is in a form that can be charged, calling avatar_getSpellCharge() returns the time that the player has been holding down the charge button.  I'm still trying to find some way to use it (or something similar) in a non-charging form (such as the normal form).

Regarding callbacks, I can't find any reference anywhere to callbacks for clicking on Naija, or even for files where said callbacks might be used.  I suspect some degree of kludging might be needed.  (Admittedly, I don't have the wiki on-hand, but I do have a list of all the functions.)

[EDIT] changeForm() can set you to forms 8 and up (unused in the main game) without crashing, although no change in appearance occurs.  You stop being able to sing, though, so you probably are actually in a new form.  There may be a file somewhere that will allow you to take advantage of this- I'm looking for that right now

- Edwards
Title: Re: Form modification/Creation
Post by: Danger Mouse on January 09, 2009, 06:09:32 am
Ooo,... that could be useful. :)
Title: Re: Form modification/Creation
Post by: Edwards on January 09, 2009, 07:48:05 am
So, yeah- the best I can come up with is an unpleasant kludge involving setCostume(), changeForm(), and either nodes using isRightMouse(), timerBeast-like entities (see Big Energy Battle version 1.2.1) with the activation property set (see seahorse.lua), or some combination of the two.  On the plus side, it would probably be functional, and would interface passably with the existing form system, due to the use of changeForm()-  just have whatever the helper node/entity is change the costume back if it notices that Naija's form has been set back to normal.  As a warning, using setCostume when Naija is not in normal form will revert her to normal form, so you'll need to keep track of that.

As for changing existing forms, that would be an even uglier kludge- adding abilities wouldn't be too bad, but changing existing abilities (except those that spawn new entities, like Nature Form) would likely be most easily done by creating an entirely new form. :-\

- Edwards
Title: Re: Form modification/Creation
Post by: Titch on January 09, 2009, 06:22:36 pm
Thanks Edwards, any chance I could get a copy of that functions list?. By using setForm(9) with the costume change it's starting to look like a new form.

I'm using Songs.lua to call the new form, I'm not sure if putting a check to see if her form has changed will work there since it seems like songs is only executed when you are singing (unless of course reverting you form is a zero note song, then it might get called anyway). So I'll probably have to make like TimerBeast and stick a node on top of Naija to handle everything. Might be a little tricky to tie up neatly, but at least I could put the new ability functions inside the node so it's all neat like. :)

http://www.niftyhat.com/posted_stuff/ninja_form.zip

The transformation song is:
 (http://www.niftyhat.com/posted_stuff/notes/notesymbol4.png) (http://www.niftyhat.com/posted_stuff/notes/notesymbol5.png) (http://www.niftyhat.com/posted_stuff/notes/notesymbol3.png) (http://www.niftyhat.com/posted_stuff/notes/notesymbol2.png)
Mostly because I liked the melody it created.

After some fits and starts I got it working. Admittedly the form doesn't do anything right now, its just a costume that behaves like a form right now. I've got to do some intermediate functions to manage the new forms and stuff. You can see basically how I pulled it off (and look at the form skin :))
Title: Re: Form modification/Creation
Post by: Particlese on January 15, 2009, 05:29:15 am
This is great news!  I'll have to take a look at it this weekend.  Are you having problems with Naija flipping when you change costumes?  There were two (http://www.bit-blot.com/forum/index.php?topic=331.msg4217#msg4217) threads (http://www.bit-blot.com/forum/index.php?topic=567.msg6266#msg6266) that sort of mentioned it, but, at least in the first one I linked to, they replaced Naija's graphics using another entity.  It sounds like you're taking a different approach that won't run into that problem, but I thought I'd ask anyway.
Title: Re: Form modification/Creation
Post by: Edwards on January 15, 2009, 05:58:25 am
No, there are no flipping problems with this, as it uses the built-in method of re-skinning Naija.  Those other threads were using even uglier hacks to re-skin Naija, as (a) the data files weren't accessible then, so the costume system couldn't be reverse-engineered, and (b) at least in some cases, they were attempting extreme changes, like swapping a sea turtle for Naija (this can't be done with the costume system).

- Edwards
Title: Re: Form modification/Creation
Post by: Titch on January 15, 2009, 04:43:09 pm
As Edwards said, this doesn't cause the flipping issue because I'm only doing a re-skin. It's worth noting that when re-skining for a form you MUST name the head files using the same string you used to name the costume xml file. For example in the mod I was using "ninja_naija.xml" so all the heads are "ninja_naija-normal" and so on, it doesn't matter what head entry you have in the xml itself, the only thing that matters is the string you are using to call the costume (and thus the name of the xml file you have used). I have been having some trouble with initHair (I've been trying to give Ninja form a bandanna. It works, but throws up an error message about creating a hair entity first. Also when I return to normal form Naija's cape seems to take on some of the properties I gave the bandanna. I probably need to store the cape off somewhere and restore it when you return to normal form.

Anyway, script updates. I'm writing a "switchForm" and "restoreForm" to help organize and clarify the code when you have more than one form as well as formsinclude.lua to store new static variables for the new forms. A big confustion right now is that switchForm is in Songs.lua while restoreForm I'm also adding a second form, just for demonstrating multiple form management. I've been working on a unique ability or two for Ninja form for actually doing something more than making ascetic changes. Having failed to alter Naija's max speed on transformation (I managed to change her max overall speed to 2000, with hilarious results) I'm trying to impliment a teleport ability where Naija just jumps directly to wherever you click on the screen instead of boosting.
Title: Re: Form modification/Creation
Post by: Particlese on January 15, 2009, 06:37:36 pm
Cool.

It might be useful to separate switchForm() from songs.lua and add it as an include instead.  This would allow you to force the form change when you defeat a boss, for example.
Title: Re: Form modification/Creation
Post by: Titch on January 16, 2009, 02:12:10 am
So I've gotten Ninja form doing this nifty teleport/dash thing when you click LMB to boost. Like the beast form bite it only works when you would usually be able to boost, so if you use it into the middle of and open area be prepared to wait a bit for a recharge time. Unlike the beast form it doesn't damage anything; but it ignores all the physical barriers between you and where you click the mouse. You can zip down tunnels like a demon as long as you can click accurately enough.

Which brings me to the current shortcomings of this move right now. It doesn't activate at all if you click somewhere Naija can't go, even if it's just overlapping the wall a little -too- much. I put in the fix I did to stop players from teleporting into the walls and it seems to have worked fairly well. I think I'll need to do some nifty vector tracing to find walls near the mouse cursor and use them. Additionally, the form_manager only initiates when songs.lua is called; which means it goes strange if you reset the level while still in form. A cleverer fix for this should be on the way. The Ninja costume still doesn't look right, I'll fix that soon too.

I'm working on a small-ish assault course level so people can put the form through it's paces, hopefully without too much fluff so it can be an example that other programmers can pick apart. It's not nearly finished yet, but there are a couple of areas the dodge really shines in already. I'm trying to decide on the secondary ability for the form, I want something else evasion/movement based rather than combit-ish. Although something that could be indirectly damaging would be nice.

http://www.niftyhat.com/posted_stuff/ninja_form.zip
Title: Re: Form modification/Creation
Post by: Chibi on January 16, 2009, 05:37:35 am
That is very neat - if it's as good as it sounds (and I believe it is) I'll be one of the first people to play the mod. I've an idea for the secondary shot - a shockwave that propels enemies out of your way (particularly useful for fast melee attackers).  :)
Title: Re: Form modification/Creation
Post by: TheBear on January 16, 2009, 06:22:21 am
Form works quite well and was fun. Being able to teleport definitely adds some new level design opportunities. Keep up the good work.
Title: Re: Form modification/Creation
Post by: Chibi on January 16, 2009, 06:41:37 am
Just a heads up - all the files have the same names as ones present in the game files: makes installing them a little annoying.
Title: Re: Form modification/Creation
Post by: Edwards on January 16, 2009, 06:46:33 am
Wow.  I could really get used to that form... :D

Anyway, that looks like a pretty decent set-up you have for keeping track of the form, its abilities, etc.  songs.lua will need a bit of clean-up before you release a version for developers to pick apart (and you might want to add a few comments), but otherwise, it's looking good.  I would suggest going back to just having a form_manager present in every level from the start, though.  postInit() fires after the level is created, regardless of whether the entity is on-screen, so if you move the n= getNaija(), entity_setPosition(...) lines into postInit(), the local form_manager will jump to be on top of Naija as soon as the level starts.  Then, you won't need to worry about duplicates (you're currently creating a new one every time a song is sung.  I hadn't meant for that duplicate-handling code to ever be used :P), and you won't have any trouble with reverting before singing, either after reloading or after entering a new map.

As for the problem of remembering the previous costume, good luck.  The best I can come up with is to have a n array of costume strings, and to save the index of the current costume in a flag when changing forms.  It's rather clunky, but at least it will maintain the memory across map transitions... :-\

- Edwards
Title: Re: Form modification/Creation
Post by: Titch on January 18, 2009, 12:25:37 am
I tried your fix Edwards, but the form manager still doesn't spawn until you sing a song of some kind, I think it's because the songs.lua doesn't execute until you sing a valid song of some kind.

Also I'm having some trouble with some nested loops. I've been trying to write a a simple while loop to test the best position to warp Naija to if the player clicks on solid rock using the dot_product function.

Code: [Select]
function getNearestPoint (cx,cy,i)
--cx and cy are target point, i is number of itterations to check for.
    cc = createEntity ("collision_check","",cx,cy)
    local bx =0
    local by =0
--cc is a dummy entity, all it has is a collision radius.
    if entity_isNearObstruction (cc, 1, OBSCHECK_RANGE) == false then
--if there isn't anything in the way just set the best spot to the target point
            bx= cx
            by= cy
    else
    -- Naija's x and y
        local nx,ny = entity_getPostion(n)
        -- dot product, half way between Naija and the target point
        local dx,dy = vector_dot (cx,cy,nx,ny)
        -- the best spot found.
        local bx,by = 0,0
        -- blocks eternal itterations.
        if i < 1 then i =1 end
            while i > 0 do
                -- put a collision checking object in where we want to test
                entity_setPositionX (cc,dx)
                entity_setPositionY (cc,dy)
                --this control hint never fires
                setControlHint("test 2", 0, 0, 0,1 )
                   if entity_isNearObstruction (cc, 1, OBSCHECK_RANGE) then
                       -- if it does collide, test a point closer to Naija
                       dx,dy = vector_dot (dx,dy,nx,ny)
                   else
                       -- if it doesn't collide, save that spot and test a spot futher away.
                       -- more itterations means you'll get closer to the obstruction.
                       bx,py = dx,dy
                       dx,dy = vector_dot (cx,cy,dx,dy)
                    end
                i = i-1
            end
    end
   --clean up the dummy checker.
    entity_delete(cc)
   --return the best spot to use
    return bx, by
end

The while loop works, the if loop works, they just don't work when I nest an if inside a while loop. It's quite frustrating. I've also probably used dot_vector() incorrectly based on my incredibly shaky memory of maths.

Since I'm on the subject of problems. I've started to try and implement a skill on the RMB, and for some reason isRightMouse () registers NOTHING right now. Perhaps I have to set some kind of state on the node or something.  I can kludge in using "entity_setActivation" but that means the cursor glows all the time, registering that it's over something that can be activated.
Title: Re: Form modification/Creation
Post by: Edwards on January 18, 2009, 06:26:49 am
I tried your fix Edwards, but the form manager still doesn't spawn until you sing a song of some kind, I think it's because the songs.lua doesn't execute until you sing a valid song of some kind.
You do still need to place a form_manager entity in the level, first (and make sure you save the level afterward!).  What I was trying to say is that having songs.lua spawn form_managers would cause problems, and placing them manually when creating the levels would solve those problems.  For convenience' sake, I may come up with a modification to the entity's code to make it visible in the editor.

...
The while loop works, the if loop works, they just don't work when I nest an if inside a while loop. It's quite frustrating. I've also probably used dot_vector() incorrectly based on my incredibly shaky memory of maths.
I'll just do this the easy way- I've added comments (prefaced by --!) to your code, pointing out where you might be getting into trouble.
[EDIT] I don't have time to check this right now, but does anything bad happen if you feed a fraction into setPosition (say, entity_setPositionX(cc, 5000.35)?
Code: [Select]
function getNearestPoint (cx,cy,i)
--cx and cy are target point, i is number of itterations to check for.
    cc = createEntity ("collision_check","",cx,cy)
    local bx =0
    local by =0
--cc is a dummy entity, all it has is a collision radius.
    if entity_isNearObstruction (cc, 1, OBSCHECK_RANGE) == false then
--if there isn't anything in the way just set the best spot to the target point
            bx= cx
            by= cy
    else
    -- Naija's x and y
        local nx,ny = entity_getPostion(n)
        -- dot product, half way between Naija and the target point
        local dx,dy = vector_dot (cx,cy,nx,ny) --! No need for this, just use dx = nx + (cx-nx)/2, and its y equivalent
--! Furthermore, just start off with bx = nx, as that is guaranteed true
--! Although, I don't know what kind of dot product it's doing if it
--! returns two values- a dot product should return cx*nx+cy*ny
        -- the best spot found.
        local bx,by = 0,0
        -- blocks eternal itterations.
        if i < 1 then i =1 end --! Good point, given that I believe that 0 is passed if no argument is given.
--! This isn't "blocking eternal iterations", though.
         while i > 0 do
            -- put a collision checking object in where we want to test
            entity_setPositionX (cc,dx)
            entity_setPositionY (cc,dy)
            --this control hint never fires --! Sounds like a syntax error.
--! Does it fire if you put it at the start of the loop?
--! How about just before the loop?
--! Are you sure that dy has a value in it?  That might be the trouble.
            setControlHint("test 2", 0, 0, 0,1 )
--! What you're trying to do here is just a binary search,
--! with a limit on the number of iterations
--! I'll get back to you with a slightly more standard method in a bit
               if entity_isNearObstruction (cc, 1, OBSCHECK_RANGE) then
                   -- if it does collide, test a point closer to Naija
                   dx,dy = vector_dot (dx,dy,nx,ny)
               else
                   -- if it doesn't collide, save that spot and test a spot futher away.
                   -- more itterations means you'll get closer to the obstruction.
                   bx,py = dx,dy
                   dx,dy = vector_dot (cx,cy,dx,dy)
                end
            i = i-1
         end
    end
   --clean up the dummy checker.
    entity_delete(cc)
   --return the best spot to use
    return bx, by
end
[EDIT] Here's a re-written version of the script.  I haven't actually tried it, lacking the collision_check entity (and the rest of the testing framework you have), but I'm pretty sure it will work:
Code: [Select]
function getNearestPoint (endx,endy,i)
--cx and cy are target point, i is number of itterations to check for.
cc = createEntity ("collision_check","",endx,endy)
--cc is a dummy entity, all it has is a collision radius.
local destx = endx
local desty = endy

-- Check if the destination is bad.  If it isn't bad, the return values are already set up!
if entity_isNearObstruction(cc, 1, OBSCHECK_RANGE) then
-- The destination is blocked.  Run a search to find the furthest unblocked location.
-- Set the initial destination to Naija's current location, as this is guaranteed to be good
destx,desty = entity_getPostion(n)

if i < 1 then i = 1 end --! Force minimum iterations

-- while destx ~= endx and desty ~= endy and i > 0 do -- Try this line once the rest of the script works
while i > 0 do
-- Get a point half-way between the start and end of the area to check
local hx,hy = vector_half(destx, desty, endx, endy)
-- move the collision-checking entity to the half-way point
entity_setPositionX(cc, hx)
entity_setPositionY(cc, hy)

-- Just a debug string.  Note that only the last iteration will appear
setControlHint(string.format("Destination:%d,%d",hx,hy), 0, 0, 0,1 )
-- if it does collide, set this bad point to the end of the test range
if entity_isNearObstruction (cc, 1, OBSCHECK_RANGE) then
endx = hx
endy = hy
else
-- if it doesn't collide, set this good point to the beginning of the search range
-- and also to be the final destination
destx = hx
desty = hy
end
i = i-1
end
end
   --clean up the dummy checker.
entity_delete(cc)
   --return the best spot to use
return destx, desty
end

-- Returns a point halfway between the two given points (ax,ay) and (bx,by)
function vector_half(ax, ay, bx, by)
halfx = ax + (bx-ax)/2
halfy = ay + (by-ay)/2
return halfx, halfy
end


Since I'm on the subject of problems. I've started to try and implement a skill on the RMB, and for some reason isRightMouse () registers NOTHING right now. Perhaps I have to set some kind of state on the node or something.  I can kludge in using "entity_setActivation" but that means the cursor glows all the time, registering that it's over something that can be activated.
Odd.  I'll need to test that.  What version are you running, on what operating system?

[EDIT] Works fine for me.  Throw this snippet into an update(…) function somewhere- it's a basic display of what's going on with Naija:
   setControlHint(string.format("StillTimer:%d SpellCharge:%d Form:%d LeftMouse:%s RightMouse:%s", avatar_getStillTimer(),avatar_getSpellCharge(),getForm(),tostring(isLeftMouse()),tostring(isRightMouse())), 0, 0, 0, 2)

- Edwards
Title: Re: Form modification/Creation
Post by: Titch on January 18, 2009, 05:46:15 pm
Thanks Ed, your like the Guru of LUA for Aquaria :), or perhaps just LUA in general. The snippet for checking control inputs helped. I'm not quite sure how, I pasted it in and checked that it was registering the right mouse in the control hint and then just wrote out the if statement again, leaving out ==true and it just worked. Anyway, the snippet is pretty handy even though it can cause a bit of slowdown.

The iterating bit of code still isn't firing though. I don't get a hint output, but the teleport fires under normal conditions (destination clicked is reachable). All the code that is in the collision checker is this:-

Code: [Select]
function init(me)
    entity_setCollideRadius(me, 1)
end

There really isn't much to go wrong there, it's just to ensure it can register a collision, perhaps it's because theres no setup_entity() call. I'll be adding a msg callback at some point so that the form manager can cull them out if they somehow escape the cleanup in the function. I'll keep testing and see if I can work it out.

Anyway, form creation framework is moving foward. Now I can recognise right/left clicks I'll write a a function/callback structure for charging skills and the like. I'm not sure if there is a way to force Naija to charge, so I'll just have to fake it.
Title: Re: Form modification/Creation
Post by: Edwards on January 18, 2009, 08:31:37 pm
Thanks Ed, your like the Guru of LUA for Aquaria :), or perhaps just LUA in general.
Nah, I'm just a CS student who has about ten years of experience programming in various languages.  I'd never even touched Lua before I started working on Aquaria mods a month or so ago.

The iterating bit of code still isn't firing though. I don't get a hint output, but the teleport fires under normal conditions (destination clicked is reachable).
Half the problem there, now that I've tested it myself, is that you're calling "entity_setPostion(n), rather than entity_setPosition(n) just before the while loop.  My code is still causing random teleportation halfway across the map, but yours might work with that fixed.

[EDIT] Here's a fixed version of the code I posted last time.  I've tested it in-game and it works quite nicely (it may miss if Naija is on a wall, and there's a narrow passage behind that wall, and the player clicks beyond that passage, but that's inevitable with this search type.  Easy enough to fix, though, if you don't care too much about execution time- I'll post a variant in a  minute).
Code: [Select]
function teleport (x,y)
    x, y = getNearestPoint (x,y,20) -- changes to be offset down and left
spawnParticleEffect("shockwave",entity_getPosition(n))
entity_setPositionX (n,x)
entity_setPositionY (n,y)
entity_sound(n,"memory-flash",1000,0)
spawnParticleEffect("shockwave",entity_getPosition(n))
done_teleport=true
end


function getNearestPoint (endx,endy,i)
--cx and cy are target point, i is number of itterations to check for.
cc = createEntity ("collision_check","",endx,endy)
--cc is a dummy entity, all it has is a collision radius.
local destx = endx
local desty = endy

-- Check if the destination is bad.  If it isn't bad, the return values are already set up!
if entity_isNearObstruction(cc, 1, OBSCHECK_RANGE) then
-- The destination is blocked.  Run a search to find the furthest unblocked location.
-- Set the initial destination to Naija's current location, as this is guaranteed to be good
destx,desty = entity_getPosition(n)

if i < 1 then i = 10 end --! Force minimum iterations- I'd actually recommend forceing 10 iterations.
--i = 10-- This seems to work well
while i > 0 do
-- Get a point half-way between the start and end of the area to check
local hx,hy = vector_half(destx, desty, endx, endy)
-- move the collision-checking entity to the half-way point
entity_setPositionX(cc, hx)
entity_setPositionY(cc, hy)

-- Just a debug string.  Note that only the last iteration will appear
-- setControlHint(string.format("Destination:%d,%d",hx,hy), 0, 0, 0,1 )
-- if it does collide, set this bad point to the end of the test range
if entity_isNearObstruction (cc, 1, OBSCHECK_RANGE) then
endx = hx
endy = hy
else
-- if it doesn't collide, set this good point to the beginning of the search range
-- and also to be the final destination
destx = hx
desty = hy
end
i = i-1
end
end
   --clean up the dummy checker.
entity_delete(cc)
   --return the best spot to use
return destx,desty
end

-- Returns a point halfway between the two given points (ax,ay) and (bx,by)
function vector_half(ax, ay, bx, by)
halfx = ax + (bx-ax)/2
halfy = ay + (by-ay)/2
return halfx, halfy
end

[EDIT] Here's the code for a linear search, which fixes the occasional problems with being unable to teleport through walls.  It's actually nowhere near as inefficient as I'd expected- even long jumps work well with just 10 iterations, and fewer iterations might also work.  Just replace the while loop in the above code with this:
Code: [Select]
-- Linear search for open space
-- i=10 seems to work most of the time, although I'd like to have the step size be capped
for n = 0, i do
-- Get a point along the line beween Naija and the target
-- Starting the search from the target end of the line
local hx,hy = vector_fraction(endx, endy, destx, desty, i, n)
-- move the collision-checking entity to the half-way point
entity_setPositionX(cc, hx)
entity_setPositionY(cc, hy)
-- if it doesn't collide, set this to be the final destination,
-- as it is the furthest open point from Naija
if not entity_isNearObstruction (cc, 1, OBSCHECK_RANGE) then
destx = hx
desty = hy
break
end
end
And add this function:
Code: [Select]
function vector_fraction(ax,ay,bx,by,divs,numofdivs)
x = ax + (bx-ax)/divs*numofdivs
y = ay + (by-ay)/divs*numofdivs
return x,y
end

- Edwards
Title: Re: Form modification/Creation
Post by: Titch on January 18, 2009, 11:25:24 pm
Again, thanks Edwards, I've been banging  my head on this for the past two days and not getting very far. With your help I can get on an try and focus on some of the other form related code, like charging levels and getting the flourish animation to work right.

As for limiting the step distance, I'm probably going to cap the jump distance. Right now since it's for the mouse only it jumps strait to wherever you can point the mouse, which gives widescreen and hi-res users a huge distance advantage (I run Aquaria at 640x480 in a window for testing  code, my laptop isn't exactly a powerhouse); plus I've got to bring it in line with how the jump is going to behave using the game pad. It's still going to be a fair distance, since I think the charm of it lies in the sheer speed you can move around areas.

So I'm building a forms include. So you can override forms from any bit of code that has the include, it's worth noting that dofile() seems to run from the Aquaria root, not the mod root. So it has to be dofile(_mods/myMod/scripts/myinclude.lua). I'm hoping to use scope to hide the old changeForm function like this:

Code: [Select]
do
    local __changeForm = changeForm
    changeForm = function (formID)
...code...
  __changeForm(formID)
end
end

So new forms can be swapped around with the same command. It will be a good place to stash new FORM_* constants. It's not working yet, but I'm nothing less than dogged ^_^

I've not used LUA before, I've been using ActionScript 2.0/3.0, UnrealScript and C# up until now. Hoping I can pick up enough about working LUA to work on something using C++/Allegro and LUA.
Title: Re: Form modification/Creation
Post by: Dolphin's Cry on January 19, 2009, 09:45:01 pm
I've not used LUA before, I've been using ActionScript 2.0/3.0, UnrealScript and C# up until now. Hoping I can pick up enough about working LUA to work on something using C++/Allegro and LUA.
Please, write "Lua" right! (http://www.lua.org/about.html#name) Or else the monkeys will throw sea loafs at you... hm, what a nicely weird mod idea. ;)

You are right about dofile. I forgot that not everyone knows this. ;)  I quickly added a note about it to the wiki.
Title: Re: Form modification/Creation
Post by: Titch on January 19, 2009, 11:49:22 pm
Haha. I skipped that part of the manual.

On my small mod list is a pet mod that adds a monkey with a divers helmet to try and lay something out for pet mods. Throwing sea loafs would be a nifty attack.

EDIT: I'll probably copy this to the start of the topic, but, form checklist stuff.

Song - Yes
Skin - Yes
LMB - Yes
RMB - Yes
Keyboard/Gamepad Input - Nope
Charging Skills - Nope
Simplified Custom Skills - Nope
Flourish Animation - Nope
Song Symbol Menu - Nope
Reusable Structure - Kind off...
Commented Script - See above.

If I want to get really picky. Li.lua has custom script where he reacts to certain forms Naija is using and I might add some easy function for doing a form tutorial when you first switch to a form. As you can see, I'm still quite a bit of way from being done.

My idea of hiding the original changeForm() call in scope and calling it from my own override didn't work. I just can't seem to store off the old changeForm() code into another function with a diff name without causing a crash or just failing. I've settled for using setForm() so that it matches better with setCostume(). If something doesn't come to me eventually then I'll use the same thing for locking form changes. We shall see.

I'm working on capturing the game pad input right now. I think I can even cancel out bursting and allow the user to replace it with something else by calling something if avatar_IsBursting() is true. Although I wouldn't recommend using it as it would add a futher layer of complexity to the controls which shouldn't strictly be necessary.
Title: Re: Form modification/Creation
Post by: Hiro on January 22, 2009, 07:59:10 am
Quote
I'd never even touched Lua before I started working on Aquaria mods a month or so ago.
Eeeehhh?? Dude.
Duuude...

Quote
Thanks Ed, your like the Guru of LUA for Aquaria
^This is still true.   O0

Anyway, this thread is getting more and more interesting as the idea of new forms comes closer and closer to a reality. ^-^