Knights Forum

General Category => Knights Discussion => Topic started by: doublejack on September 03, 2012, 03:22:17 PM

Title: LUA-question
Post by: doublejack on September 03, 2012, 03:22:17 PM
Hello! I have read a post about LUA-modules and want to help with development, if I can.
I have lua-coding experience and a lot of ideas for knights game so I'll be really happy to help.

Can anyone show me where I can script and maybe some examples so I could understand how the whole knights thing works.

thanks.
sorry if there are some mistakes, English isn't my native language.
Title: Re: LUA-question
Post by: K9 on September 03, 2012, 04:35:32 PM
You're English seems great! 

Thank you for the interest in coding Lua game enhancements for Knights.

I have played this game for many years and seen Stephen do amazing things with this game, reborn from Amiga version.

All hardcore fans are excited to see new possibilites opened with Lua.

I am responding now, to tell you from a player perspective, about our excitement for your post.

The last thing I read is that Stephen Is still perfecting the system for Lua integration and hasn't released the version ready for development yet.

He will probably post a reply to you with answers to your questions.

Thanks again, I hope we can see you on our weekend games.

Check the server list and join the fun to see what it's like with a great group of Knights battling in unique, often hilarious dungeon quests.
Title: Re: LUA-question
Post by: Stephen on September 03, 2012, 04:51:21 PM
Welcome!

Unfortunately the Lua support is not released yet. It is coming in the next release of Knights, which will happen fairly soon (probably 1-2 weeks from now).

I would suggest you wait until then.

In the meantime, there is some documentation here: http://www.knightsgame.org.uk/trac/wiki/lua but I don't know if it will be much use at this point.

Maybe the best way is if you told us what kind of things you want to add? I could then give you some hints about how to do it. But, like I said, we have to wait for the new release first :)
Title: Re: LUA-question
Post by: doublejack on September 04, 2012, 05:45:57 AM
Yes, as I said I have ideas but first of all I'll be happy to create something for users, I mean something that they want or suggested here, maybe some new game modes, monsters and other.
But I understand that the game is yours and I would not try to change the whole game system or try to turn it in something totally new. I think people like knights game and want to see some upgrades/improvements but not global changes.
I'll try to discuss with you all ideas so if you like them too you would be able to add them to next game versions.

But if you interested in my personal ideas, I think that it would be great to make some really teamplay-oriented game modes like defense(survival) where all players are trying to defend their spawn/fortress from being destroyed by hordes of zombies and swarms of bats or maybe capture the flag mode with two teams... but I have to repeat - there are my personal ideas and I would work on them only if you like it as developer and if the community like it.

so I'll TRY to help you in development. I think that it's no sense in creating stuff that would not be added in game, so hope I would be able to help and maybe one day become a part of the knights game development team

thanks
Title: Re: LUA-question
Post by: ImpassIve on September 04, 2012, 03:16:43 PM
doublejack
"But I understand that the game is yours and I would not try to change the whole game system or try to turn it in something totally new."

Sorry, but I can't agree with you at that point.

Modding is an unofficial part of the game. So, if you want to make something cool, but conflicting with main idea - you should try to do that...
It is most likely that such mod wouldn't be imported to official game in later releases, but this game supports unofficial servers (see "Download" page), so I don't see any problem.

I can cite as a good example the game "Cortex Command". It is almost 90% moddable (all "standart" units/scripts were written in the same way as mods which you can create just by using notepad and photoshop). Now, there are 700+ available mods and some of them are really cool!

I hope that new modding system in "Knights" will have the same success. But we need people who would make all those mods, because without them this feature would be purposeless.
I am glad that you are willing to participate in the present case)
Title: Re: LUA-question
Post by: doublejack on September 04, 2012, 05:00:49 PM
...but I still think that it is better to help with official development now.
maybe sometimes when knights would have at least 10-15 players online always it would be good idea to create mods and separate servers for them.
anyway, Stephen looks like developer ready for innovations and game enlargement so I hope there would not be problems with official modding:)
Title: Re: LUA-question
Post by: Stephen on September 04, 2012, 06:36:20 PM
Personally, I am happy for all types of mods to be made. New quests, new game modes, new monsters or items... whatever you want really.

There is not really any difference between "official" and "unofficial" development. Anyone can make a mod. If you make a mod, and people like the idea, then I will put it up on the official server. (We could then test it during our weekly game perhaps.) This is easy enough to do, and it doesn't need a new release of Knights -- I can just install the files on the server and it will be available straight away.

Eventually, some mods might become an "official" part of Knights, but let's wait until some mods are actually made before thinking about that :)
Title: Re: LUA-question
Post by: K9 on September 05, 2012, 06:02:20 PM
Development and enhancements to Knights are exciting, either way you call it (i second Stephen's and ImpassIve_rus's comments)

As a DB Coder (programmer at heart) i also really respect your point of view about ownership, and your direction toward honoring the existing crowd.

That is very cool approach, I am sure everyone will enjoy playing your ideas and seeing previous suggestions come to pass as well.


Thank you.
Title: Re: LUA-question
Post by: ImpassIve on September 06, 2012, 08:41:58 AM
Well, now I have one question about lua scripting.

In this game, when you become invulnerable - you get a special addition to sprite of your knight (something like new armor).

Is there any way to make something like that by mod?

(In my mod, some players should have a crown or helmet sprites on their knights).
If that is not possible, well... that is not so necessary.


P.S. Also, is there any way to increase default knight's health?

P.P.S. I found how to make player win (kts.WinGame), but how can I eliminate him?

P.P.P.S. I have tried to use some hooks but my function was never called... Also, I checked tutorial files and have found only "on_pickup" etc. functions but no hooks... Are they working now?
Title: Re: LUA-question
Post by: Stephen on September 07, 2012, 09:31:54 AM
Quote from: ImpassIve_rus on September 06, 2012, 08:41:58 AM
In this game, when you become invulnerable - you get a special addition to sprite of your knight (something like new armor).

Is there any way to make something like that by mod?

(In my mod, some players should have a crown or helmet sprites on their knights).
If that is not possible, well... that is not so necessary.

Currently this is not possible. I could add it, but if it's not important then I'll wait until some other time.

Quote
P.S. Also, is there any way to increase default knight's health?

kts.MISC_CONFIG.knight_hitpoints = 10    -- or however many hit points you want

Not tested but it should work :)

Quote
P.P.S. I found how to make player win (kts.WinGame), but how can I eliminate him?

Not possible currently. I can add "kts.EliminatePlayer", that would be easy to do.

Quote
P.P.P.S. I have tried to use some hooks but my function was never called... Also, I checked tutorial files and have found only "on_pickup" etc. functions but no hooks... Are they working now?

It should be working. Have you tried a simple hook that only does a "print"? Maybe post your code and I can try to figure out what's wrong?
Title: Re: LUA-question
Post by: ImpassIve on September 07, 2012, 01:28:54 PM
1) No, this feature is not necessary. Mod can work even without this.
2) Ok, I will try this, but this is not so important for me too...
3) Yeah, EliminatePlayer would be nice...
4) Lol. Looks like I have found, where was the problem.
Before that, I had tried to put "kts.HOOK_KNIGHT_DAMAGE = knight_damage_f" in "features" part of menu (because this hook should be installed only if my mod was selected in menu) - everything worked, except hooks.
5 minutes ago I tried to move it into initial part of my lua... now it works. But, sure, that hook is called even if my mod wasn't selected in menu. But that problem seems solvable.
Title: Re: LUA-question
Post by: ImpassIve on September 07, 2012, 01:51:48 PM
Hm... but I have got some more questions now))

1) How differs "cxt.actor" and "cxt.originator", for example while executing function <item>.on_pick_up or <item>.on_drop ?
because kts.GetNumHeld(cxt.originator, i_revive_gem) -- causes an error "bad userdata"
kts.GetNumHeld(cxt.actor, i_revive_gem)  --working fine.

But in the same time

kts.SetRespawnFunction(respawn_func)
...
function respawn_func (player)
...
for i=1,#heroes do
    if (heroes[i]==player)
           print("hello")
...

prints "hello" only after "table.insert(heroes, cxt.originator)" but not after "table.insert(heroes, cxt.actor)" (both were called in "on_pickup" function)

2) I haven't found in wiki any definition of types returned by "cxt.actor" and some other, so I don't know what to do with it, does it contain some information (e.g. player's nickname, health etc.), or that is just something like number of this knight?
Title: Re: LUA-question
Post by: Stephen on September 08, 2012, 11:50:10 AM
Quote from: ImpassIve_rus on September 07, 2012, 01:51:48 PM
1) How differs "cxt.actor" and "cxt.originator", for example while executing function <item>.on_pick_up or <item>.on_drop ?

cxt.actor is a "Creature" while cxt.originator is a "Player".

A "Creature" represents the knight itself. A "Player" represents the person controlling that knight.

If your knight dies, then the old "Creature" object is marked as "dead" and can no longer be used. (You can use kts.IsAlive to find out whether a Creature object is "alive" or "dead".) When you respawn, a completely new Creature object is created for your new knight.

By contrast, "Player" objects are never destroyed -- each player keeps the same Player object all through the game.

If you have a Creature you can get the corresponding Player using kts.GetPlayer. (There is no function to go the other way currently.)

For monsters, it works slightly differently. The Creature object represents the zombie, or bat, or whatever. There is no Player object for monsters. (kts.GetPlayer returns nil if called on a monster.) For monsters, cxt.originator will be set to the string "monster".

Quote
because kts.GetNumHeld(cxt.originator, i_revive_gem) -- causes an error "bad userdata"
kts.GetNumHeld(cxt.actor, i_revive_gem)  --working fine.


kts.GetNumHeld requires a Creature (not Player) as first parameter. That's why it only works with cxt.actor.

Quote
But in the same time

kts.SetRespawnFunction(respawn_func)
...
function respawn_func (player)
...
for i=1,#heroes do
    if (heroes[i]==player)
           print("hello")
...

prints "hello" only after "table.insert(heroes, cxt.originator)" but not after "table.insert(heroes, cxt.actor)" (both were called in "on_pickup" function)

The respawn function has one parameter which is a Player object. Note that when the respawn function is called, there is a Player object, but no corresponding Creature object (their old knight has been destroyed, but the new knight hasn't been created yet).

Quote
2) I haven't found in wiki any definition of types returned by "cxt.actor" and some other, so I don't know what to do with it, does it contain some information (e.g. player's nickname, health etc.), or that is just something like number of this knight?

They are just userdata objects. (Technically, they are pointers to C++ objects.) You can't do anything with them apart from compare them for equality and pass them to "kts" functions.
Title: Re: LUA-question
Post by: ImpassIve on September 08, 2012, 02:04:15 PM
Ok, thanks for the answer =)
Title: Re: LUA-question
Post by: ImpassIve on September 09, 2012, 08:02:58 PM
Just one more question (or, maybe, a request?) to Stephen.

Since 21th build of Knight isn't released yet, it is possible to add some features to it, right?

Well, I am making (or, at least, trying to make) a new quest type - something similar to deathmatch, but with some new contents, and with different scoring type. That's why I asked about a way to eliminate player. But I have a little trouble right now. Score in standart deathmatch depends on how much players killed each other, but that is not quite correct for this quest.

Atm, I am counting score of each player in a special array, and when player gets one more violet gem (from killed barbarian) - total amount of his gems are displayed by using a flashing message (in the same way as effect of potion).
But he can not compare his score with the opponent's scores, because I don't know their nicknames. I can display only something like
1st player - 0
2nd player - 3
3rd player - 1

So, is that hard to implement a function to retrieve a name from "Player" object?
I think, that may be useful in mods, focused on multiplayer and new quest types.

Also, an ability to operate with Deathmatch scores table (displayed on the upper right side of the screen) would be nice for me, but with feature is a bit more specific, so that is not so important.

If that is not possible for some reason, I would like to ask for advice.
Which way to inform players about their scores is better? (using current functionality)

1) Do not use names at all. For example, display the top score.
2) Use numeric interpretation of players (first, second, third, etc.) - as they are placed in players list.
3) Some graphical interpretation (I don't know)
4) Other
Title: Re: LUA-question
Post by: Stephen on September 09, 2012, 10:37:31 PM
Quote from: ImpassIve_rus on September 09, 2012, 08:02:58 PM
Since 21th build of Knight isn't released yet, it is possible to add some features to it, right?

I'm sorry, but I have already started doing the build, so it's too late to add new features. It will have to wait until the next one I'm afraid.

Quote
So, is that hard to implement a function to retrieve a name from "Player" object?

No, this is not difficult at all. I'll add it in version 22.

Quote
Also, an ability to operate with Deathmatch scores table (displayed on the upper right side of the screen) would be nice for me, but with feature is a bit more specific, so that is not so important.

I agree - it should be possible to set the scores directly from Lua. That way, the Deathmatch mission could be coded in Lua instead of being a special case. I've added a Trac ticket (#205).

Quote
Which way to inform players about their scores is better? (using current functionality)

There's no way to access player names using current functionality, so the best you can do is tell the player their own score, and maybe the top score as well.
Title: Re: LUA-question
Post by: doublejack on September 16, 2012, 01:33:30 PM
hello again and sorry for my absence) now I'm trying to get into the knights scripting specifics)

I have some ideas and hope you would see something I created soon)

and Stephen, maybe it would be a good idea to create a forum section for mods and modding discussions?
Title: Re: LUA-question
Post by: Stephen on September 17, 2012, 07:51:30 PM
Quote from: doublejack on September 16, 2012, 01:33:30 PM
and Stephen, maybe it would be a good idea to create a forum section for mods and modding discussions?

Good idea.

Maybe there should be one forum for Mod Announcements (where people can announce completed mods) and a second forum for Lua Discussion (where people can ask questions about scripting and so on)?
Title: Re: LUA-question
Post by: doublejack on September 17, 2012, 08:04:45 PM
I think there is no need for two forums. just make topics with mods start with [mod] prefix ([mod] Spiders, [mod] Toolbox, etc.)

and create a main topic with mod list (links) and small descriptions. and make this topic main, so it would always be on the top)
Title: Re: LUA-question
Post by: Moo on September 17, 2012, 10:12:32 PM
Yes, with the level of activity here, no need to separate things like that...
Title: Re: LUA-question
Post by: Worst on September 17, 2012, 11:49:36 PM
I guess a separate mod forum is just fine, but I'd be wary of making too much new forums as that might make things look deserted, which is not something that'll attract new people.. And it would mean more browsing for the current users of the forum. (I wouldn't even make a separate forum for mods at this point, but this is just me :P)

If it's about organizing things, then with the low level of activity, I think thats the least of the worries right now.. And once it is a worry, then I think we can celebrate - for other reasons :)
Title: Re: LUA-question
Post by: Stephen on September 18, 2012, 11:55:35 AM
OK... let's just leave things as they are for the moment. When we have more users we can think about creating new forums.

If someone wants to make a mod list topic, then I can set it as sticky so that it always appears at the top...
Title: Re: LUA-question
Post by: ImpassIve on September 27, 2012, 05:29:07 PM
Heh, I have some more questions)

1) I noticed a bug (?) with respawn function in lua:
kts.SetRespawnFunction(respawn_func)
function respawn_func(player)
print("Died!")
return nil
end


If one player will be eliminated (e.g. by using kts.EliminatePlayer(player) )- this function will be called for an infinity times. So, you will get
Died!
Died!
Died!
Died!
Died!
etc. in your chat.

2)
kts.AddMonsters(monster_type, number_to_place)
function is useful, because you don't have to thinks about "how to place this monster in this dungeon".
But if you want to control all your "special" monsters - you will have to add them one-by-one by using
cr = kts.AddMonster(pos, monster_type);
table.insert(My_mobs, cr);

But how can you find a correct place for it...
You will have to choose a random pos (hmm... from what range?), check tile on that position (it shouldn't be some kind of wall) and in some way check if somebody is already placed here (not so necessary, because in that case function just will return nil).

Is there any way to simplify this process?
Title: Re: LUA-question
Post by: Moo on September 27, 2012, 06:01:06 PM
Yes, a "return random dungeon square" function would be great. I needed something like that for my teleport wand, so I gave up with that... Worst did it the hard way with his wand in the meantime though, pretty much the same way you described.
If the function could return any "existant" square in the dungeon (not "air") but including walls, that would be good, then you could just keep trying if you got a wall (or table, or pit, or whatever) and didn't want that.

Another possibility would be if you could use the AddMonster method, then have another function which returns all existing creatures (or objects etc?) of that type.
Title: Re: LUA-question
Post by: Stephen on September 28, 2012, 12:27:35 PM
Quote from: ImpassIve_rus on September 27, 2012, 05:29:07 PM
1) I noticed a bug (?) with respawn function in lua:

Yeah, that sounds like a bug, there is no point in calling the respawn function if a player is eliminated. (Added to Trac)

Quote from: Moo on September 27, 2012, 06:01:06 PM
Yes, a "return random dungeon square" function would be great.

Indeed, you don't want to be doing it how Worst did it :)

I could add "kts.GetRandomPos()" that returns a random dungeon position, this would probably be the simplest solution.

Quote from: ImpassIve_rus on September 27, 2012, 05:29:07 PM
You will have to choose a random pos (hmm... from what range?), check tile on that position (it shouldn't be some kind of wall) and in some way check if somebody is already placed here (not so necessary, because in that case function just will return nil).

You don't need to check if it's a wall, because kts.AddMonster won't place a monster inside a wall (it will return nil instead).

You do have to worry about pits. kts.AddMonster will place a monster on a pit -- but the monster will instantly fall down the pit and die. You can check for this by calling "kts.IsAlive" immediately after creating the monster.

I should probably change kts.AddMonster so that it refuses to place monsters on tiles in the "ai_avoid" list. This would prevent monsters being created on tiles which they would not normally walk onto.
Title: Re: LUA-question
Post by: Stephen on September 29, 2012, 07:21:07 PM
OK, I have now added kts.GetRandomPos() and modified kts.AddMonster() so that it does not place monsters in tiles from the "ai_avoid" list (usually pits). The new build is available in http://www.solarflare.org.uk/snapshots/ (assuming my upload script worked properly!).
Title: Re: LUA-question
Post by: Romanio(Rus) on October 07, 2012, 03:23:46 PM
For some reason functions addMonster and getTiles are not working for me as supposed to do.

Here is a small example code:
module(...)
local C = require("classic")
local M = require("menu")

local thelayout = nil
local mapwidth = 0
local mapheight = 0

function getlayout()
if thelayout == nil then
thelayout = C.Dsetup.layout.func()
mapwidth  = (thelayout.width  * 12) + thelayout.width  + 1
mapheight = (thelayout.height * 12) + thelayout.height + 1
end
end

spawn_item = {
id = "spawn-bat",
text = "Spawn",
choice_min = 1,
choice_max = 1,
features = function(S)
getlayout()
kts.SetRespawnFunction(spawn())
end
}

function spawn()
    local pos = { x, y }
    local xmax = mapwidth
    local ymax = mapheight
print("Spawn begin!")
for i=1,10000 do
pos.x = kts.RandomRange(0, xmax)
pos.y = kts.RandomRange(0, ymax)
cr = kts.AddMonster(pos, C.m_vampire_bat)
--print("x",pos.x,"y",pos.y)
if cr ~= nil then
print("A creature was added")
end
end
print("Spawn end!")
end

table.insert(kts.MENU.items, spawn_item)


but value, returned by kts.addMonster is always == nil. Similar situation was with getTiles (returns an empty array), used in a same way.
What I am doing wrong?
Title: Re: LUA-question
Post by: Moo on October 07, 2012, 06:39:09 PM
With the new GetRandomPos you shouldn't need to use the layout or RandomRange to get a location...

Does it place the bats but return nil, or not do anything?
Title: Re: LUA-question
Post by: Stephen on October 07, 2012, 07:01:16 PM
What are you trying to do? Do you want monsters to be created every time a knight respawns?

If so, your problem is the following:

kts.SetRespawnFunction(spawn())


That should be:

kts.SetRespawnFunction(spawn)


Or do you want monsters to be created once, at the start of the game? In that case, the easiest way is to do this:

C.add_initial_monsters(C.m_vampire_bat, 10)

where 10 is the number of monsters you want.

("add_initial_monsters" is a function defined in classic/dungeon_setup.lua. You can see an example in the "Vampire Bats" entry in menus.lua.)
Title: Re: LUA-question
Post by: ImpassIve on October 07, 2012, 08:24:33 PM
Well, I will answer instead of him, because he is offline right now and I was helping him to make his mod...

In original, that were not bats, but his own monsters and he should store them into an array to control their behavior (that is why he didn't use "add_initial_monsters" or "kts.AddMonsters")

QuoteDoes it place the bats but return nil, or not do anything?
That doesn't place any monster.

Quotekts.SetRespawnFunction(spawn)
instead of
kts.SetRespawnFunction(spawn())
Yes, this example was made in 10 minutes just to show the problem and that kind of mistake was made... So, this example is incorrect.

I am not sure (because I don't have a copy of Romanio's mod on my PC) but as I know he really have done the same error in his mod. But he noticed it and corrected even before that post

I hope, tomorrow he will either approve what the problem is solved or make a new example.
Title: Re: LUA-question
Post by: Romanio(Rus) on October 08, 2012, 09:36:02 PM
Thank you Stephen!
Indeed, as soon as I remove the brackets after the spawn, it worked :o
Thank you for your detailed response.
And, as said ImpassIve, I need to use kts.AddMonster instead C.add_initial_monsters
Title: Re: LUA-question
Post by: ImpassIve on October 10, 2012, 06:26:12 PM
Hm... just some random thoughts about mods...

If you want to make your mod switchable (on/off) you will meet several questions.

- First. How to determine the moment when the game started? Yes, "features" function on menu elements is nice, but there are some special moments... What if you have none elements in the menu? Ok, let's suppose what you have something in menu, but you need to make something after generation of the dungeon is finished (place special monsters or replace/move some tiles)...

- Well, in that case, you can use kts.SetRespawnFunction(f). But only one mod (as I suppose) can use this in the same time. So, if you decided to "install" your custom respawn function, others won't be able to do it... or even you will "lose" your already installed respawn function if someone else needs this function too. Because while using hooks, you can find an old hook function and manually call it after your function... but here is no kts.GetRespawnFunction.

- Hm... but you can make some plugin what will claim this function for himself and send to registered mod some kind of notification about respawn event. Well, I have thought about adding such feature to my Toolbox mod (in the same way as hooks were implemented in it)... But it can't (as far as I know) call kts.SetRespawnFunction because this mod doesn't have any elements in the menu, lol...

- I am not talking about using existing hooks, because if you want to generate monsters in the dungeon - it is a bad idea to wait until someone will be hurt/step on some special tile etc. etc.

- The second question is how to determine the fact what the game already finished? So, you can delete all your hooks, free data tables, etc? Because there is a strong chance what in the next match your mod will be disabled, but you will get no notification about that... so, in some cases (excluding custom respawn function, initial mosters and other "auto-disabling" options) your mod will be acting as enabled. How to avoid such situation?
Title: Re: LUA-question
Post by: Stephen on October 11, 2012, 07:16:51 PM
1) kts.SetRespawnFunction() is used to control where the knight respawns. It is not meant as a general "initialization" function.

For example, the Tutorial uses kts.SetRespawnFunction to make the knight respawn close to where he died, instead of all the way back at the beginning of the tutorial.

It would not make sense for two mods to install their own respawn function, because a knight can logically only respawn in a single place :)

2) It sounds like you want to be able to call functions at the start of the game, but after the dungeon has been created. To do that you need to replace "kts.MENU.start_game_func" with your own function.

For example:

require ("classic")

local old_start_game_func = kts.MENU.start_game_func

kts.MENU.start_game_func = function(S)
   -- call the original start_game_func first... this will create the dungeon
   old_start_game_func(S)

   -- now do your stuff here
end


3) There is no way to "do something at the end of the game" currently. Maybe there should be an "end_game_func" to complement "start_game_func"?
Title: Re: LUA-question
Post by: ImpassIve on October 11, 2012, 07:42:10 PM
Quotekts.MENU.start_game_func

Oh, thanks, I didn't notice this function!

QuoteIt would not make sense for two mods to install their own respawn function, because a knight can logically only respawn in a single place

Yes, that seems unlikely now (because I didn't knew about start_game_func before). But that scheme is still possible if the 'first' function in most cases passes (returns nil). So, in 'regular' situation spawn position would be determined by the second function... but in some 'extreme' situations (maybe, the knight have lost all his 'lives'?) first function will setup some specific spawn point, or e.g. eliminate this knight.
Well, I realize, that this situation is far-fetched, but it still may occur...

QuoteMaybe there should be an "end_game_func" to complement "start_game_func"?

I can't give many examples of using such function, but it could be useful in some specific cases...
Title: Re: LUA-question
Post by: Stephen on October 11, 2012, 08:04:21 PM
Quote from: ImpassIve_rus on October 11, 2012, 07:42:10 PM
Yes, that seems unlikely now (because I didn't knew about start_game_func before). But that scheme is still possible if the 'first' function in most cases passes (returns nil). So, in 'regular' situation spawn position would be determined by the second function... but in some 'extreme' situations (maybe, the knight have lost all his 'lives'?) first function will setup some specific spawn point, or e.g. eliminate this knight.
Well, I realize, that this situation is far-fetched, but it still may occur...

Hmm, well, it would not be hard to add "kts.GetRespawnFunction" so I should probably do it :)

Quote
QuoteMaybe there should be an "end_game_func" to complement "start_game_func"?

I can't give many examples of using such function, but it could be useful in some specific cases...

OK, I'll put it down as a low-priority feature.
Title: Re: LUA-question
Post by: doublejack on October 15, 2012, 07:29:40 PM
maybe if we are going to use toolbox in all knights mods so it would be a good idea to make a new button in game menu, something like "addons" where you can switch on/off ALL installed mods, taking information from toolbox?
Title: Re: LUA-question
Post by: ImpassIve on October 16, 2012, 05:16:27 PM
Hm...
Quote from: doublejackmaybe if we are going to use toolbox in all knights mods so it would be a good idea to make a new button in game menu, something like "addons" where you can switch on/off ALL installed mods, taking information from toolbox?
1) Term "all mods" is not quite correct. Toolbox is an optional mod, because you can implement all functions from it by yourself. So, if you have made a mod, which don't need to interact with others - why would you use toolbox in it?
2) Anyway, this feature requires free space in menu screen. Imho, it is better to make such disabling feature in each mod independently. Because all existing at this moment mods (Telewand, Living Armours, Spiders) can be "disabled" from menu (L.A. and Spiders - just set corresponding activity to 0; Telewand - just do not select this wand in the menu). Why should we add some new menu elements to do the same thing?
Title: Re: LUA-question
Post by: ImpassIve on October 18, 2012, 07:32:01 PM
Hm... looks like knights_editor is not working with the current version of knights?
That is sad...
Title: Re: LUA-question
Post by: Stephen on October 20, 2012, 12:43:55 PM
Yes, unfortunately, that is true, the knights editor does not work with the current version of Knights.

I do need to fix that but unfortunately I don't really have time right now...
Title: Re: LUA-question
Post by: ImpassIve on October 23, 2012, 04:13:39 PM
Hm... you have said

Quote from: StephenIt sounds like you want to be able to call functions at the start of the game, but after the dungeon has been created. To do that you need to replace "kts.MENU.start_game_func" with your own function.

I have modified a bit Romanio's previous example:
module(...)
local C = require("classic")
local M = require("menu")

local thelayout = nil
local mapwidth = 0
local mapheight = 0

function getlayout()
if thelayout == nil then
thelayout = C.Dsetup.layout.func()
mapwidth  = (thelayout.width  * 12) + thelayout.width  + 1
mapheight = (thelayout.height * 12) + thelayout.height + 1
end
end


local function spawn()
    local pos = { x, y }
    local xmax = mapwidth
    local ymax = mapheight
print("Spawn begin!")
for i=1,10000 do
pos.x = kts.RandomRange(0, xmax)
pos.y = kts.RandomRange(0, ymax)
cr = kts.AddMonster(pos, C.m_vampire_bat)
--print("x",pos.x,"y",pos.y)
if cr ~= nil then
print("A creature was added")
break
end
end
print("Spawn end!")
if old_game_f then
old_game_f()
end
end

spawn_item = {
id = "spawn-bat",
text = "Spawn",
choice_min = 1,
choice_max = 1,
features = function(S)
getlayout()
--kts.SetRespawnFunction(spawn)
end
}

table.insert(kts.MENU.items, spawn_item)
old_game_f = kts.MENU.start_game_func
--kts.MENU.start_game_func = spawn


So why if I would uncomment
--kts.SetRespawnFunction(spawn)
-the game will print "Spawn begin!/A creature was added/Spawn end!"

but if instead I would uncomment
--kts.MENU.start_game_func = spawn
-the game will print only "Spawn begin!/Spawn end!"

Does that mean that we can't place monsters using this function?
____________
Also:
Quotekts.HOOK_WEAPON_DOWNSWING -- called when any creature swings a weapon
Does that really means "any creature" as stated or "knights only"?
Title: Re: LUA-question
Post by: Stephen on October 24, 2012, 09:10:24 PM
1) You need to call old_game_f() before you do your spawning. Move "if old_game_f then old_game_f() end" up to the top of the spawn() function. Then it works.

The reason is that old_game_f is the thing that creates the dungeon. If you haven't called that yet, then the dungeon doesn't exist and no monsters can be created.

ALSO: Please replace


pos.x = kts.GetRandomRange(0, xmax)
pos.y = kts.GetRandomRange(0, ymax)


with


pos = kts.GetRandomPos()


You can then delete your getlayout() function and thelayout, mapwidth, mapheight variables. This will simplify your code.

2) It is actually only knights, not any creature.

In my Monster Proposal thread, I proposed to add an "on_attack" function for each monster type. This would be the equivalent of HOOK_WEAPON_DOWNSWING but it would be defined per monster type instead of globally. Therefore you could create different sound effects for different creature types (for example).
Title: Re: LUA-question
Post by: ImpassIve on October 24, 2012, 09:28:14 PM
Quote from: Stephen
You need to call old_game_f() before you do your spawning.
oh... thanks. I will have to fix this in Toolbox mod..)

Quote from: Stephenpos = kts.GetRandomPos()
Yes, I remember this. But since there is no such function in current 'official' release (only in dev. versions) I prefer not to use new features yet (or use, but in separated 'dev' version of a mod...)

Quote from: StephenIt is actually only knights, not any creature.
Well, in this case corresponding description of kts.HOOK_WEAPON_DOWNSWING (http://www.knightsgame.org.uk/trac/wiki/lua/The%20%22kts%22%20table#Listofavailablehooks) in wiki should be fixed?
Title: Re: LUA-question
Post by: Stephen on October 25, 2012, 02:34:16 PM
Quote from: ImpassIve_rus on October 24, 2012, 09:28:14 PM
Quote from: Stephenpos = kts.GetRandomPos()
Yes, I remember this. But since there is no such function in current 'official' release (only in dev. versions) I prefer not to use new features yet (or use, but in separated 'dev' version of a mod...)

OK fair enough :)

Quote
Quote from: StephenIt is actually only knights, not any creature.
Well, in this case corresponding description of kts.HOOK_WEAPON_DOWNSWING (http://www.knightsgame.org.uk/trac/wiki/lua/The%20%22kts%22%20table#Listofavailablehooks) in wiki should be fixed?

Thanks, I have updated the wiki page.
Title: Re: LUA-question
Post by: ImpassIve on November 01, 2012, 07:38:19 PM
Quote from: ImpassIve_rus on October 16, 2012, 05:16:27 PM
Hm...
Quote from: doublejackmaybe if we are going to use toolbox in all knights mods so it would be a good idea to make a new button in game menu, something like "addons" where you can switch on/off ALL installed mods, taking information from toolbox?
1) Term "all mods" is not quite correct. Toolbox is an optional mod, because you can implement all functions from it by yourself. So, if you have made a mod, which don't need to interact with others - why would you use toolbox in it?
2) Anyway, this feature requires free space in menu screen. Imho, it is better to make such disabling feature in each mod independently. Because all existing at this moment mods (Telewand, Living Armours, Spiders) can be "disabled" from menu (L.A. and Spiders - just set corresponding activity to 0; Telewand - just do not select this wand in the menu). Why should we add some new menu elements to do the same thing?

I have changed my mind.
That is a really nice idea, thanks for it!
This was implemented in 4th version of Toolbox.
Title: Re: LUA-question
Post by: ImpassIve on October 30, 2016, 04:44:13 PM
That's me again!
Yesterday, Moo and I were discussing some mod ideas and he pointed out the fact "ai_fear" field wouldn't work for bats.

I had to recheck this, and that's true: monsters with "flying" type are ignoring this field - FlyingMonsterAI class constructor doesn't even has a parameter to take this list.
So, the question is:
- Right now, do we have any way to force flying monster to run away from all knights? Originally, I was planning to add all possible weapon types into "ai_fear" list, but maybe indirect manipulation over "run_away_flag" would somehow work? (I don't know, how about constantly hitting a monster with zero damage strikes via script?)
- Otherwise, is there any chance of implementing such a possibility in the future, or should we stick to a walking type of monsters?

Thanks for attention

P.S. I've tried "hitting a monster with zero damage" idea by adding custom "on_move" function, but that didn't worked for this reason:

bat->move(MT_MOVE);  // It moves
bat->runMovementAction(); // It calls "on_move" lua function
bat->clearRunAwayFlag(); // It resets the flag

"on_move" action is called immediately before resetting the flag, so we cannot use it - at least not for the monster, who caused the event.
But if we would find another reliable event generator - I guess, this method may actually work
Title: Re: LUA-question
Post by: Stephen on November 06, 2016, 10:36:11 PM
Hi,

Sorry for taking so long to reply... I somehow missed your post

I'm a little confused, what are you trying to do exactly?
Title: Re: LUA-question
Post by: ImpassIve on November 07, 2016, 09:42:25 AM
Hello, Stephen.

We have already changed the concept of the mod, so described questions are not so important anymore...

Anyway, we were planning to make a vampire, who could turn into a special bat (in a similar way, as it was implemented in Rat Riders mod: just replacing old monster with another one) to avoid lethal damage. This bat was supposed to run away from all knights and if it is still alive after XX seconds - it can turn back into a vampire form (fully regenerated, of course).

  1) Since we don't have much control over AI behaviour, we had an idea to fill "ai_fear" field with all possible knight weapons, but... yeah, now I see in the wiki - "ai_fear" is listed in "Walking monsters only" category.

  2) Then we had another idea: FlyingMonsterAI class from the source code has a "run_away_flag" variable, which forces flying creature to run away from the target. It is even possible to set it into "true" state via Lua script, by calling "kts.Damage" with zero amount of damage at each tile (or just frequently enough).

But there were a problem: it cannot be done from inside the "on_move" hook of the monster (see previous post), while other hooks are... not so reliable. Looks like Lua doesn't provide a way to run a function with specific time intervals?

Also, later we realised that a monster with constant "run_away_flag == 1" wouldn't run from the knight - it will run in the direction, pointed by knight's facing, so we had to abandon this concept.

  3) There were a backup plan: in some legends, vampires are turning into fog instead of bats, so we could use (1) case with walking type of monster. But a walking monster can easily be cornered, so this wouldn't add a lot to his survivability.

Anyway, as I mentioned in the beginning of the post, the concept of the mod has been changed and it doesn't require any manipulations over monster's behavious anymore.

EDIT:
Quote from: ImpassIve_rus on November 07, 2016, 09:42:25 AM
Looks like Lua doesn't provide a way to run a function with specific time intervals?

Ah, my bad!
I haven't noticed the "kts.AddTask()" function...
Title: Re: LUA-question
Post by: Stephen on November 07, 2016, 07:30:48 PM
OK, that mod does sound interesting.

I did once have an idea to make AI controllable from Lua, so that you could write little Lua scripts to control what a monster does. That would be quite a lot of work though.

There's no good reason why ai_fear should be walking monsters only... it just needs to be implemented in the FlyingMonsterAI as well. (The only reason it wasn't implemented, is because it was only needed for zombies at the time.) I guess I could do that sometime.

If I ever make another indie game, I will put the scripting in from the beginning, instead of tacking it on at the end like I did with Knights... that is the cause of most of these problems I think :)
Title: Re: LUA-question
Post by: ImpassIve on November 07, 2016, 07:55:09 PM
An offtop note:
hey, looks like I've got a personal remote-controlled monster!
(http://i.imgur.com/sDSt1SU.gif)
Title: Re: LUA-question
Post by: Stephen on November 08, 2016, 06:22:01 PM
Nice, I like it ;)