• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Should We Start Learn TFS Coding ?

Should We Start Doing it?


  • Total voters
    47
  • Poll closed .
as you see code
Code:
Account() {
            id = 0;
            accountType = ACCOUNT_TYPE_NORMAL;
        }

that's mean if accountID = 0 == nothing
it should return type with ACCOUNT_TYPE_NORMAL
I think it's a good idea that each function in TFS should be commented, maybe a header comment, but I got this far in your post and quit. This is totally wrong. First of all, this is a constructor for the Account class, not a function. When you create an Account object it sets the id to 0 and the accountType to ACCOUNT_TYPE_NORMAL. This is to prevent possible errors.

Also, I think that placing comments inside of the source code would be better than how you did it in your post. But that's just my opinion.
 
Last edited:
And funniest thing is that everything you described here can be done in creaturescripts without source edit.

For example:
I have a boss which recovers his full hp when he kills his target, he may throw your character causing some damage or even cast healing spell which affects only selected creatures. Destroying mwalls and placing his own is simple thing too.

There are a lot of possibilities which don't need source edits. All you need is knowledge.
I like you.
 
I would love to learn editing it because i got a lot of ideas :3
Now i've learned something from it but as scripter i want to know everything..

For example why is there :: or -> or !
And when do i need to use it..
 
It's great to see interest in source diving and understanding the source code, but you should probably truly understand C++ before trying to teach others. Your explanations of things are very vague and sometimes incorrect, I can't even imagine how you're going to explain A* pathfinding and how the map is stored in memory (quad tree), and several other parts of the source code that aren't beginner friendly. I don't mean any offense, I think it's really great that you want help others climb up to your level of understanding the source code, but I find it counterintuitive when the explanations aren't accurate. I'm also sorry to hear about your uncle.
I used to be like you, making complex LUA scripts you can do some amazing things.
Then I started editing sources....

Now I have Monsters that can open doors, chase you down and up stairs, seagulls can fly through windows and over bushes and trees, ghosts can go through walls, my monsters have aggro and don't follow a random targeting system. Orcs and Minotaurs and other creatures are hostile to each other will attack each other, and if a friendly Orc Shaman is about to cast Fireball, other orcs will run out of the way so they do not get hit by the splash damage.
Once you start editing the source, literally anything is possible as long as it logically could happen in a 2d tile based game.

I'm not going to argue against you, because you're obviously more limited in Lua, but that can be a good thing to protect the end-user from literally making any mistake that is possible to do with machine instructions. Besides, most of the things you mentioned are possible to do in TFS 1.0 in Lua, using monster scripting (it was added a while back by @Dalkon).

I would love to learn editing it because i got a lot of ideas :3
Now i've learned something from it but as scripter i want to know everything..

For example why is there :: or -> or !
And when do i need to use it..

"::" is used in three different ways that I am aware of. In two of the cases, it is a separator between class name and function name. It is used both when writing the function body that belongs to a class and when calling a static function.
A function body in ClassName example:
void ClassName::FunctionName() {
}

Now, if FunctionName in ClassName is declared static, you could call it like this:
ClassName::FunctionName();

The third case is when you have a namespace, for example the C++ Standard Library is in the "std" namespace, so to access types from the standard library namespace you must prepend it with "std::", example (cout and endl are part of the C++ standard library):
std::cout << "Hello world" << std::endl;

"leftside->" is a shortcut for "(*leftside).", which is dereferencing a pointer and accessing a data member or calling a function of the dereferenced pointer (which the dot is a separator for), example:
(*leftside).do_something();

! means not. You will usually see it in an if statement, example:
if (!player->isOffline()) {
That will evaluate true if the player is not offline.
 
It's great to see interest in source diving and understanding the source code, but you should probably truly understand C++ before trying to teach others. Your explanations of things are very vague and sometimes incorrect, I can't even imagine how you're going to explain A* pathfinding and how the map is stored in memory (quad tree), and several other parts of the source code that aren't beginner friendly. I don't mean any offense, I think it's really great that you want help others climb up to your level of understanding the source code, but I find it counterintuitive when the explanations aren't accurate. I'm also sorry to hear about your uncle.


I'm not going to argue against you, because you're obviously more limited in Lua, but that can be a good thing to protect the end-user from literally making any mistake that is possible to do with machine instructions. Besides, most of the things you mentioned are possible to do in TFS 1.0 in Lua, using monster scripting (it was added a while back by @Dalkon).



"::" is used in three different ways that I am aware of. In two of the cases, it is a separator between class name and function name. It is used both when writing the function body that belongs to a class and when calling a static function.
A function body in ClassName example:
void ClassName::FunctionName() {
}

Now, if FunctionName in ClassName is declared static, you could call it like this:
ClassName::FunctionName();

The third case is when you have a namespace, for example the C++ Standard Library is in the "std" namespace, so to access types from the standard library namespace you must prepend it with "std::", example (cout and endl are part of the C++ standard library):
std::cout << "Hello world" << std::endl;

"leftside->" is a shortcut for "(*leftside).", which is dereferencing a pointer and accessing a data member or calling a function of the dereferenced pointer (which the dot is a separator for), example:
(*leftside).do_something();

! means not. You will usually see it in an if statement, example:
if (!player->isOffline()) {
That will evaluate true if the player is not offline.

Thank you for your comment, But its still not clearly yet for me except the ! thing..
Could you explain it to me in noob language?
 
Thank you for your comment, But its still not clearly yet for me except the ! thing..
Could you explain it to me in noob language?
Code:
int a = 1;
int b = 2;

if (a == b)
{
    //a is equal to b
}

if (a != b)
{
    //a is not equal to b
}
The first if statement is asking if a is equal to b, if it is (meaning the statement a==b is true), then it goes in to the block. The code between { and } is called a block. The first if statement will never be true because a (1) is not equal to b (2), and therefore the code inside the block will never be accessed. The second if statement is asking if a is NOT equal to b, if it's not (meaning the statement a != b is true), then it goes in to that block. This if statement will always be true because a (1) does not equal b (2). Does that make sense? Remember, the blocks of if statements are only accessed if the if statement returns true.

In English:
Code:
Set the Integer labeled 'a' equal to 1.
Set the Integer labeled 'b' equal to 2.

If a is equal to b then go inside of the block.

If a is not equal to b then go inside of the block.
 
Last edited:
And funniest thing is that everything you described here can be done in creaturescripts without source edit.

For example:
I have a boss which recovers his full hp when he kills his target, he may throw your character causing some damage or even cast healing spell which affects only selected creatures. Destroying mwalls and placing his own is simple thing too.

There are a lot of possibilities which don't need source edits. All you need is knowledge.

Ok, i'll script your example right now:
Boss heals when he kills target:
Code:
function onKill(cid, target)
doCreatureAddHealth(cid, getCreatureMaxHealth(cid))
return true
end
Boss throws your character and causing some damage.
Code:
local function throwTile(cid, dir)
  if isCreature(cid) then
    local pos = {x=getCreaturePosition(cid).x,y=getCreaturePosition(cid).y,z=getCreaturePosition(cid).z}
    doMoveCreature(cid, dir)
    if pos.x == getCreaturePosition(cid).x and pos.y == getCreaturePosition(cid).y then
      doCreatureAddHealth(cid, -50)
    end
  end
  return true
end
(Just add this to any spell and pick a direction to throw the target, if they hit a wall it does damage)

Heal only effecting selected creatures:
Code:
local specs = getSpectators(getCreaturePosition(cid), 10, 10, false)
for _, tid in ipairs(specs) do
  if tid ~= cid and getCreatureName(tid) == "Selected Creature" then
    doCreatureAddHealth(tid, 150)
  end
end
Oh now destroying mwalls..
Code:
onTargetTile(cid, pos)
  local mwall = getTileItemById(1497, pos)
  if mwall.itemid > 0 then
    doRemoveItem(mwall.uid)
  end
  return true
end

Saying these are anything is laughable, I just did all of your mentioned scripts in less than 5 minutes.
Bigger scripts, will take too much CPU usage in LUA to be logical to DO in lua, for example, feel free to test out my pathing test script to make a better pathing system for TFS.

(I can't add it here, because it is TOO LONG for this forum to even have it posted)
So here it is on pastebin:

http://pastebin.com/DK791LAr

Just attach it to any useable item (I use a mysterious fetish) and any location you click it will create a test path to that location.
now THAT is an LUA script.
YES I could do that in LUA, and add it to every monster onThink() and have it play every time their target moves a position so they will follow you up and down stairs, but guess what!? EVERY time that is played in TFS it takes around 300 ms for long distances, which means if 100 monsters were active and chasing players, thats 100 * 300 = 30000 = 30 seconds of load time every second. Oh wait that means the server is frozen.

Do it in the Source, not only did that REDUCE lag, now monsters find their targets faster, and farther and up/down stairs.
Consider yourself Ignorant Mr zbizu.
 
Last edited:
I'm not going to argue against you, because you're obviously more limited in Lua, but that can be a good thing to protect the end-user from literally making any mistake that is possible to do with machine instructions. Besides, most of the things you mentioned are possible to do in TFS 1.0 in Lua, using monster scripting (it was added a while back by @Dalkon).

Hello Mark,
I agree that LUA protects the end-user from making big mistakes. I know I myself have broken TFS many many times in the source, and had to go through debugging to find out what was wrong.

But some things just need to be done in the source to be fast enough to be usable and efficient.
And some things can only be done in TFS, for example I have a custom WorldLight where you can change the color and intensity of the WorldLight for each player individually. So when entering caves or stormy areas etc you can make it dark, but only for those players, Or you could have someone doing a quest where the sun was blocked out, or turned blue, and the entire world would look different until the quest is completed.
 
Last edited:
Bigger scripts, will take too much CPU usage in LUA to be logical to DO in lua, for example, feel free to test out my pathing test script to make a better pathing system for TFS.

(I can't add it here, because it is TOO LONG for this forum to even have it posted)
So here it is on pastebin:

http://pastebin.com/DK791LAr

Just attach it to any useable item (I use a mysterious fetish) and any location you click it will create a test path to that location.
now THAT is an LUA script.
YES I could do that in LUA, and add it to every monster onThink() and have it play every time their target moves a position so they will follow you up and down stairs, but guess what!? EVERY time that is played in TFS it takes around 300 ms for long distances, which means if 100 monsters were active and chasing players, thats 100 * 300 = 30000 = 30 seconds of load time every second. Oh wait that means the server is frozen.

Do it in the Source, not only did that REDUCE lag, now monsters find their targets faster, and farther and up/down stairs.
Consider yourself Ignorant Mr zbizu.

Not sure why you would implement that kind of logic in Lua. In TFS 1.0 you can just use Creature.getPathTo.
 
@Flatlander
- Use isSightClear or your monster will throw enemies through the wall and check pathing or you may make player stuck.
- Your post is laughable and your arguments are terrible.
- I posted that as example to let you know that source edits aren't needed to do all this pointless crap you're proud of(such as seagulls flying through windows).
- Your pathfinding script is pointless, takes more memory and does same thing. It's slower, because you check every tile 255 times and other things too often.
- Doing monster AI in lua is still efficient, because onThink is executed only when monster is somewhere near player and not all monsters will use these scripts(separate events for different behaviors).
- I'm not ignorant. Check your scripts before you call someone's work inefficient.
 
@Flatlander
- Use isSightClear or your monster will throw enemies through the wall and check pathing or you may make player stuck.
- Your post is laughable and your arguments are terrible.
- I posted that as example to let you know that source edits aren't needed to do all this pointless crap you're proud of(such as seagulls flying through windows).
- Your pathfinding script is pointless, takes more memory and does same thing. It's slower, because you check every tile 255 times and other things too often.
- Doing monster AI in lua is still efficient, because onThink is executed only when monster is somewhere near player and not all monsters will use these scripts(separate events for different behaviors).
- I'm not ignorant. Check your scripts before you call someone's work inefficient.
  1. You do not need isSightClear with doMoveCreature, it won't push a creature onto a spot they cannot move to.
  2. My post is logical and fact therefor you saying it is laughable is pretty funny to me
As for my Pathing system:
It is like people just don't understand the purpose of optimization.
In TFS, the pathing system branches out in every direction with almost NO Criteria at all. Creating TONS of useless nodes that are completely illogical.
The purpose of my LUA script wasn't to be efficient IN LUA. I first scripted it using the rules that TFS pathing system follows, test it to a far away location with obstacles it will time how long it takes to find a path, and how many nodes it created. Adding a few checks and preferences, it now creates up to 1/3rd of the nodes and takes 1/3rd of the PROCESSING TIME to calculate a path to a location.
Why did I do this you may ask? Because when I edited the view range of monsters up to 50 sqm. The entire server would freeze for 2 full seconds while making paths for even a few monsters.
Even in TFS 1.0 they use a similar Pathing System. (It isn't bad, it does what it needs to for MOST servers)
Code:
AStarNode* AStarNodes::getBestNode()
{
if (curNode == 0) {
return nullptr;
}
int32_t best_node_f = std::numeric_limits<int32_t>::max();
int32_t best_node = -1;
for (uint32_t i = 0; i < curNode; i++) {
if (openNodes[i] && nodes[i].f < best_node_f) {
best_node_f = nodes[i].f;
best_node = i;
}
}
if (best_node >= 0) {
return &nodes[best_node];
}
return nullptr;
}
But it can be made MUCH more efficient and better by adding preferences to tiles that are more likely the correct path. Which is what I did.

Also zbizu, I'm sorry I hurt your little ego. I was just pointing out the things I have done, are leagues ahead of creatures healing them self or each other. Which are basically the examples you gave. I don't know how good you are or what you have done, I was judging your intelligence by your one post.
 
  1. You do not need isSightClear with doMoveCreature, it won't push a creature onto a spot they cannot move to.
  2. My post is logical and fact therefor you saying it is laughable is pretty funny to me
As for my Pathing system:
It is like people just don't understand the purpose of optimization.
In TFS, the pathing system branches out in every direction with almost NO Criteria at all. Creating TONS of useless nodes that are completely illogical.
The purpose of my LUA script wasn't to be efficient IN LUA. I first scripted it using the rules that TFS pathing system follows, test it to a far away location with obstacles it will time how long it takes to find a path, and how many nodes it created. Adding a few checks and preferences, it now creates up to 1/3rd of the nodes and takes 1/3rd of the PROCESSING TIME to calculate a path to a location.
Why did I do this you may ask? Because when I edited the view range of monsters up to 50 sqm. The entire server would freeze for 2 full seconds while making paths for even a few monsters.
Even in TFS 1.0 they use a similar Pathing System. (It isn't bad, it does what it needs to for MOST servers)
Code:
AStarNode* AStarNodes::getBestNode()
{
if (curNode == 0) {
return nullptr;
}
int32_t best_node_f = std::numeric_limits<int32_t>::max();
int32_t best_node = -1;
for (uint32_t i = 0; i < curNode; i++) {
if (openNodes[i] && nodes[i].f < best_node_f) {
best_node_f = nodes[i].f;
best_node = i;
}
}
if (best_node >= 0) {
return &nodes[best_node];
}
return nullptr;
}
But it can be made MUCH more efficient and better by adding preferences to tiles that are more likely the correct path. Which is what I did.

Also zbizu, I'm sorry I hurt your little ego. I was just pointing out the things I have done, are leagues ahead of creatures healing them self or each other. Which are basically the examples you gave. I don't know how good you are or what you have done, I was judging your intelligence by your one post.

Would you mind elaborating on what these "preferences" are? It sounds to me like you are ignoring tiles that could potentially lead to the best path, because TFS doesn't ignore a tile unless a) it's in direction we arrived from b) it's too far away c) it's not possible to walk on the tile d) we already know a cheaper way to arrive at the tile. The pathfinding in TFS 1.0 is really fast, I'd be surprised if you found a way to make it faster while still being able to find the most optimal path. I've even tried implementing it using a priority queue for the best node (which is what OTClient uses), and even that was slower than the current implementation (might be faster for a larger viewport though, but not in our use cases).

The only thing I can think of is to also skip tiles that are adjacent to the parent tile in the path chain, but I would have to test whether the cost of adding such checks is actually a performance gain.
 
Would you mind elaborating on what these "preferences" are? It sounds to me like you are ignoring tiles that could potentially lead to the best path, because TFS doesn't ignore a tile unless a) it's in direction we arrived from b) it's too far away c) it's not possible to walk on the tile d) we already know a cheaper way to arrive at the tile. The pathfinding in TFS 1.0 is really fast, I'd be surprised if you found a way to make it faster while still being able to find the most optimal path. I've even tried implementing it using a priority queue for the best node (which is what OTClient uses), and even that was slower than the current implementation (might be faster for a larger viewport though, but not in our use cases).

The only thing I can think of is to also skip tiles that are adjacent to the parent tile in the path chain, but I would have to test whether the cost of adding such checks is actually a performance gain.

It doesn't IGNORE tiles, it makes them more expensive. For TFS it would be making the .f (cost of a tile) more if it is going in a way that is LESS likely.

This way paths that are more likely to lead to the correct path.
Also, once my script FINDS a path, ANY node that costs more than that one are automatically closed, because if it costs more it would be impossible for it to be a better path.

Once I get off work I can make a youtube video to explain it.

Basically lets say you want this path. S is Start F is Finish, 1 is a wall.

{0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, S, 1, F, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0},

TFS would branch out in ALL direction evenly. N = Node

{N, N, N, N, N, N, 0},
{N, N, N, 1, N, N, 0},
{N, N, N, 1, N, 0, 0},
{N, N, S, 1, F, 0, 0},
{N, N, N, 1, N, 0, 0},
{N, N, N, 1, N, N, 0},
{N, N, N, N, N, N, 0},

Thats a total of... 32 nodes to check IF we don't count when it checks a tile twice and replaces it with a better node parent.
Now if we add my preferences,

{0, N, N, N, N, 0, 0},
{0, N, N, 1, N, 0, 0},
{0, N, N, 1, N, 0, 0},
{0, N, S, 1, F, 0, 0},
{0, N, N, 1, N, 0, 0},
{0, N, N, 1, N, 0, 0},
{0, N, N, N, N, 0, 0},

Thats a total of... 20 nodes. Because why would we check FARTHER nodes from the target location FIRST? It is ok to check them IF there isn't a better way (which my script does) but you should always prefer the better node that is most likely a faster path.
 
Last edited:
I just want people to know that its not as easy learning TFS Coding as LUA is. Its a matter of fact harder and finding the errors are way more difficult. Im not trying to decourage anyone, im just saying if you REALLY want to learn TFS Coding you gotta have patient and motivation to keep learning. Its easy to say "hell yea lets do this!" than actually doing it. Keep that in mind, I myself am not a super expert within this area but I know the most basics of source editing.
Anyways, good luck with it cause ull need it
 
It doesn't IGNORE tiles, it makes them more expensive. For TFS it would be making the .f (cost of a tile) more if it is going in a way that is LESS likely.

This way paths that are more likely to lead to the correct path.

So then my question is, which factors make it less likely? In TFS, we already increase the cost for tiles where you need to take a diagonal step or where there is a field item (unless immune to the damage type). Are there any other factors that you take into account to make a tile more expensive, which is reasonable? By looking at the Lua script you posted, it doesn't look like you increase the cost for fields.

Also, once my script FINDS a path, ANY node that costs more than that one are automatically closed, because if it costs more it would be impossible for it to be a better path.

Yes, that is how A* or any other "best first"-search algorithm works. It's the same in TFS.

EDIT: Okay, now that I've seen your edit I get what you're saying. I had the wrong idea about how we were selecting the best tile, there's definitely room for improvement by also taking into account the distance we are from a destination. Thanks for explaining.
 
Last edited:
So then my question is, which factors make it less likely? In TFS, we already increase the cost for tiles where you need to take a diagonal step or where there is a field item (unless immune to the damage type). Are there any other factors that you take into account to make a tile more expensive, which is reasonable? By looking at the Lua script you posted, it doesn't look like you increase the cost for fields.



Yes, that is how A* or any other "best first"-search algorithm works. It's the same in TFS.

Currently my script has 3 additives. (It does not add these TO the node, it adds them under getBestNode, so it does not effect the base cost).

#1 it will add 1 cost per tile away from the target location.
#2 it will add the difference of its distance to the targetPos subtracted by the startPos distance to the target location.
#3 it adds 10 cost if the tile is going in the complete opposite direction of the targetPos.
 
EDIT: Okay, now that I've seen your edit I get what you're saying. I had the wrong idea about how we were selecting the best tile, there's definitely room for improvement by also taking into account the distance we are from a destination. Thanks for explaining.

No Problem :)
I'm not trying to be an ass. I just know when I am right and I have a big ego...
 
Hello All..
First i'm sorry for mistakes .. and i knew that will happened because i'm not expert at C++ and i said it from beginning we teach each other
but i know i explain few things wrong
but you know i was drunk this day

because there is a person who is the reason for this ::
imagine a person who is precious to you ...
one day you stand with him and laugh .. but suddenly you took him to hospital :(

and you know that he has cancer :(
so his life transferred from 100% life to 100% death
that was in the same day i wrote tutorial .. and i had spoken about it in first page :(

but today he gone forever .. he won't back to me again
so i make a message for moderators or @Mark .. him self

delete this thread .. because i won't care about it any more
and i won't be here at least 1 year or maybe forever to back after what happened

yea i know that 1 year is too much for a person who died
but believe me if he was my father my mother i won't come back forever or i will kill my self

btw ..
few friends here in otland .. are really like real brother
and they are @HalfAway , @dominique120 , @Testerus ..
thanks for you tears guys

so Moderators Delete this thread and good bye every one :|
 
Hello All..
First i'm sorry for mistakes .. and i knew that will happened because i'm not expert at C++ and i said it from beginning we teach each other
but i know i explain few things wrong
but you know i was drunk this day

because there is a person who is the reason for this ::
imagine a person who is precious to you ...
one day you stand with him and laugh .. but suddenly you took him to hospital :(

and you know that he has cancer :(
so his life transferred from 100% life to 100% death
that was in the same day i wrote tutorial .. and i had spoken about it in first page :(

but today he gone forever .. he won't back to me again
so i make a message for moderators or @Mark .. him self

delete this thread .. because i won't care about it any more
and i won't be here at least 1 year or maybe forever to back after what happened

yea i know that 1 year is too much for a person who died
but believe me if he was my father my mother i won't come back forever or i will kill my self

btw ..
few friends here in otland .. are really like real brother
and they are @HalfAway , @dominique120 , @Testerus ..
thanks for you tears guys

so Moderators Delete this thread and good bye every one :|

I feel sorry for you, i wish i could make you smile or at least lesser sad..
I recommend you to listen to this song:


Both of my parents died.. My father when i was 14 and my mother 4 months ago..
It hurts, but keep ya head up ;)

Search for distracton, cry it all out do whatever it ease the pain, i wish you the best even if i don't know you..
If you want to talk, PM me if you read this atleast...

But about the thread don't remove it please, the idea itself is nice..
 
No Problem :)
I'm not trying to be an ass. I just know when I am right and I have a big ego...
Forcing your opinion doesn't make it right. From what I've noticed ego level grows with programming skill.
I tried to avoid being what almost every advanced scripter became, but lack of others knowledge is sometimes annoying.
Another problem are all those perfectionists who point out everything(even fucking formatting) how they could that better.
If one person treats other people like shit, others do that too. This is why we can't have nice community.
 
Back
Top