Starting the game: Player Health and Combat

Toel47
22 Mar 2013, 22:16
I am attempting to create my first game in Quest - the first bit showing that I have no experience.

The thing I am interested in is combat, and as a devision of that, health. I want to be able to set the Player's starting health at something like 800 (with certain Classes, e.g. Fighter, getting more). However, when ever I try to design a script that set's "player"'s "health" attribute to 800, the side bar only shows "Health: %". I have "Show health" ticked under "game" as well.

I was wondering how to get the game to set the Player's starting health at 800 - in a situation were I can then use "If..." script to change the health depending on Class (Mages and Spellcasters would have around 500, Fighters and Soldiers around 1,000).

Any help with this would be greatly appreciated. Thanks in advance! :)

HegemonKhan
23 Mar 2013, 05:39
what you're asking for, unfortunately, isn't exactly easy for noobs, but here we go, hehe. GOOD LUCK! lol

(I'll help you through this, so just ask away, as I'm sure you'll need to do so, and this isn't a perfect guide either, I likely got some mistakes and other problems, and oops... I was going to say that if you got this all correct, you'd be dying as I left out a small tweak~addition that is needed lol ... except we haven't set up death yet... so nvm haha... )

I haven't really looked at how the built-in health works, it confuses me too, lol.

however, you can just click on this option to turn it off, and create your own health attribute.

in he gui~editor mode, you understand about the left and right panes, correct ?

left pane, contains the "tree" of stuff:

Objects
-> Game
->-> Verbs
->-> Commands
-> Room
->-> Player
Functions
Timers
Walkthrough
Advanced
-> Included Libraries
->-> English.aslx
->-> Core.aslx
-> Templates
-> Dynamic Templates
-> Object Types
-> Javascript

and right pane, displays further details of whatever you got highlighted on the left pane's tree of stuff.

-------------------

I still use quest version 5.3, so if you're using the (beta) v5.4, some things might be different.

-------------------

so, first we want to to turn off the built-in health option (only if it is on lol), which we do by:

Game (left pane ~ click on it to highlight it) -> Player (right pane, the Tab called "player" at top, click on it) -> Show Health box (right pane) -> make sure it is UNchecked

now, to make your own health attributes:

Player (left pane ~ click on it to highlight it) -> Attributes (right pane, the Tab called "attributes" at top, click on it) -> Attributes box (right pane, at the bottom) -> Add ->

name: hp
type: integer (select this choice in the small box at bottom)
value: 0

Player (left pane ~ click on it to highlight it) -> Attributes (right pane, the Tab called "attributes" at top, click on it) -> Attributes box (right pane, at the bottom) -> Add ->

name: current_hp
type: integer (select this choice in the small box at bottom)
value: 0

Player (left pane ~ click on it to highlight it) -> Attributes (right pane, the Tab called "attributes" at top, click on it) -> Attributes box (right pane, at the bottom) -> Add ->

name: maximum_hp
type: integer (select this choice in the small box at bottom)
value: 0

I'm showing you how to do a bit more complexity with the health~life~hit points, so let me explain what you've done, for what we will be doing with it:

the "hp" is going to be used, in order, to display your hp as:

Hp: 999 / 999

and the "current_hp" and "maximum_hp" is pretty self explanatory, I hope, lol:

Hp: (current_hp) / (maximum_hp)

-------

but, we still got more to do still, so now do this:

Player (left pane ~ click on it to highlight it) -> Attributes (right pane, the Tab called "attributes" at top, click on it) -> Status Attributes box (right pane, at the top) -> Add ->

name~key: hp
format string~value: !

this will create the display when you're playing the game, in the status pane on the right side.

-------

there's a bit more to do though, for getting it to display Hp: 999 / 999, so now do this:

Object (left pane ~ click on it to highlight it) ->

at the very top, on the bar that reads~has: File ~ Edit ~ Add ~ Tools ~ Help, click on "Add", and choose: Turn Script ->

(it should look like this, in your right pane)

Turn script
Turn Script
Name:
[] Enabled when the game begins
Script: (script tool bar)
-> Add New Script

name: game_turns_turnscript
[X] Enabled when the game begins
Script -> Add New Script -> Variables -> Set a variable or attribute ->

Set variable game.pov.hp = [expression] Hp: game.pov.current_hp + " / " + game.pov.maximum_hp

This is the final part, to get it to display it when you're playing the game

---------

but, while we're here, we're going to set the game turns counter too, so do this:

(still with the turn script stuff) -> Script -> Add New Script ->

Set variable game.turns = [expression] game.turns + 1

alright, we're done with the turn script stuff.

-------

however, we got to really quick add the turns attribute, and its status display, to the game object, so now do this:

Game (left pane ~ click on it to highlight it) -> Attributes (right pane, the Tab at the top called "Attributes" ~ click on it) -> Attributes (the box at the bottom) -> Add ->

name: turns
type: integer (select this option from the small box)
value: 0

Game (left pane ~ click on it to highlight it) -> Attributes (right pane, the Tab at the top called "Attributes" ~ click on it) -> Status Attributes (the box at the top) -> Add ->

name~key: turns
format string~value: !

alright, we're done with setting up the game turns

-------------

now, for the character creation ;)

(hopefully you get what I mean now, so I'm not going to put in the comments that you should already understand now)

Game -> Script (Tab) -> Start Script -> Add New Script ->

Output -> Print A Message ->

Print [message] "What is your name?"

Add New Script ->

Output -> Get input -> Get input, then -> run script ->

Variables -> set a variable or attribute ->

Set variable -> game.pov.alias = [expression] result

Add New Script ->

Output -> Print A Message ->

Print [expression] "-" + game.pov.alias

Add New Script ->

Output -> Show a menu ->

Show menu with caption [text] "What is your race?"
-> Options from list/dictionary split ("human;dwarf;elf;orc",";")
-> Allow player to cancel [yes or no, as it's up to you, lol]
-> After choosing, run script ->
->-> Variables -> set a variable or attribute ->

Set variable -> game.pov.race = [expression] result

->->-> Add New Script (same as above, such as if you want to do for example, "class" and~or whatever else, just follow the same attern, though it has to be indenting "nesting" further right each time, so be careful, make sure you are clicking on the right script adding buttons, hehe)

(HK's note: I use the " -> " 's for representing "indenting" or "nesting" of the script)

here's what an example would look like:

Game -> Script (Tab) -> Start Script ->

Print [message] "What is your name?"
Get input, then -> run script
-> game.pov.alias = [expression] result
-> Print [expression] "-" + game.pov.alias
-> Print [message] "What is your age?"
-> Get input, then -> run script
->-> game.pov.age = [expression] result
->-> Show menu with caption [text] "What is your gender?"
->->-> Options from list/dictionary split ("male;female",";")
->->-> Allow player to cancel [no]
->->-> After choosing, run script
->->->-> game.pov.gender = [expression] result
->->->-> Show menu with caption [text] "What is your race?"
->->->->-> Options from list/dictionary split ("human;dwarf;elf;orc",";")
->->->->-> Allow player to cancel [no]
->->->->-> After choosing, run script
->->->->->-> game.pov.race = [expression] result
->->->->->-> Show menu with caption [text] "What is your class?"
->->->->->->-> Options from list/dictionary split ("warrior;cleric;mage;thief",";")
->->->->->->-> Allow player to cancel [no]
->->->->->->-> After choosing, run script
->->->->->->->-> game.pov.class = [expression] result
->->->->->->->-> Print [expression] game.pov.alias + " is a " " + game.pov.age + " year old " + game.pov.gender + " " + game.pov.race + " " + game.pov.class +"."
->->->->->->->-> Wait for key press, then run script
->->->->->->->->-> Clear the screen


now, the harder (or more cumbersome, lol) part:

assigning your hp (and~or other stats based upon your charater reation choices) amount

this part will look like this (I'm going to keep this very simple, lol):

Add New Script -> Scripts -> Switch... ->

Switch: game.pov.class
-> Cases
->-> Key: "warrior"
->->-> Script: game.pov.current_hp = [expression] 999
->->-> Script: game.pov.maximum_hp = [expression] 999
->-> Key: "cleric"
->->-> Script: game.pov.current_hp = [expression] 500
->->-> Script: game.pov.maximum_hp = [expression] 500
->-> Key: "mage"
->->-> Script: game.pov.current_hp = [expression] 250
->->-> Script: game.pov.maximum_hp = [expression] 250
->-> Key: "thief"
->->-> Script: game.pov.current_hp = [expression] 750
->->-> Script: game.pov.maximum_hp = [expression] 750

this part can be put after the: "Clear the screen", see below for how it will look
(and it gets more messy~complex if you want to have such as male~female affect your starting stats as well too, lol. Switches within switches... enjoy, lol)

here's what it would look like:

Game -> Script (Tab) -> Start Script ->

Print [message] "What is your name?"
Get input, then -> run script
-> game.pov.alias = [expression] result
-> Print [expression] "-" + game.pov.alias
-> Print [message] "What is your age?"
-> Get input, then -> run script
->-> game.pov.age = [expression] result
->-> Show menu with caption [text] "What is your gender?"
->->-> Options from list/dictionary split ("male;female",";")
->->-> Allow player to cancel [no]
->->-> After choosing, run script
->->->-> game.pov.gender = [expression] result
->->->-> Show menu with caption [text] "What is your race?"
->->->->-> Options from list/dictionary split ("human;dwarf;elf;orc",";")
->->->->-> Allow player to cancel [no]
->->->->-> After choosing, run script
->->->->->-> game.pov.race = [expression] result
->->->->->-> Show menu with caption [text] "What is your class?"
->->->->->->-> Options from list/dictionary split ("warrior;cleric;mage;thief",";")
->->->->->->-> Allow player to cancel [no]
->->->->->->-> After choosing, run script
->->->->->->->-> game.pov.class = [expression] result
->->->->->->->-> Print [expression] game.pov.alias + " is a " " + game.pov.age + " year old " + game.pov.gender + " " + game.pov.race + " " + game.pov.class +"."
->->->->->->->-> Wait for key press, then run script
->->->->->->->->-> Clear the screen
Switch: game.pov.class
-> Cases
->-> Key: "warrior"
->->-> Script: game.pov.current_hp = [expression] 999
->->-> Script: game.pov.maximum_hp = [expression] 999
->-> Key: "cleric"
->->-> Script: game.pov.current_hp = [expression] 500
->->-> Script: game.pov.maximum_hp = [expression] 500
->-> Key: "mage"
->->-> Script: game.pov.current_hp = [expression] 250
->->-> Script: game.pov.maximum_hp = [expression] 250
->-> Key: "thief"
->->-> Script: game.pov.current_hp = [expression] 750
->->-> Script: game.pov.maximum_hp = [expression] 750


--------------

lastly is how to change your hp:

all you got to do is to add these wherever you want them to be:

(of game.pov ~ you can do the same on, and so, your enemies~monsters, have hp too, just switch game.pov with your enemy~monster 's name

for decreasing the hp:

game.pov.current_hp = [expression] game.pov.current_hp - the_amount_you_want_to_lose

for increasing the hp:

game.pov.current_hp = [expression] game.pov.current_hp + the_amount_you_want_to_gain

----------------

the "character creation" is only for the start of the game, your starting stats.

if you want your stats to change during the game, like at level ups, based upon your, for example, "class", then, you'll need to ask me how to do this, (and likely you'd need to just ask me how to do a "level up" too, hehe).

none of this stuff is easy for a noob to do, you really should start out with much simplier stuff first ;)

---------------

P.S.

if you're interested in learning to work with the code, it is a lot easier for me to guide you, and also for you too.

it's not easy to help a person through using the gui~editor mode, using the code directly or via Code View mode, is much easier for both of us.

---------------

P.S.S.

I'd recommend working through the tutorial first, get that stuff understood, then you'd be more ready for working with quest.

here's the link to the tutorial: http://quest5.net/wiki/Tutorial

enjoy ;)

Toel47
23 Mar 2013, 16:25
Thank you, this is really helpful (I know have fully-working Character Creation with name, gender and class being taken into account, and each class effects what you get out of the 6 stats [starting health, strength, resistance, dexterity, faith and magic]).

You mentioned explaining how to apply a level up? I have established an "xp" stat (stating at "current_xp" = 0, "lvl_xp" = 200) and assume that to make a level up I would just have to add:

If: [expression] player.current_xp = player.lvl_xp

And then apply the Level Up, increasing all other stats but changing the "current_xp" back to 0 and the "lvl_xp" to something higher, say, 220. (I might also add a stat called "Level")

However, I am not sure about where would I put this "If..." statement? I am thinking the "Turn Script" might work OK, but that might slow the game down - i don't know.

Thanks for the help already, and any further help would be greatly appreciated.

levicki
23 Mar 2013, 20:00
Level up check should go after player earns XP. Every time you add XP to his current XP you should check if he is ready for a level up. No need to put that in a turn script. I suggest you make a function which adds XP and does the check, and another one which does actual level up.

sonic102
23 Mar 2013, 21:50
The health value is a percentage, and obviously percentages never exceed 100.

Alternatives:

1. Change 800 to 80%
2. Make a new attirbute

Option 1 is limiting but easy but Option 2 allows more control.

XP: Add a function CheckLevelUp that checks xp, adds levels etc. Add another function AddXP that has a parameter of 'integer'.
This should add Xp of parameter 'integer', call function CheckLevelUp, print messages, etc. Now when you add XP, call AddXP with the parameter of how much xp you want to add.

HegemonKhan
24 Mar 2013, 06:43
I'm tired after doing that long explanation, so hopefully you can work with the game code, lol.

--------

Don't worry about using the turn script, in regards to slowing the game down, as Jaynebonne explained to me in a different question that I had asked a while ago, that the game engine can do like trillions of code a second (or whatever lol), so you don't have to worry about any slow down, that is, if I understood him correctly, lol. I think there's no slow down in terms of it processing the code, but maybe if you have a bunch of objects in the game, that may slow down it's initial game load up time.

however, you might not want to use the turn script (with the level up function inside of it), as levicki mentioned, there's many ways of doing stuff or locations of where to do stuff.

-----------

Pixie helped me do all of this stuff, as I was a full noob back then too, so credit goes to him~her.

Anyways, the level up isn't done in the same way as like with the hp, you do *NOT* want to use the same structure of "current and maximum" for your level up and experience.

the structure~system we're going to use is this:

we need to create an equation~formula~algorithm that achieves this (see much further below for the level up function and the equations that I used):

(well, you can set up your equation to however you want to do your exp to level, your level up set up. I decided that I wanted it to be: level 1 = +100 exp needed, level 2 = +200 exp needed, level 3 = +300 exp needed, etc etc etc)

if game.pov*(game.pov = player).exp >= 100, then player.level (0) + 1 = 1
if game.pov*(game.pov = player).exp >= 200, then player.level (1) + 1 = 2
if game.pov*(game.pov = player).exp >= 300, then player.level (2) + 1 = 3

so, as you can see, no need for using "current and maximum" experience. We just increase the level attribute by 1 each time, the required exp is met for increasing that level up.

*v5.3 allowed us to have multiple player objects (such as if we wanted to change control between our party members), so in v5.2, there was only the "player" for your control character, now we can make a bunch of "player objects" (such as "Conan, Thor, Odin, etc etc", and the current control is known as game.pov

game.pov = "player or frodo (player object 1)" or "conan (player object 2)" or "thor (player object 3)" ~ whoever you've asigned to be controlled

so, in v5.2, it was just: player.experience

now in v5.3, it is: game.pov, and if you're controlling "player", then game.pov will show "player" 's inventory for example, and you'll move the "player" around as you play the game. If you're controlling "thor (player2)", then game.pov will show "thor" 's inventory for example, and you'll move "thor" around as you play the game. So, 5.3 and it's use of game.pov, enables you to have "player" in the castle dungeon, trying to get free, and "thor" in the town, trying to break into the castle dungeon to free "player", being able to switch between them, controlling one, and then controlling the other, switching back and forth.

game.pov represents whoever (whichever "player object") you're currently controlling. But, you can still give specific codes to the individual player objects too, you can still use: player.exp, but that will only apply to your "player" player object. If you use game.pov.exp, that will be used for all of your player objects ("player", "thor", "odin"). So, you need to use whichever is the one you want to use: game.pov (game.pov.exp) or the individual player object (such as "player", player.exp). If you want to keep stats (or whatever stat, separate for each player object, then you don't want to be using game.pov).

pov = point of view = who you're controlling

it's game.pov, because the pov is under (a "child" of) the game object.

just as exp is under (a "child" of) the "player" 's as an attribute (in: player.exp)

player1.exp = the exp is only an attribute amount (integer) of player1
game.pov.exp = the exp is a shared attribute amount (integer) of player1, player2, player3, etc etc etc

Sorry, if I'm confusing you more, lol, it's hard to explain this well, at least for me, lol.

-------------

I use the turn script, but you can set up or place this stuff however or wherever you want.

I have a level up function (which does the level up), and then I put it into the turn script, as that will use the function each turn, checking and doing the level up (if you've got the needed exp) automatically. Though, this isn't the only way of doing it.

I also have exp potion objects, giving 100 and 300 exp, to test that I have everything working correctly.

here's a quick game code, of an old file I have on this stuff (level up, character creation, race~class level up stat bonuses, and experience potions):

<!--Saved by Quest 5.2.4515.34846-->
<asl version="520">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Testing Game Stuff">
<gameid>cd102f9d-370a-4bda-b6ea-ca42288f619c</gameid>
<version>1.0</version>
<start type="script">
msg ("What is your name?")
get input {
msg (" - " + result)
player.alias = result
show menu ("What is your gender?", split ("male;female" , ";"), false) {
player.gender = result
show menu ("What is your race?", split ("human;elf;dwarf" , ";"), false) {
player.race = result
show menu ("What is your class?", split ("warrior;cleric;mage;thief" , ";"), false) {
player.class = result
msg (player.alias + " is a " + " " + player.gender + " " + player.race + " " + player.class + ".")
}
}
}
}
</start>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="defaultplayer" />
<statusattributes type="stringdictionary">level = ;experience = ;turns = </statusattributes>
<level type="int">0</level>
<experience type="int">0</experience>
<turns type="int">0</turns>
</object>
<object name="potion100">
<inherit name="editor_object" />
<alias>100 exp potion</alias>
<take />
<alt type="list"></alt>
<displayverbs>Look at; Take; Drink</displayverbs>
<inventoryverbs>Look at; Use; Drop; Drink</inventoryverbs>
<drink type="script">
msg ("You drink the exp potion, receiving 100 experience.")
player.experience = player.experience + 100
</drink>
</object>
<object name="potion300">
<inherit name="editor_object" />
<alias>300 exp potion</alias>
<take />
<displayverbs>Look at; Take; Drink</displayverbs>
<inventoryverbs>Look at; Use; Drop; Drink</inventoryverbs>
<drink type="script">
msg ("You drink the exp potion, receiving 300 experience.")
player.experience = player.experience + 300
</drink>
</object>
</object>
<turnscript name="turns lvlup script">
<enabled />
<script>
lvlup
player.turns = player.turns + 1
</script>
</turnscript>
<function name="lvlup"><![CDATA[
if (player.experience >= player.level * 100 + 100) {
player.experience = player.experience - (player.level * 100 + 100)
player.level = player.level + 1
switch (player.gender) {
case ("male") {
player.strength = player.strength + 1
}
case ("female") {
player.agility = player.agility + 1
}
}
switch (player.race) {
case ("dwarf") {
player.strength = player.strength + 2
}
case ("elf") {
player.agility = player.intelligence + 2
}
case ("human") {
player.strength = player.strength + 1
player.agility = player.agility + 1
}
}
switch (player.class) {
case ("warrior") {
player.strength = player.strength + 2
}
case ("cleric") {
player.intelligence = player.intelligence + 1
player.agility = player.agility + 1
}
case ("mage") {
player.intelligence = player.intelligence + 2
}
case ("thief") {
player.strength = player.strength + 1
player.agility = player.agility + 1
}
}
lvlup
}
]]></function>
</asl>


my level up works like this:

level 1 requires +100 experience, going from 0 to 100 exp (level 0-1), and thus 100 total experience (level 0-1)
level 2 requires +200 experience, going from 0 to 200 exp (level 1-2) (you start from 0 experience for each new level progression, but you also get your extra exprience to carry over too towards your new level progression), and thus 300 total experience (level 0-2)
level 3 requires +300 experience, going from 0 to 300 exp (level 2-3), and thus 600 total experience (level 0-3)
level 4 requires +400 experience, going from 0 to 400 exp (level 3-4), and thus 1,000 total experience (level 0-4)
level 5 requires +500 experience, going from 0 to 500 exp (level 4-5), and thus 1,500 total experience (level 0-5)

so, for example:

you're at level 0 (and with 0 exp) and you drink the 300 exp potion:

100 (out of the 300) exp earns level 1 (0-100 exp), with 200 exp left over
200 (out of the 300) exp earns level 2 (0-200 exp), with 0 exp left over

now, let's say you're level 1 (and with 0 extra ~ carry over ~ exp) and you drink the 300 exp potion:

200 (out of the 300) exp earns you level 2 (0-200), with 100 exp left over
100 (out of the 300) exp is 100 exp towards level 3, which needs, 300 experience (0-300, so you only got 100 out of the 300 exp that is needed for earning level 3), so you're still level 2 (with 100/300 exp towards earning level 3)

---------

here's the level up function (without the stat bonuses):

<function name="lvlup"><![CDATA[
if (player.experience >= player.level * 100 + 100) {
player.experience = player.experience - (player.level * 100 + 100)
player.level = player.level + 1
lvlup
}
]]></function>


plug in 0 for the "player.level": if (player.experience >= player.level * 100 + 100) {

if player.exp is greater than or equal to player.level times 100 + 100
if player.exp is greater than or equal to 0 x 100 + 100
if player.exp is greater than or equal to 100

than: player.level (new~next, output) = player.level (old~previous, input)) + 1
(plugging in 0 for the "old~previous,input" player.level):
player.level = 0 + 1 = 1
player.level = 1 (from being at level 0)

with 100 or more exp, you earn level 1 (from level 0)

you can see how the equation works, by plugging in 1,2,3,etc for player.level, as it tells you how much experience you need

and this equation, deals with the extra experience (AND it resets your exp back to 0 for the next level progression, though + the extra exp too, as you get to keep~use it for the next level progression, hehe):

player.experience = player.experience - (player.level * 100 + 100)

so, for example, let's say you drank the 300 exp potion, while at level 0

300 is greater than or equal to 100 (player.level times 100 + 100 -> 0 x 100 + 100 = 100)
you don't lose that extra 200, due to this equation:

player.experience = player.experience - (player.level * 100 + 100)
player.exp = 300 - (0 x 100 + 100)
player.exp = 300 - 100
player.exp = 200

then this: player.level = player.level + 1, increases my level:

player.level = 0 + 1
player.level = 1 (you're now at lvl 1, with 200 extra ~ carry over ~ exp towards level 2)

and thus because I have a call function script line, "lvlup", it does the equation over again:

if (player.experience >= player.level * 100 + 100) {
if (200 >= 1 * 100 + 100) {
if (200 >= 200) { (yes: 200 = 200)
then again check~do the extra exp equation:
player.experience = player.experience - (player.level * 100 + 100)
player.experience = 200 - (1 * 100 + 100)
player.experience = 200 - 200 = 0
and, also raise the level (as you had the 200 exp that was needed):
player.level = player.level + 1
player.level = 1 + 1 = 2 (you're now at level 2, with 0 extra ~ carry over ~ exp towards level 3)

and here you can see how it's resetting of exp to 0 works too:

so, for example, let's say you drank the 100 exp potion, while at level 0 (and with 0 exp):

player.experience = player.experience - (player.level * 100 + 100)
player.experience = 100 - (0 * 100 + 100)
player.experience = 100 - 100 = 0
you've earned lvl 1, and you've got no extra exp left~carried over, and thus you're resetted to starting from 0 exp for lvl 2 (from 0 exp to 200 exp to earn level 2) and you've got no (zero = 0) extra experience added to your reset exp of at 0. (if you had extra experience, then it is added to your reset exp at 0, for: 0 + extra exp, towards the next level)

if you got exactly the exp needed for a level up, while having 0 exp, then the player.experience = player.experience will equal the (player.level * 100 + 100), and thus that minus sign will produce 0

starting at level 0 and 0 exp, getting 100 exp:

player.experience = [ player.experience ] [ minus ] (player.level * 100 + 100)
player.experience = [ 100 ] [ minus -> equals ] (0 * 100 + 100) = 0
player.experience = [ 100 [ equals ] (100) = 0
and so, since there's a minus instead of the equals, it produces 0 (how I achieve the resetting of the exp back to 0, for the next level up)
player.experience = [ 100 ] [ equal -> minus ] (100) = 0
player.experience = [ 100 ] [ minus ] (100) = 0
player.experience = [[ 0 )) = 0

(player.level * 100 + 100) = the exp needed for the level up

so, if you got exactly the exp needed for a level up (and you started with 0 exp), then you're subtracting the same amount, resulting in the resetting of your exp to 0 for the next level. And if you got extra exp (greater exp than the exp needed for the level up or for the "(player.level * 100 + 100)", then you'll have that extra exp remaining, after the subtraction, for the next level.

HegemonKhan
24 Mar 2013, 09:25
As for combat... (and other RPG elements)

you can look at Pertex' Combat Library (or mine, which is based off of Pertex', it's mostly the same, with some small changes), or Pixie's Combat Libraries. Pertex' and mine's is more like traditional RPGs (game play stops until the battle ends), and Pixie's is more direct, the gameplay isn't stopped by the battle, as there's no "battle screen which stops gameplay" like effect.

Pertex' Combat (+Equipment+dialogue menus) Library: viewtopic.php?f=10&t=2660

HK's Combat Library (it's functional ~ of physical~melee combat, but I got a lot more to do with it, lol): viewtopic.php?f=10&t=3348&p=23013#p23013 (find my "veni vidi veci" post, it's near the end ~ one of my most recent posts in the thread, as of now, it's on page 9, lol, or just see it in the code below)

<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Testing Game Stuff">
<gameid>d83ba5bb-2e3c-4f31-80c9-3e88a2dc082c</gameid>
<version>1.0</version>
<pov type="object">player</pov>
<start type="script">
cc
</start>
<turns type="int">0</turns>
<statusattributes type="stringdictionary">turns = </statusattributes>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="defaultplayer" />
<inherit name="pc" />
<cur_hp type="int">999</cur_hp>
<max_hp type="int">999</max_hp>
<str type="int">100</str>
<end type="int">100</end>
<dex type="int">100</dex>
<agi type="int">100</agi>
<spd type="int">100</spd>
<hc type="int">100</hc>
<pd type="int">100</pd>
<pr type="int">100</pr>
</object>
<object name="orc1">
<inherit name="editor_object" />
<inherit name="npc" />
<hostile type="boolean">true</hostile>
<dead type="boolean">false</dead>
<alias>orc</alias>
<cur_hp type="int">999</cur_hp>
<max_hp type="int">999</max_hp>
<str type="int">25</str>
<end type="int">25</end>
<dex type="int">25</dex>
<agi type="int">25</agi>
<spd type="int">25</spd>
<hc type="int">25</hc>
<pd type="int">25</pd>
<pr type="int">25</pr>
</object>
</object>
<turnscript name="game_turns">
<enabled />
<script>
sa
game.turns = game.turns + 1
</script>
</turnscript>
<command name="fight">
<pattern>fight #text#</pattern>
<script>
battle_system (game.pov,text)
</script>
</command>
<type name="char">
<cur_hp type="int">0</cur_hp>
<drop type="boolean">false</drop>
<defending type="boolean">false</defending>
<max_hp type="int">0</max_hp>
<str type="int">0</str>
<end type="int">0</end>
<dex type="int">0</dex>
<agi type="int">0</agi>
<spd type="int">0</spd>
<hp type="int">0</hp>
<hc type="int">0</hc>
<pd type="int">0</pd>
<pr type="int">0</pr>
</type>
<type name="pc">
<inherit name="char" />
<statusattributes type="stringdictionary">hp = ;str = ;end = ;dex = ;agi = ;spd = ;hc = ;pd = ;pr = </statusattributes>
</type>
<type name="npc">
<inherit name="char" />
<dead type="boolean">false</dead>
<hostile type="boolean">false</hostile>
<displayverbs type="list">Look at; Talk; Fight</displayverbs>
</type>
<function name="cc">
msg ("What is your name?")
get input {
game.pov.alias = result
msg (" - " + game.pov.alias)
show menu ("What is your gender?", split ("male;female" , ";"), false) {
game.pov.gender = result
show menu ("What is your race?", split ("human;dwarf;elf" , ";"), false) {
game.pov.race = result
show menu ("What is your class?", split ("warrior;cleric;mage;thief" , ";"), false) {
game.pov.class = result
msg (game.pov.alias + " is a " + game.pov.gender + " " + game.pov.race + " " + game.pov.class + ".")
wait {
ClearScreen
}
}
}
}
}
</function>
<function name="sa">
game.pov.hp = game.pov.cur_hp + " / " + game.pov.max_hp
</function>
<function name="battle_system" parameters="self,text" type="boolean">
first_value = false
enemy = GetObject (text)
if (enemy = null) {
foreach (obj,AllObjects()) {
if (obj.alias=text) {
enemy = obj
}
}
}
if (enemy = null) {
msg ("There is no " + text + " here.")
first_value = false
}
else if (not Doesinherit (enemy,"npc")) {
msg ("You can not battle that!")
first_value = false
}
else if (not npc_reachable (enemy)) {
msg ("There is no " + enemy.alias + " in your vicinity.")
first_value = false
}
else if (GetBoolean (enemy,"dead") = true) {
msg (enemy.alias + " is already dead.")
first_value = false
}
else if (GetBoolean (enemy,"hostile") = false) {
msg (enemy.alias + " is not hostile.")
first_value = false
}
else if (battle_sequence (self,enemy) = true) {
msg ("The battle is over.")
first_value = true
}
return (first_value)
</function>
<function name="battle_sequence" parameters="self,enemy" type="boolean"><![CDATA[
second_value = false
if (enemy.dead = false) {
if (GetInt (self,"spd") > GetInt (enemy,"spd")) {
on ready {
msg ("You get to go first for this round")
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
}
on ready {
if (enemy.dead = false) {
if (enemy_battle_turn (self,enemy) = true) {
msg ("The round has ended.")
}
}
}
on ready {
battle_sequence (self,enemy)
}
}
else if (GetInt (self,"spd") < GetInt (enemy,"spd")) {
on ready {
msg (enemy.alias + " gets to go first for this round.")
if (enemy_battle_turn (self,enemy) = true) {
msg ("It is now your turn.")
}
}
on ready {
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
else {
msg ("The round has ended.")
}
}
on ready {
battle_sequence (self,enemy)
}
}
else if (GetInt (self,"spd") = GetInt (enemy,"spd")) {
if (RandomChance (50) = true) {
on ready {
msg ("You get to go first for this round")
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
}
on ready {
if (enemy_battle_turn (self,enemy) = true) {
msg ("The round has ended.")
}
}
on ready {
battle_sequence (self,enemy)
}
}
else {
on ready {
msg (enemy.alias + " gets to go first for this round.")
if (enemy_battle_turn (self,enemy) = true) {
msg ("It is now your turn.")
}
}
on ready {
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
else {
msg ("The round has ended.")
}
}
on ready {
battle_sequence (self,enemy)
}
}
}
}
else {
second_value = true
}
return (second_value)
]]></function>
<function name="self_battle_turn" parameters="self,enemy" type="boolean"><![CDATA[
third_value = false
msg (self.alias + " has " + self.cur_hp + " HP left.")
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
wait {
show menu ("What is your battle choice?", split ("Attack;Defend;Cast;Item;Run", ";"), false) {
switch (result) {
case ("Attack") {
fourth_value = false
if (RandomChance (GetInt (enemy,"agi") - GetInt (self,"spd")) = true) {
msg (enemy.alias + "evaded your attack!")
fourth_value = true
}
else if (RandomChance (GetInt (enemy,"Dex") - GetInt (self,"agi")) = true) {
msg (enemy.alias + "parried your attack!")
fourth_value = true
}
else if (RandomChance (GetInt (enemy,"agi") - GetInt (self,"dex")) = true) {
msg (enemy.alias + "blocked your attack!")
fourth_value = true
}
else if (RandomChance (GetInt (self,"dex") - GetInt (enemy,"spd")) = false) {
msg ("Your attack missed " + enemy.alias +"!")
fourth_value = true
}
else if (RandomChance (GetInt (enemy,"pr") - GetInt (self,"hc")) = true) {
msg ("Your attack got resisted by " + enemy.alias +"!")
fourth_value = true
}
else if (fourth_value = false) {
if (self.defending = true and enemy.defending = true) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * 2 * GetInt (self,"pd") / 2 + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
self.defending = false
}
else if (self.defending = true and enemy.defending = false) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * 2 * GetInt (self,"pd") + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
self.defending = false
}
else if (self.defending = false and enemy.defending = true) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * GetInt (self,"pd") / 2 + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
}
else if (self.defending = false and enemy.defending = false) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * GetInt (self,"pd") + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
}
}
}
case ("Defend") {
if (self.defending = false) {
self.defending = true
}
}
case ("Cast") {
self.defending = false
}
case ("Item") {
self.defending = false
}
case ("Run") {
self.defending = false
}
}
if (GetInt (enemy,"cur_hp") > 0) {
if (RandomChance (GetInt (self,"spd") - GetInt (enemy,"spd")) = true) {
msg ("You get an extra battle turn!")
self_battle_turn (self,enemy)
}
else {
msg ("Your battle turn is over.")
third_value = false
}
}
else if (GetInt (enemy,"cur_hp") <= 0) {
msg (enemy.alias + " is dead.")
msg ("You have won the battle!")
enemy.defending = false
enemy.dead = true
third_value = true
wait {
ClearScreen
}
}
}
}
return (third_value)
]]></function>
<function name="enemy_battle_turn" parameters="self,enemy" type="boolean"><![CDATA[
fifth_value = false
msg (self.alias + " has " + self.cur_hp + " HP left.")
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
result = GetRandomInt (1,3)
switch (result) {
case (1) {
sixth_value = false
if (RandomChance (GetInt (self,"agi") - GetInt (enemy,"spd")) = true) {
msg ("You have evaded the attack!")
sixth_value = true
}
else if (RandomChance (GetInt (self,"dex") - GetInt (enemy,"agi")) = true) {
msg ("You have parried the attack!")
sixth_value = true
}
else if (RandomChance (GetInt (self,"agi") - GetInt (enemy,"dex")) = true) {
msg ("You have blocked the attack!")
sixth_value = true
}
else if (RandomChance (GetInt (enemy,"dex") - GetInt (self,"spd")) = false) {
msg (enemy.alias +"'s attack missed!")
sixth_value = true
}
else if (RandomChance (GetInt (self,"pr") - GetInt (enemy,"hc")) = true) {
msg ("You resisted the attack!")
sixth_value = true
}
else if (sixth_value = false) {
if (enemy.defending = true and self.defending = true) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * 2 * GetInt (enemy,"pd") / 2 + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
enemy.defending = false
}
else if (enemy.defending = true and self.defending = false) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * 2 * GetInt (enemy,"pd") + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
enemy.defending = false
}
else if (enemy.defending = false and self.defending = true) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * GetInt (enemy,"pd") / 2 + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
}
else if (enemy.defending = false and self.defending = false) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * GetInt (enemy,"pd") + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
}
}
}
case (2) {
if (enemy.defending = false) {
msg (enemy.alias + " has choosen to defend itself.")
enemy.defending = true
}
}
case (3) {
enemy.defending = false
msg ("Cast")
}
}
if (GetInt (self,"cur_hp") > 0) {
if (RandomChance (GetInt (enemy,"spd") - GetInt (self,"spd")) = true) {
msg (enemy.alias + " gets an extra battle turn!")
wait {
enemy_battle_turn (self,enemy)
}
}
else {
msg (enemy.alias + " 's battle turn is over.")
fifth_value = true
}
}
else if (GetInt (self,"cur_hp") <= 0) {
msg (self.alias + " has died.")
msg ("GAME OVER")
finish
}
return (fifth_value)
]]></function>
<function name="npc_reachable" parameters="object" type="boolean">
value = false
foreach (x,ScopeReachableNotHeld ()) {
if (x=object) {
value = true
}
}
return (value)
</function>
<function name="crit_hit" parameters="object" type="int">
if (RandomChance (GetInt (object,"luck")) = true) {
value = 2
}
else {
value = 1
}
return (value)
</function>
</asl>


and here's just a key~legend for all the terms and~or abreviations that I used:

01. cc = character creation function
02. sa = status attributes (mainly for implementing/displaying of ' cur / max ' stats) function
03. char = character object type ("pcs", "npcs", "monsters", etc., so, not a room, item, equipment, spell, etc)
04. pc = playable character object type ("player" characters / game.povs)
05. npc = non-playable character ("people", "monsters", and etc, so not a "player" character / not a game.pov, I'm going to have a hostility system, so any npc can be friendly or hostile, instead of having an actual "monster/enemy" type set aside)
06. hp = hit points (life) stat attribute
07. mp = mana points (magic) stat attribute
08. str = strength (physical damage, carry weight / equipment requirement, etc) stat attribute
09. end = endurance (physical defense, and etc) stat attribute
10. dex = dexterity (weapon~attack skill, think of this as "if your attack connects or not, do you 'whiff' or not", so not to gete confused with hc, and etc) stat attribute
11. agi = agility (dodging/evading, and etc) stat attribute
12. spd = speed (who goes first in battle, extra battle turns, escaping from battle, and etc) stat attribute
13. hc = hit chance (think of this more as piercing their armor or not, so not to get confused with dex, and etc) stat attribute
14. pd = physical damage stat attribute
15. fp = fire damage stat attribute
16. wp = water damage stat attribute
17. ap = air damage stat attribute
18. ed = earth damage stat attribute
19. ld = light damage stat attribute
20. dd = dark damage stat attribute
21. pr = physical resistance stat attribute
22. fr = fire resistance stat attribute
23. wr = water resistance stat attribute
24. ar = air resistance stat attribute
25. er = earth resistance stat attribute
26. lr = light resistance stat attribute
27. dr = dark resistance stat attribute
28. defending = boolean (reduces damage done for that character and increases the damage done by that character, if they chosoe to attack on the next turn)
29. escaped = boolean, run from battle (not completed/implemented yet)
30. hostile = boolean, any npc can be friendly or a(n) "monster/enemy", based upon a hostility scale (0-100), but not completed
31. dead = boolean
32. crit_hit = critical hit (bonus damage based upon luck)
33. luck = luck stat attribute
34. lvl = level stat attribute
35. exp = experience stat attribute
36. cash = cash stat attribute (currency)
37. lvlup = level up function


Pixie's Combat Library: http://quest5.net/wiki/Simple_Combat_System_(Advanced)

Pixie's Magic Libraries: http://quest5.net/wiki/More_on_Tabs_(Advanced) , http://quest5.net/wiki/Using_Types_and_Tabs_(Advanced) , http://quest5.net/wiki/Using_Types

Chase's Wearables (Equipment) Library: http://quest5.net/wiki/Clothing_Library2

Pixies' Clothing Library: viewtopic.php?f=10&t=2567

-----------

*when you click on the links, some will say the page doesn't exist, this is because it (the url) leaves off the ")" mark, so just add this onto the url, click~enter again, and it'll take you to the page.

for example: http://quest5.net/wiki/More_on_Tabs_(Advanced

this page doesn't exist (because it's missing the ")" mark at the end of advanced, I'm not sure why the url goto does this... argh)

so just add the missing ")" mark so it looks like this: http://quest5.net/wiki/More_on_Tabs_(Advanced)

Toel47
24 Mar 2013, 12:20
Thanks, you've all been really helpful. One last thing I would like to know (as I have nearly everything working) is how to make a verb call which object it is attached to?

What I mean is this:

I have made a working verb, "attack", on my Goblin creature. It works out how much damage the player does, determines if this killed the goblin, and then gives the player XP if they did (calling the "GetIsLevel" function I made to see if you player leveled up).

What I would like to know is whether there is a term I can put in all the expressions I previously put "goblin" that would mean I could just copy this whole verb onto another monster? What would be useful is if I could also get one that replaces that "goblin" with "the target of this action" - as I have made a weapon item and am giving it's "Use" as an alternate way of making your attack.

So, I'm looking for something I can add into expressions that means "this object" and one that means "what you used this on". The terms need to work in all forms of expressions (not just in working out who's Resistance stat I'm using against the attack, but also in Print [expression] = "The " + [term] + " survived your attack!").

If you could tell me this, I would be very grateful.

EDIT: I have encountered another problem. My damage it says is dealt, and the damage done, seem completely unrelated. The first attack the enemy does says "dealt [so much] damage", but your health doesn't go down. After that, it does go down, but not by the amount said.

I'm programming it in GUI mode, the script looks like this:

Turn Script
Name: goblin_attack
[X] Enable when the game begins
Script:
-> If: [object is visible] [object] goblin
--> Then:
--> Print Message:
--> Print Message: The goblin attacked you!
--> Set variable goblin_dice_result = [expression] DiceRoll (goblin.attack_dice_number + "d" + goblin.attack_dice_sides)
--> Set variable goblin_damage = [expression] goblin_dice_result * goblin.atk - player.def_stat
--> Print [expression]: "The goblin did " + goblin_damage + " damage!"
--> If: [expression] goblin_damage < 0
---> Then:
---> Set variable goblin_damage = [expression] 0
--> Print [expression]: "Attack report: The goblin attacked with " + goblin.attack_dice_number + "D" + goblin.attack_dice_sides + " dice roll x " + goblin.atk + " bonus - enemy resistance (" + player.def_stat + ")."
--> If [expression]: goblin_damage > player.current_hp or goblin_damage = player.current_hp
---> Then:
---> Set variable player.current_hp = [expression] 0
---> Print [message]:
---> Print [message]: You were killed by the goblin!
---> Finish the game.
---> Else:
---> Set variable player.current_health = [expression] player.current_hp - goblin_damage
---> Print [message]: You survived the attack!

The code looks like this (on code view):
<turnscript name="goblin_attack">
<script><![CDATA[
if (ListContains(ScopeVisible(), goblin)) {
msg ("")
msg ("The goblin attacked you!")
goblin_dice_result = DiceRoll (goblin.attack_dice_number + "d" + goblin.attack_dice_sides)
goblin_damage = goblin_dice_result * goblin.atk - player.def_stat
msg ("The goblin did " + goblin_damage + " damage!")
if (goblin_damage < 0) {
goblin_damage = 0
}
msg ("Attack report: The goblin attacked with " + goblin.attack_dice_number + "D" + goblin.attack_dice_sides + " dice roll x " + goblin.atk + " bonus - enemy resistance (" + player.def_stat + ").")
if (goblin_damage > player.current_hp or goblin_damage = player.current_hp) {
player.current_hp = 0
msg ("")
msg ("You were killed by the goblin!")
finish
}
else {
player.current_hp = player.current_hp - goblin_damage
msg ("You survived the attack!")
}
}
]]></script>
<enabled />
</turnscript>


Any help with this would be greatly appreciated. I would rather edit in GUI mode, but if the only fix is in Code view I will work with it. Thanks in advance!

EDIT: Found out that the damage is not "random", nor is the starting damage "missing" - the damage is happening exactly 1 turn after the rest of the script (it deals the damage for the last attack on the turn of this attack), Hope that helps in working out what is happening! A possible explanation for this that I have come across is that the display is updated BEFORE the damage is dealt each turn. This can be explained by the fact the stats are all drawn on a "turn" script as well. Is there a way I can make the turn script happen at the end of the turn

HegemonKhan
24 Mar 2013, 18:49
NOTE 1: for the future, I (and us~others) don't need (nor want) to see your stuff in the GUI-Editor form, just copy and paste your game code, which is all that I and~or we (others) need for helping you. We can read the game code, so that is all we be needing, and it's much easier (just copy and paste it here, hehe) than trying to write in the GUI-Editor stuff or waste space by printing out the screens of the GUI~Editor stuff.

0. You seem to be getting this well, not a single question asked on something not working, with the previous stuff, WOW !!!
(It took me a long time just to get the character creation working, lol)

It'll be too hard and long for me to try to help you with doing all this stuff through the GUI-Editor mode, so hopefully, you can pick up working with the code, if you need help, I can help you deal with working~using the code.

you seem to already know this, but just in case:

you can view the game file code in two ways

one way is in the GUI~Editor mode, at the top is a button that looks like a note paper, between the play and ? (help) buttons. This is a toggle button between the GUI-Editor mode and the Code View mode.

the other way is to simply open up the game file with notepad, notepad++, or wordpad

(I recommand downloading the latest version of notepad++, it's really handy for working with code)

also, you can highlight and copy your entire game code, and then post it here (as you've already done, lol), which allows us to look at it, making it easier for us to know what you're doing, trying to do, and how to then help you or fix problems you may have.

And use this code (which you already know too, lol) for posting it here:

[code.]you game file code[/code.]

but without the dots in the [ code ] 's

1. you're now getting into learning about a few more code types, and a bit more advanced stuff, which is needed for what you're asking about now.

Verbs are "local" (they only work on that single object that you created the verb for and on~upon it), for example, the verb you created for your goblin, only works for that single object, which you uniquely named goblin ("Name" attributes are unique, you can never create anything with the same "name", as the "name" is the identifier for the game engine. However, you can also assign an "alias" attribute, and so multiple objects can have the same alias, as the game engine still continues to identify the object by its name attribute).

for example:

object.name.goblin
object.name.goblin = error (can't have two objects with the same name attribute, of example, "goblin")

object.name.goblin1
object.name.goblin2 = no error

then you can assign alias attributes:

goblin1.alias.goblin
goblin2.alias.goblin = no error

do note, that if you have an alias, that is what the game player will see. The game player will only see the name if there's no alias. So, you can use the name, to help you catelog~organize~inform you of what the object is for or whatever about it, and then use the alias, for the game player, as you nor the game player, wants to see: name.goblin1_red_mountain_area_50_hp, lol.

also, when using commands and the "GetObject" function, it'll search for an object with that NAME, which can be a problem as the player tries to type in the alias, and the game engine searches for a NAME and thus doesn't find an object with that word, as that word only exists as an object's alias. There is however, a method to deal with this, but let's not worry about this until it happens, lol.

which leads perfectly into the next thing:

Commands

Commands are universal verbs, so this is something you might want to use. Commands operate by the game player typing in an input. Whereas verbs gives you the button to push on the right pane or as a hyperlink in the left pane's text.

here's an example of how a command can be set up (see the tutorial too, as it helps with learning commands):

<command name="attack">
<pattern>attack #text#</pattern>
<script>
attack_function (text)
</script>
</command>


the command is activated by the game player, when he types in (for example): attack goblin

and in this example, it activates the function: attack_function (text)

and now, this leads us into:

Functions

Functions can do more things than Scripts, such as assigning parameters and~or return values of a specified type.

so, continuing our example:

<command name="attack">
<pattern>attack #text#</pattern>
<script>
attack_function (text)
OR
attack_function (game.pov,text)
</script>
</command>

<function name="attack_function" parameters="text2">
OR
<function name="attack_function" parameters="self,text2">
enemy = GetObject (text)
if (enemy = null) {
foreach (obj, AllObjects ()) {
if (obj.alias=text) {
enemy = obj
} else {
msg ("There seemingly is no " + text + "here.")
}
}
}
do whatever you want here, whatever you got set up for your attack system.
</function>


so...

Parameters

in the command, you got: attack #text#
the function call in the command's script, "attack_function", will use (the parameters) what the game player typed in for the #text#

for example:

game player types in: attack goblin
so now in the command' script's function call line: attack_function (parameter: text) will be known as attack_function (parameter: goblin) to the game engine

now, in the function: attack_function (text2), the the goblin will now be assigned to the new parameter: text2, which is used within this function itself.

do note that the carry over from parameter to parameter, is matched up by order:

parameter="item1=goblin1,item2=goblin2,item3=goblin3"
new parameters of new code block="red,blue,yellow"

so:

red = goblin1
blue = goblin2
yellow = goblin3

you can see this in the example with using the parameters="game.pov,text"

in the command, game.pov and text is plugged into the call function's parameters: attack_function (game.pov,text)

and now in the attack_function itself, the first parameter, game.pov, is plugged into the new first parameter, self, so game.pov -> self, and the second parameter, text, is plugged into the new second parameter, text, so text -> text.

now through the game engine, the attack_function will identify any usage of "self" as "game.pov", so for example if I were to code this inside of attack_function:

self.strength = strength + 50

guess what would happen?

my game.pov (for example, "player"), would now have 50 more strength, for it's strength attribute (game.pov.strength).

and I do do the same with the other parameter (in this example): text

such as coding this inside of the attack_function:

enemy = text
enemy.strength = enemy.strength - 50

guess what would happen?

the object that the game player typed in for the attack command, will now have 50 less strength for its strength attribute (such as: orc.strength)

though you can see it's a bit more complicated... too complicated to explain, unless you want to be using commands like this, lol. Then I'll try to help and explain you through it, otherwise, I don't want to take the time to try to do so.

----

you can copy and paste your verb code into a function, and create a command that calls upon that function.

then we'd jsut need to set up the parameters, so that it can work on any object, but the problem is that the object must be typed in by the game player...

your other option is to simply copy and paste your verb code for each monster~enemy object that you create, lol.

-----

I'm not sure if there's any other way to do it besides, commands and verbs... so maybe someone else can help you then, if there are other ways to do this.

2. Another thing you need to learn is object types (it's under the "advanced" on the left pane's tree of stuff in the GUI~Editor)

object types enables you to create a "group" of attributes, and then you can simply assign that "group" to your objects, and they'll get all the attributes of that assigned "group", the term "inherit" is used in the code, see below:

for examples:

<type name="snake_type">
<strength type="int">10</strength>
<endurance type="int">10</endurance>
<dexterity type="int">10</dexterity>
</type>

<object name="snake1">
<inherit name="editor_object" />
<inherit name="snake_type" />
<alias>cobra</alias>
</object>

<object name="snake2">
<inherit name="editor_object" />
<inherit name="snake_type" />
<alias>python</alias>
</object>

<object name="snake3">
<inherit name="editor_object" />
<inherit name="snake_type" />
<alias>anaconda</alias>
</object>

<object name="snake4">
<inherit name="editor_object" />
<inherit name="snake_type" />
<alias>black_mamba</alias>
</object>

<type name="dragon_type">
<strength type="int">100</strength>
<endurance type="int">100</endurance>
<dexterity type="int">100</dexterity>
</type>

<type name="fire_elemental_type">
<fire_damage type="int">100</fire_damage>
<fire_resistance type="int">100</fire_resistance>
<water_resistance type="int">0</water_resistance>
</type>

<type name="water_elemental_type">
<water_damage type="int">100</water_damage>
<water_resistance type="int">100</water_resistance>
<fire_resistance type="int">0</fire_resistance>
</type>

<object name="dragon1A">
<inherit name="editor_object" />
<inherit name="dragon_type" />
<inherit name="fire_elemental_type" />
<alias>fire dragon</alias>
</object>

<object name="dragon1B">
<inherit name="editor_object" />
<inherit name="dragon_type" />
<inherit name="fire_elemental_type" />
<alias>Salamander</alias>
<water_resistance type="int">50</water_resistance>
</object>

<object name="dragon2A">
<inherit name="editor_object" />
<inherit name="dragon_type" />
<inherit name="water_elemental_type" />
<alias>water dragon</alias>
</object>

<object name="dragon2A">
<inherit name="editor_object" />
<inherit name="dragon_type" />
<inherit name="water_elemental_type" />
<alias>ice drake</alias>
<fire_resistance type="int">50</fire_resistance>
</object>


3. as for your "order of operations" problem:

you simply need to order them correctly, lol

with code~script blocks (including such as: functions, scripts, turn scripts, verbs, commands, and etc, too):

first
second
third
etc

also, about turn scripts:

they can be assigned to different locations:

if you highlighted (by clicking on) "Object" in the left pane's "tree of stuff", you create a game turn script (universal turn script), it is always running and effecting you.

if you highlighted (by clicking on), for example, "room" in the left pane's "tree of stuff", you create a turn script locally, just for that object room, "room", it is only running and effecting you, when you are in that specific place, "room".

btw, in the GUI~Editor, you can use the up and down arrows in the little greyish tool bar that appears for when you're coding the script (like with the character creation), to move code lines up and down (allowing you to create a new code line, and then move it up or down to where it needs to be, or jsut move around ~readjust your existing code lines). If you didn't already know this, that is, lol.

let me look at your game code, to be able to address and help you with your "order of operations" problem(s), so give me some time.

HegemonKhan
24 Mar 2013, 19:04
Also, you can copy (or cut) and paste script in the GUI~Editor, if you didn't know, there's buttons to do it on that little greyish script tool bar, but jsut becareful, as there's some caveats, you don't want to lose a huge script block, having to recode it all, ugh!

-------

A quick note: obviously, if you don't want to share (make public) your code with others, then do NOT do so, but if there's any code of yours that you don't mind sharing, then just copy and paste it on here, for us to look it over, to help you.

also, this is a really useful link, for working with the code:

http://quest5.net/wiki/Category:All_Fun ... t_Commands

All the different stuff that you can do, hehe ;)

and here's some links for combat, that might prove much more useful than me trying to help you, lol:

Pixie's Combat Library: http://quest5.net/wiki/Simple_Combat_System_(Advanced)

and more useful links:

http://quest5.net/wiki/Main_Page
http://quest5.net/wiki/Tutorial
http://quest5.net/wiki/How_to

object types links:

http://quest5.net/wiki/Types
http://quest5.net/wiki/Using_Types
http://quest5.net/wiki/Using_Types_and_Tabs_(Advanced)

character creation (just in case you want to look at it, lol):

http://quest5.net/wiki/Character_Creation

----------

your DiceRoll may not be set up correctly... I'm not sure, someone will have to look it over

here's how to do it normally:

http://quest5.net/wiki/DiceRoll

your "syntax~format" of it might be slightly incorrect, and I'm not too sure myself of how it should look, so try to ask someone else on this part.

as it is suppose to be (look like this):

(whatever word you want to use) = DiceRoll ("{number_amount}d{number_amount}")
result=DiceRoll("3d6")

basically the d acts as "times" [ word_15 = DiceRoll "5x3" ], but you need to have the (little case, as correct case matters!) d there in the middle for the game engine to understand the DiceRoll function.

you could (and might as well), just remove the DiceRoll, and just do your amounts times each other, lol:

goblin_dice_result = goblin.attack_dice_number * goblin.attack_dice_sides

Edit:

err... I guess it's not quite # x #, as Alex likely coded that the sides are like an actual dice (1-6 for each side, for a six-sided dice, 1-8 for each side of a eight-sided dice, in~for his RollDice function, so it's a little different than a straight up times'ing of two numbers, lol. Though, I'm not sure why you couldn't just do two numbers times each other, as you jsut want some random value, actually instead, you should use this:

GetRandomInt (min_amount,max_amount)

for example:

goblin_dice_amount = GetRandomInt (50,100)

it randomly selects some amount between 50 and 100, so the choices would be: 50, 51, ..., 99, 100

----

otherwise, if you got all the attributes in your attack_goblin script actually created on your goblin object too, then it should be working fine...

Does everything work fine? It does the attack correctly or not? (other than the problem with being out of order with the turns)

also, I'd just make a small change (re-arrangement) here:

Turn Script
Name: goblin_attack
[X] Enable when the game begins
Script:
-> If: [object is visible] [object] goblin
--> Then:
--> Print Message:
--> Print Message: The goblin attacked you!
--> Set variable goblin_dice_result = [expression] DiceRoll (goblin.attack_dice_number + "d" + goblin.attack_dice_sides)
--> Set variable goblin_damage = [expression] goblin_dice_result * goblin.atk - player.def_stat
--> Print [expression]: "The goblin did " + goblin_damage + " damage!"
--> If: [expression] goblin_damage < 0
---> Then:
---> Set variable goblin_damage = [expression] 0

--> Print [expression]: "Attack report: The goblin attacked with " + goblin.attack_dice_number + "D" + goblin.attack_dice_sides + " dice roll x " + goblin.atk + " bonus - enemy resistance (" + player.def_stat + ")."
--> If [expression]: goblin_damage > player.current_hp or goblin_damage = player.current_hp
---> Then:
---> Set variable player.current_hp = [expression] 0
---> Print [message]:
---> Print [message]: You were killed by the goblin!
---> Finish the game.
---> Else:
---> Set variable player.current_health = [expression] player.current_hp - goblin_damage
---> Print [message]: You survived the attack!

to this:

Turn Script
Name: goblin_attack
[X] Enable when the game begins
Script:
-> If: [object is visible] [object] goblin
--> Then:
--> Print Message:
--> Print Message: The goblin attacked you!
--> Set variable goblin_dice_result = [expression] DiceRoll (goblin.attack_dice_number + "d" + goblin.attack_dice_sides)
--> Set variable goblin_damage = [expression] goblin_dice_result * goblin.atk - player.def_stat
--> If: [expression] goblin_damage < 0
---> Then:
---> Set variable goblin_damage = [expression] 0
--> Print [expression]: "The goblin did " + goblin_damage + " damage!"

--> Print [expression]: "Attack report: The goblin attacked with " + goblin.attack_dice_number + "D" + goblin.attack_dice_sides + " dice roll x " + goblin.atk + " bonus - enemy resistance (" + player.def_stat + ")."
--> If [expression]: goblin_damage > player.current_hp or goblin_damage = player.current_hp
---> Then:
---> Set variable player.current_hp = [expression] 0
---> Print [message]:
---> Print [message]: You were killed by the goblin!
---> Finish the game.
---> Else:
---> Set variable player.current_health = [expression] player.current_hp - goblin_damage
---> Print [message]: You survived the attack!

-----------------

Edit:

I didn't realize you didn't post your entire game code, so I can only try to guess~help you with the out of order with your turns

so...

by doing this:

Object (left pane, click on it to highlight it) -> very top of screen (File ~ etc ~ Add ~ etc), click on the "Add" and choose "turn script"

this will always run whatever is in it, always effecting the game.pov and the game as a whole if it can be done so.

this is how we can create "game turns" and then we can use these turns for other things, as each action that the game player does, causes a game turn to go by (to increase)

<turnscript name="game_turns_turnscript">
game.turns = game turns + 1
</turnscript>

<game name="blah blah blah">
<etc blah blah>
<start type="script">
character_creation_function
</start>
<turns type="int">0</turns>
<etc blah blah>
</game>


if we were to do:

(for example) room (left pane, click on it to highlight it) -> very top of screen (File ~ etc ~ Add ~ etc), click on the "Add" and choose "turn script"

then we'd create a turnscript that is just for that room, and if we add in the turns code for it, it operate as a "room turns".

<turnscript name="room_turns_turnscript">
room.turns = room turns + 1
</turnscript>

<object name="room">
<inherit name="editor_room" />
<turns type="int">0</turns>
<object name="player">
<inherit name="editor_object" />
<inherit name="editor_player" />
</object>
</object>


but it gets more complicated:

<turnscript name="hp_0_and_game_turns_and_death_and revival_spell_turnscript">

game.pov.cur_hp = 0

<game_pov_death_script type="script>
if (game.pov.cur_hp = 0) {
msg ("You've died!")
msg ("GAME OVER")
finish
}
</game>

game.turns = game turns + 1

<revival_spell type="script">
if (game.pov.cur_hp = 0) {
game.pov.cur_hp = 0 + game.pov.max_hp
}
</revival_spell type>

</turnscript>


this would mean that I die (if I have 0 hp) before the next turn happens, and thus before the revival spell can heal back my hp

and you'd die also if it was in this order too:

<turnscript name="hp_0_and_game_turns_and_death_and revival_spell_turnscript">

game.pov.cur_hp = 0

<game_pov_death_script type="script>
if (game.pov.cur_hp = 0) {
msg ("You've died!")
msg ("GAME OVER")
finish
}
</game_pov_death_script>

<revival_spell_script type="script">
if (game.pov.cur_hp = 0) {
game.pov.cur_hp = 0 + game.pov.max_hp
}
</revival_spell_script>

game.turns = game turns + 1

</turnscript>


due to the finish of the game, nullifies the revival spell that occurs afterward, before the next turn

however, if I change the order around, to this:

<turnscript name="hp_0_and_game_turns_and_death_and revival_spell_turnscript">

game.pov.cur_hp = 0

<revival_spell_script type="script">
if (game.pov.cur_hp = 0) {
game.pov.cur_hp = 0 + game.pov.max_hp
}
</revival_spell_script>

<game_pov_death_script type="script>
if (game.pov.cur_hp = 0) {
msg ("You've died!")
msg ("GAME OVER")
finish
}
</game_pov_death_script>

game.turns = game turns + 1

</turnscript>


now, even though I have 0 HP, the revival spell is executed first, before the death script and the finishing~ending of the game, and so thus after the revival spell, you now got full HP back, and thus you don't die obviously.

(if you are still dying, than I need to add in the "OnReady" code to the death_script so that it waits for the revival spell to finish before it, the death_script, starts to be executed~run, lol)