• 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!

[Idea] Python Scriptengine

stian

Banned User
Joined
Oct 29, 2009
Messages
3,755
Reaction score
50
Location
Norway
Well, this is currently just an idea and will take some time to implant. First we'll have to redo some of the current script system in order to support multiple script engines (by compile choice).

So this will be the thread where we can discusse how the Python script shall work. The "lib" will be done in mostly C/C++.

Each script file can handle multiple classes, each class can be extended, or called by other actions. Each action can do for multiple items etc. Or have multiple calls. Python is quite simelar to Lua in many cases, but force you to write nice looking code and is more powerful in many cases.

Code:
import tfs

class MyScript(tfs.onUse):
    items = (123,576,987)
    def action(self):
        # Make the player say Hello World
        self.who.say("Hello World")

        if self.item.id == 123:
            # This will tell the user that item is used
            self.who.send("This is item 123 in action!")
You can also have multiple things to trigger one action
Code:
import tfs

class MyScript(tfs.onEquip, tfs.onDeEquip):
    items = (123)
    def action(self):
        # Say something when item 123 is equiped and deEquiped
        self.who.send("This is item 123 in action!")
Actions can trigger other actions
Code:
class MyScript(tfs.onEquip, tfs.onDeEquip):
    items = (123)
    def action(self):
        # Say something when item 123 is equiped and deEquiped
        self.who.send("This is item 123 in action!")

class MyOtherScript(tfs.onUse):
    items = (23423)
    def action(self):
        # def trigger(self, scriptname, action=0)
        self.trigger('MyScript') # Will trigger first action, equip, using same item id and player
        self.trigger('MyScript', 'deEquip') # Trigger deEquip
Change player/creature state is easy
Code:
class MyScript(tfs.onUse):
    items = (123) # Super Potion etc
    def action(self):
        self.who.addMana(500)
        self.who.addHealth(500)
        self.who.setSpeed(1.5) # 1 means 100% regular, values over etc 10 means static speed
        self.who.loseSkill(0) # No skill loose on death
Same goes for creatures
Code:
class MyScript(tfs.onAttack):
    creature = (123) # Attacker creature ID, set to 0 or 1 or something for players
    def action(self):
        self.attacker.setSpeed(1.5)
Require states to be in action
Code:
class MyScript(tfs.onUse):
    items = (123)
    def action(self):
        if self.who.state('onAttack'):
            self.attacker.setSpeed(1.5) # 1 means 100% regular, values over etc 10 means static speed
Static ID, etc NPC
Code:
class MyScript(tfs.onUse):
    items = (123)
    def action(self):
        # Within 10 fields of creatureID 45554
        if self.who.inRange(10, 45554):
            self.attacker.addMana(200)
A bigger example for some full script
Code:
import tfs

class Script(tfs.onUse, tfs.onAttack, tfs.onAttackEnd)
    items = (123) # the holy of holiest!
    cache = {}

    # Only triggered on use with item = 123
    def onUse(self):
        self.who.state("holy", 1)

    # Triggered always when attacked, even if holy is not active
    def onAttack(self):
        if self.who.state("holy") and self.who.maxHealth() < 10000:
            self.cache[self.who.id] = (self.who.maxHealth(), self.who.maxMana())
            self.who.maxHealth(10000)
            self.who.maxMana(10000)
            self.who.regenHealth(3)
            self.who,regenMana(3)

    def onAttackEnd(self):
        if self.who.state("holy") and self.who.maxHealth() == 10000:
            self.who.regenHealth(1)
            self.who.regenMana(1)
            self.who.maxMana(self.cache[self.who.id][0])
            self.who.maxMana(self.cache[self.who.id][1])
 
Last edited:
Sounds good^^.
also good that users can choose between both.:)
Just waiting for your update before I say more.:p
 
I know it's different but it looks similar to Revscriptsys.
 
Oh please dear god no... L2J uses python as their scripting engine, and good lord it's the worst language ever IMO. 15 gajillion errors simply because you missed ONE space in the middle of a 250 lines long script.

I'm all for a new scripting language, but please, not one that uses SPACES (or tabs) to define coding-blocks. >.<
 
Why not? You like C code without a singel tab, space or newline? I had some ideas about C++ scripts (like trinitycore/mangos) too.
 
Actually, no I don't.

What I do like is a scripting language that ignores whitespace unless its inside " " or ' '. This allows for far more formatting options.

Python on the other hand, defines code blocks using tabs or spaces, thus if you for some reason happens to accidentally put one extra space somewhere in the code in that "padding", the entire following code will get fucked because it looks for an "end" which doesn't exist.

What is even more fun is that, at least the version of python I coded in, lacks the ability to distinguish which line is lacking a proper ending.
Thus all you get is either one or more error involving completely irrelevant lines of code, forcing you to go through every single line of the code to find where that missing/extra space is.

Trust me, I spent a whole day coding an NPC for L2j in python (And ripping my hair too, mind you).
In C++/LUA/PHP/WHATEVER it would have taken max 30 minutes, but thanks to pythons wonderful padding-system, I got stuck having to look through slithering lines of code to find that extra/missing space at least 50 times or more.

Long story short, padding is nice, but not when it's a requirement and the compiler is as sensitive to touch of the padding, as a Female Canine in heat.


EDIT:

But yes. A scripting language similar to C++/Java would be HEAVEN. Imagine the deliciously complicated scripts you could write if you had access to fullscale OOP. <3
It's the only thing I miss about lua really.
 
Last edited:
python ++

learn to correctly tab or use space and u dont have problems+ a good looking code.

Yes, but again, you have far more formatting options with a code that doesn't REQUIRE tabs/spaces for code-block separation, that's what { } is for, clean and simple separation of blocks, and the option to add spaces/tabs/newline as you see fit for formatting purposes.
 
That is true, it sucks hard if u accidentally press the space bar. But look at the lua script now. Some scripts are really hard to understand because it is really a mess.

Maybe C# or vb.net is good, but then again. linux probs I guess:O But .net has an good userfriendly editor^^.
 
That is true, it sucks hard if u accidentally press the space bar. But look at the lua script now. Some scripts are really hard to understand because it is really a mess.

Maybe C# or vb.net is good, but then again. linux probs I guess:O But .net has an good userfriendly editor^^.

Yes, VERY much true. The thing I hate about LUA is the END-separation of code, no real distinction between what ends where. If you miss one END, you're screwed and the compiler throws an annoying "EOF Error" which doesn't actually tell you where the END is missing, just that it IS probably missing SOMEWHERE. =/
And indeed, LUA scripts lacking tabs is a nightmare. ><

What I also miss about LUA is the comprehensible OOP, the Object-based stuff you do in LUA now feels crippled and messy.

Perhaps Java would be a solution? It's very platform independent.
 
Java is too heavy to be used as a script engine. .NET/mono C# is an alternative, so har C++ scripts and Python. Also Python tends to be good to report where you got the script messed up

Code:
var=True

if var is False:
   print "False"
elif var is 8:
   print "False"
elif var is 7:
  print "False"
   print "It's 7"
else:
   print "True"

Gives:
Code:
  File "test2.py", line 9
    print "It's 7"
    ^
IndentationError: unexpected indent
You get the exact line number where you can fix it...
 
I see, I guess L2j used a weird version of python, cause I remember getting completely different errors pointing at the beginning (Line 0) of the file complaining about ... "Unexpected end of if statement" or something. =/
 
Stian is one of the developers of theforgottenserver, I think he already knows the plans.

Ok, didn't know that.

I don't get why the script engine needs a change after revscriptsys :s
 
well, pretty nice idea, still will be a bit complicated to move from lua, but python is much better I guess...
 
Last edited:
Well, elf want to support both lua systems. But we'll see how it turns out. Gonna be some huge changes to 0.5 (or later 0.4?) that might break all current lua scripts anyway. We're still open for suggestions regarding any wanted changes to both lua and other engines. Still, we can't maintain 5-6 engines (like lua, lua revscriptsys, python, c#, c++ etc). I still keep my vote for Python as it forces people to write nice and readable scripts.

You can't make Python like this:
if a==True:
module.callSomething()PrintShit()DoThis()
elif a==10:
doSomethingElse()PrintOk()
else
raise Error
It won't work

Here is a small hack to write ugly code :p
Code:
def c(do,do2=None):
   exec(do)
   if do2!=None:
      exec(do2)

c('print "Hey"',c('print "My name is...,"',c('print "Ugly code"',c('print "I know that 2+2 is %s"' % str(2+2)))))

This will print:
I know that 2+2 is 4
Ugly code
My name is...,
Hey


On the most ugly way I would think of.
 
If it is possible I think a .NET language is better. This has great tools to program in and it is very easy to understand.
 
Back
Top